diff --git a/frontend/package.json b/frontend/package.json index 472e9481..a8a2b568 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,7 +8,7 @@ "build": "tsc && vite build", "check": "tsc --noEmit", "preview": "vite preview", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 110", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 30", "lint:fix": "eslint . --ext ts,tsx --fix", "lint:i18n": "LINT_I18N=true eslint . --ext ts,tsx --max-warnings 0", "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"", diff --git a/frontend/src/hooks/useJsonPatchWsStream.ts b/frontend/src/hooks/useJsonPatchWsStream.ts index eee09f9c..e6c23ec9 100644 --- a/frontend/src/hooks/useJsonPatchWsStream.ts +++ b/frontend/src/hooks/useJsonPatchWsStream.ts @@ -26,7 +26,7 @@ interface UseJsonPatchStreamResult { /** * Generic hook for consuming WebSocket streams that send JSON messages with patches */ -export const useJsonPatchWsStream = ( +export const useJsonPatchWsStream = ( endpoint: string | undefined, enabled: boolean, initialData: () => T, @@ -117,16 +117,17 @@ export const useJsonPatchWsStream = ( ? deduplicatePatches(patches) : patches; - if (!filtered.length || !dataRef.current) return; + const current = dataRef.current; + if (!filtered.length || !current) return; // Deep clone the current state before mutating it - dataRef.current = structuredClone(dataRef.current); + const next = structuredClone(current); // Apply patch (mutates the clone in place) - applyPatch(dataRef.current as any, filtered); + applyPatch(next, filtered); - // React re-render: dataRef.current is already a new object - setData(dataRef.current); + dataRef.current = next; + setData(next); } // Handle finished messages ({finished: true}) diff --git a/frontend/src/vscode/bridge.ts b/frontend/src/vscode/bridge.ts index 3a9eeda0..6e04c53d 100644 --- a/frontend/src/vscode/bridge.ts +++ b/frontend/src/vscode/bridge.ts @@ -152,15 +152,15 @@ function cutFromInput(el: HTMLInputElement | HTMLTextAreaElement) { el.value = before + after; el.setSelectionRange(start, start); } - const ie = - typeof (window as any).InputEvent !== 'undefined' - ? new (window as any).InputEvent('input', { + const ie: Event = + typeof InputEvent === 'function' + ? new InputEvent('input', { bubbles: true, composed: true, inputType: 'deleteByCut', }) : new Event('input', { bubbles: true }); - el.dispatchEvent(ie as Event); + el.dispatchEvent(ie); el.dispatchEvent(new Event('change', { bubbles: true })); } } @@ -182,16 +182,16 @@ function pasteIntoInput( el.setSelectionRange(caret, caret); } el.focus(); - const ie = - typeof (window as any).InputEvent !== 'undefined' - ? new (window as any).InputEvent('input', { + const ie: Event = + typeof InputEvent === 'function' + ? new InputEvent('input', { bubbles: true, composed: true, inputType: 'insertFromPaste', data: text, }) : new Event('input', { bubbles: true }); - el.dispatchEvent(ie as Event); + el.dispatchEvent(ie); el.dispatchEvent(new Event('change', { bubbles: true })); } @@ -216,7 +216,7 @@ function insertTextAtCaretGeneric(text: string) { } else { try { document.execCommand('insertText', false, text); - (el as any).dispatchEvent?.(new Event('input', { bubbles: true })); + el.dispatchEvent(new Event('input', { bubbles: true })); } catch { (el as HTMLElement).innerText += text; }