diff --git a/ui/desktop/eslint.config.js b/ui/desktop/eslint.config.js index dad0b8f625..35b9090a6d 100644 --- a/ui/desktop/eslint.config.js +++ b/ui/desktop/eslint.config.js @@ -101,8 +101,6 @@ module.exports = [ MediaStream: 'readonly', Blob: 'readonly', FormData: 'readonly', - Worker: 'readonly', - MessageEvent: 'readonly', }, }, plugins: { diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 6153bc65ef..feb7c4832c 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -363,15 +363,11 @@ export function AppInner() { }); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.addEventListener('add-active-session', handleAddActiveSession as any); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.addEventListener('clear-initial-message', handleClearInitialMessage as any); + window.addEventListener('add-active-session', handleAddActiveSession); + window.addEventListener('clear-initial-message', handleClearInitialMessage); return () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.removeEventListener('add-active-session', handleAddActiveSession as any); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.removeEventListener('clear-initial-message', handleClearInitialMessage as any); + window.removeEventListener('add-active-session', handleAddActiveSession); + window.removeEventListener('clear-initial-message', handleClearInitialMessage); }; }, []); diff --git a/ui/desktop/src/components/BaseChat.tsx b/ui/desktop/src/components/BaseChat.tsx index 95a996fe46..17930bdd05 100644 --- a/ui/desktop/src/components/BaseChat.tsx +++ b/ui/desktop/src/components/BaseChat.tsx @@ -70,23 +70,17 @@ function BaseChatContent({ const [searchParams] = useSearchParams(); const scrollRef = useRef(null); const chatInputRef = useRef(null); - const disableAnimation = location.state?.disableAnimation || false; const [hasStartedUsingRecipe, setHasStartedUsingRecipe] = React.useState(false); const [hasNotAcceptedRecipe, setHasNotAcceptedRecipe] = useState(); const [hasRecipeSecurityWarnings, setHasRecipeSecurityWarnings] = useState(false); - const isMobile = useIsMobile(); const { state: sidebarState } = useSidebar(); const setView = useNavigation(); const { markSessionActive } = useSessionStatusContext(); - const contentClassName = cn('pr-1 pb-10', (isMobile || sidebarState === 'collapsed') && 'pt-11'); - - // Use shared file drop const { droppedFiles, setDroppedFiles, handleDrop, handleDragOver } = useFileDrop(); - // Mark session as active when viewing it (only if this is the active session) useEffect(() => { if (sessionId && isActiveSession) { markSessionActive(sessionId); @@ -119,9 +113,7 @@ function BaseChatContent({ onStreamFinish, }); - // Emit session status updates for the sidebar useEffect(() => { - // Map ChatState to StreamState let streamState: 'idle' | 'loading' | 'streaming' | 'error' = 'idle'; if (chatState === ChatState.LoadingConversation) { streamState = 'loading'; @@ -313,10 +305,8 @@ function BaseChatContent({ shouldStartAgent?: boolean; editedMessage?: string; }>; - const { newSessionId, shouldStartAgent, editedMessage } = customEvent.detail; - - // Dispatch session-created event to refresh the sidebar window.dispatchEvent(new CustomEvent('session-created')); + const { newSessionId, shouldStartAgent, editedMessage } = customEvent.detail; const params = new URLSearchParams(); params.set('resumeSessionId', newSessionId); diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index ebc0242a27..47e81fbc18 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -263,35 +263,27 @@ export default function ChatInput({ }, }); - // Get dictation settings to check configuration status const { settings: dictationSettings } = useDictationSettings(); - - // Refs - declare early since they're used in useEffects const internalTextAreaRef = useRef(null); const textAreaRef = inputRef || internalTextAreaRef; const timeoutRefsRef = useRef>>(new Set()); - // Update internal value when initialValue changes useEffect(() => { setValue(initialValue); setDisplayValue(initialValue); - - // Use a functional update to get the current pastedImages - // and perform cleanup. This avoids needing pastedImages in the deps. setPastedImages((currentPastedImages) => { currentPastedImages.forEach((img) => { if (img.filePath) { window.electron.deleteTempFile(img.filePath); } }); - return []; // Return a new empty array + return []; }); - // Reset history index when input is cleared setHistoryIndex(-1); setIsInGlobalHistory(false); setHasUserTyped(false); - }, [initialValue]); // Keep only initialValue as a dependency + }, [initialValue]); // Handle recipe prompt updates useEffect(() => { @@ -305,7 +297,6 @@ export default function ChatInput({ } }, [recipeAccepted, initialPrompt, messages.length, textAreaRef]); - // State to track if the IME is composing (i.e., in the middle of Japanese IME input) const [isComposing, setIsComposing] = useState(false); const [historyIndex, setHistoryIndex] = useState(-1); const [savedInput, setSavedInput] = useState(''); diff --git a/ui/desktop/src/components/ChatSessionsContainer.tsx b/ui/desktop/src/components/ChatSessionsContainer.tsx index 20f0e9a562..3afac2ce8d 100644 --- a/ui/desktop/src/components/ChatSessionsContainer.tsx +++ b/ui/desktop/src/components/ChatSessionsContainer.tsx @@ -19,12 +19,10 @@ export default function ChatSessionsContainer({ const [searchParams] = useSearchParams(); const currentSessionId = searchParams.get('resumeSessionId') ?? undefined; - // If no current session, don't render anything if (!currentSessionId) { return null; } - // Check if the current session is in our active sessions const isActiveSession = activeSessions.some((s) => s.sessionId === currentSessionId); // If the current session isn't in active sessions, we need to render it anyway diff --git a/ui/desktop/src/vite-env.d.ts b/ui/desktop/src/vite-env.d.ts index 6793cb346a..fa8fbcc167 100644 --- a/ui/desktop/src/vite-env.d.ts +++ b/ui/desktop/src/vite-env.d.ts @@ -50,6 +50,19 @@ declare global { interface Window { isCreatingRecipe?: boolean; } + + // Augment WindowEventMap to include custom events + interface WindowEventMap { + 'add-active-session': CustomEvent<{ + sessionId: string; + initialMessage?: string; + }>; + 'clear-initial-message': CustomEvent<{ + sessionId: string; + }>; + responseStyleChanged: CustomEvent; + 'session-created': CustomEvent; + } } export {};