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
This commit is contained in:
Richard R 2026-01-21 13:17:57 -07:00
parent c28c074e43
commit 5a40e4b00a
3 changed files with 11 additions and 7 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "openreader-webui", "name": "openreader-webui",
"version": "v1.2.0", "version": "v1.2.1",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev --turbopack -p 3003", "dev": "next dev --turbopack -p 3003",

View file

@ -138,6 +138,8 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
// Word-level highlight layered on top of the block highlight // Word-level highlight layered on top of the block highlight
useEffect(() => { useEffect(() => {
clearWordHighlightTimeouts();
if (!pdfHighlightEnabled || !pdfWordHighlightEnabled) { if (!pdfHighlightEnabled || !pdfWordHighlightEnabled) {
clearWordHighlights(); clearWordHighlights();
return; return;
@ -149,8 +151,7 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
} }
const wordEntry = const wordEntry =
currentSentenceAlignment && currentSentenceAlignment && currentWordIndex < currentSentenceAlignment.words.length
currentWordIndex < currentSentenceAlignment.words.length
? currentSentenceAlignment.words[currentWordIndex] ? currentSentenceAlignment.words[currentWordIndex]
: undefined; : undefined;
const wordText = wordEntry?.text || null; const wordText = wordEntry?.text || null;
@ -160,8 +161,6 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
return; return;
} }
clearWordHighlightTimeouts();
const seq = ++wordHighlightSeqRef.current; const seq = ++wordHighlightSeqRef.current;
const isLayoutChange = layoutKey !== lastWordLayoutKeyRef.current; const isLayoutChange = layoutKey !== lastWordLayoutKeyRef.current;
lastWordLayoutKeyRef.current = layoutKey; lastWordLayoutKeyRef.current = layoutKey;
@ -188,13 +187,18 @@ export function PDFViewer({ zoomLevel }: PDFViewerProps) {
} }
}; };
const cleanup = () => {
clearWordHighlightTimeouts();
};
if (isLayoutChange) { if (isLayoutChange) {
clearWordHighlights(); clearWordHighlights();
scheduleWordTimeout(() => tryApplyWord(0), 250); scheduleWordTimeout(() => tryApplyWord(0), 250);
return; return cleanup;
} }
tryApplyWord(0); tryApplyWord(0);
return cleanup;
}, [ }, [
currentWordIndex, currentWordIndex,
currentSentence, currentSentence,

View file

@ -104,7 +104,7 @@ test.describe('splitTextToTtsBlocks', () => {
for (const block of result) { for (const block of result) {
expect(block.length).toBeGreaterThan(0); expect(block.length).toBeGreaterThan(0);
expect(block.length).toBeLessThanOrEqual(450); expect(block.length).toBeLessThanOrEqual(450);
expect(block.endsWith('.')).toBe(true); expect(block).toMatch(/[.!?]$/);
} }
}); });