diff --git a/frontend/editor/src/core/tools/pdfTextEditor/v2/charcode/BackendResolver.ts b/frontend/editor/src/core/tools/pdfTextEditor/v2/charcode/BackendResolver.ts index 95658dc90d..94ed5b2eb5 100644 --- a/frontend/editor/src/core/tools/pdfTextEditor/v2/charcode/BackendResolver.ts +++ b/frontend/editor/src/core/tools/pdfTextEditor/v2/charcode/BackendResolver.ts @@ -240,10 +240,12 @@ function maybeAutoPrefetch( } // Stop the per-keystroke prefetch storm. resolve looks these - // chars up under the QUERIED font, not perCharFont. + // chars up under the QUERIED font, not perCharFont. Use the + // TTL'd null: this font was never actually asked, so a permanent + // null would kill the pair for the rest of the session. if (perCharFont !== fontPtr) { for (const ch of fontChars) { - charCache.set(cacheKey(fontPtr, ch), null); + setTransientNull(cacheKey(fontPtr, ch)); } } } diff --git a/frontend/editor/src/core/tools/pdfTextEditor/v2/commands/editTextHelpers.ts b/frontend/editor/src/core/tools/pdfTextEditor/v2/commands/editTextHelpers.ts index 64f133cadb..d8362b15a5 100644 --- a/frontend/editor/src/core/tools/pdfTextEditor/v2/commands/editTextHelpers.ts +++ b/frontend/editor/src/core/tools/pdfTextEditor/v2/commands/editTextHelpers.ts @@ -140,8 +140,12 @@ export function charcodesResolveFully( } catch { ok = false; } - perFont.set(ch, ok); - if (!ok) return false; + // Only memoise a POSITIVE result. A miss here can simply mean the + // charcode cache was cold or the backend was briefly unreachable, and + // caching that as "this font cannot encode this character" made the + // failure permanent for the session. + if (ok) perFont.set(ch, true); + else return false; } return true; } diff --git a/frontend/editor/src/core/tools/pdfTextEditor/v2/components/FindBar.tsx b/frontend/editor/src/core/tools/pdfTextEditor/v2/components/FindBar.tsx index 76e4c8ec15..24f4830cd1 100644 --- a/frontend/editor/src/core/tools/pdfTextEditor/v2/components/FindBar.tsx +++ b/frontend/editor/src/core/tools/pdfTextEditor/v2/components/FindBar.tsx @@ -13,6 +13,7 @@ import type { MatchOptions, TextMatch, } from "@app/tools/pdfTextEditor/v2/util/textMatching"; +import { ensureAllPagesRead } from "@app/tools/pdfTextEditor/v2/hooks/useDocumentLoader"; import type { EditorStore } from "@app/tools/pdfTextEditor/v2/store/EditorStore"; import type { PageSnapshot, @@ -60,6 +61,14 @@ export function FindBar({ store, pages, onClose }: FindBarProps) { inputRef.current?.focus(); }, []); + // Opening Find is a document-wide request, so pull in every page that lazy + // loading has not read yet. Yield first: the read is synchronous, and on a + // long document it would otherwise block before the bar has painted. + useEffect(() => { + const id = setTimeout(() => ensureAllPagesRead(store), 0); + return () => clearTimeout(id); + }, [store]); + const options: MatchOptions = useMemo( () => ({ matchCase, wholeWord, ignoreAccents }), [matchCase, wholeWord, ignoreAccents],