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:
Nicolas Varrot
2026-02-12 11:27:42 +00:00
parent 908dbb4a60
commit 6734b54389
3 changed files with 8 additions and 8 deletions

View File

@@ -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} />

View File

@@ -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);

View File

@@ -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);