fix: resolve CI lint errors in Sidebar, TypingIndicator, and useGateway
- Sidebar: replace useEffect setState with callback pattern for filter reset - TypingIndicator: initialize useRef with 0 instead of impure Date.now() - TypingIndicator: remove redundant setElapsed(0) from mount effect - useGateway: remove unused eslint-disable directive
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useMemo, useRef, useEffect } from 'react';
|
import { useState, useMemo, useRef, useEffect, useCallback } from 'react';
|
||||||
import { X, Sparkles, Search } from 'lucide-react';
|
import { X, Sparkles, Search } from 'lucide-react';
|
||||||
import type { Session } from '../types';
|
import type { Session } from '../types';
|
||||||
import { useT } from '../hooks/useLocale';
|
import { useT } from '../hooks/useLocale';
|
||||||
@@ -31,8 +31,10 @@ export function Sidebar({ sessions, activeSession, onSwitch, open, onClose }: Pr
|
|||||||
return () => window.removeEventListener('keydown', handler);
|
return () => window.removeEventListener('keydown', handler);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Reset focus index when filter changes
|
const updateFilter = useCallback((value: string) => {
|
||||||
useEffect(() => { setFocusIdx(-1); }, [filter]);
|
setFilter(value);
|
||||||
|
setFocusIdx(-1);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const filtered = useMemo(() => {
|
const filtered = useMemo(() => {
|
||||||
if (!filter.trim()) return sessions;
|
if (!filter.trim()) return sessions;
|
||||||
@@ -70,14 +72,14 @@ export function Sidebar({ sessions, activeSession, onSwitch, open, onClose }: Pr
|
|||||||
ref={searchRef}
|
ref={searchRef}
|
||||||
type="text"
|
type="text"
|
||||||
value={filter}
|
value={filter}
|
||||||
onChange={e => setFilter(e.target.value)}
|
onChange={e => updateFilter(e.target.value)}
|
||||||
placeholder={t('sidebar.search')}
|
placeholder={t('sidebar.search')}
|
||||||
aria-label={t('sidebar.search')}
|
aria-label={t('sidebar.search')}
|
||||||
className="w-full pl-8 pr-3 py-1.5 rounded-xl border border-white/8 bg-zinc-800/30 text-xs text-zinc-300 placeholder:text-zinc-500 outline-none focus:ring-1 focus:ring-cyan-400/30 transition-all"
|
className="w-full pl-8 pr-3 py-1.5 rounded-xl border border-white/8 bg-zinc-800/30 text-xs text-zinc-300 placeholder:text-zinc-500 outline-none focus:ring-1 focus:ring-cyan-400/30 transition-all"
|
||||||
/>
|
/>
|
||||||
{filter && (
|
{filter && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setFilter('')}
|
onClick={() => updateFilter('')}
|
||||||
className="absolute right-2 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-300"
|
className="absolute right-2 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-300"
|
||||||
>
|
>
|
||||||
<X size={12} />
|
<X size={12} />
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ function formatElapsed(seconds: number): string {
|
|||||||
export function TypingIndicator() {
|
export function TypingIndicator() {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const [elapsed, setElapsed] = useState(0);
|
const [elapsed, setElapsed] = useState(0);
|
||||||
const startRef = useRef(Date.now());
|
const startRef = useRef(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
startRef.current = Date.now();
|
startRef.current = Date.now();
|
||||||
setElapsed(0);
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
setElapsed(Math.floor((Date.now() - startRef.current) / 1000));
|
setElapsed(Math.floor((Date.now() - startRef.current) / 1000));
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|||||||
@@ -314,7 +314,6 @@ export function useGateway() {
|
|||||||
const stored = getStoredCredentials();
|
const stored = getStoredCredentials();
|
||||||
if (stored) {
|
if (stored) {
|
||||||
// Init on mount — setupClient sets state as part of establishing the connection
|
// Init on mount — setupClient sets state as part of establishing the connection
|
||||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
||||||
setupClient(stored.url, stored.token);
|
setupClient(stored.url, stored.token);
|
||||||
} else {
|
} else {
|
||||||
setAuthenticated(false);
|
setAuthenticated(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user