From 5a40e4b00a416ef86f14eda45c7e7827fce593d3 Mon Sep 17 00:00:00 2001 From: Richard R Date: Wed, 21 Jan 2026 13:17:57 -0700 Subject: [PATCH] fix: improve word highlight cleanup in PDFViewer and update test - Add cleanup function to prevent memory leaks in word highlighting - Update test to allow blocks ending with ., !, or ? for better accuracy --- package.json | 2 +- src/components/PDFViewer.tsx | 14 +++++++++----- tests/unit/nlp.spec.ts | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 25d17db..735c6aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openreader-webui", - "version": "v1.2.0", + "version": "v1.2.1", "private": true, "scripts": { "dev": "next dev --turbopack -p 3003", diff --git a/src/components/PDFViewer.tsx b/src/components/PDFViewer.tsx index 94ac3f6..6668299 100644 --- a/src/components/PDFViewer.tsx +++ b/src/components/PDFViewer.tsx @@ -138,6 +138,8 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) { // Word-level highlight layered on top of the block highlight useEffect(() => { + clearWordHighlightTimeouts(); + if (!pdfHighlightEnabled || !pdfWordHighlightEnabled) { clearWordHighlights(); return; @@ -149,8 +151,7 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) { } const wordEntry = - currentSentenceAlignment && - currentWordIndex < currentSentenceAlignment.words.length + currentSentenceAlignment && currentWordIndex < currentSentenceAlignment.words.length ? currentSentenceAlignment.words[currentWordIndex] : undefined; const wordText = wordEntry?.text || null; @@ -160,8 +161,6 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) { return; } - clearWordHighlightTimeouts(); - const seq = ++wordHighlightSeqRef.current; const isLayoutChange = layoutKey !== lastWordLayoutKeyRef.current; lastWordLayoutKeyRef.current = layoutKey; @@ -188,13 +187,18 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) { } }; + const cleanup = () => { + clearWordHighlightTimeouts(); + }; + if (isLayoutChange) { clearWordHighlights(); scheduleWordTimeout(() => tryApplyWord(0), 250); - return; + return cleanup; } tryApplyWord(0); + return cleanup; }, [ currentWordIndex, currentSentence, diff --git a/tests/unit/nlp.spec.ts b/tests/unit/nlp.spec.ts index becc95e..14dbd86 100644 --- a/tests/unit/nlp.spec.ts +++ b/tests/unit/nlp.spec.ts @@ -104,7 +104,7 @@ test.describe('splitTextToTtsBlocks', () => { for (const block of result) { expect(block.length).toBeGreaterThan(0); expect(block.length).toBeLessThanOrEqual(450); - expect(block.endsWith('.')).toBe(true); + expect(block).toMatch(/[.!?]$/); } });