Files
readest/apps/readest-app/.claude/memory/MEMORY.md
T
Huang Xin 27fa9ab226 chore(i18n): translate new strings; commit pending agent memory notes (#4430)
Translate 4 new keys across all 33 locales:
- Send
- Book file is not available locally
- Failed to send book
- Highlight Current Sentence

Also commit pending .claude/memory bug-fix notes.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 19:01:47 +02:00

12 KiB
Raw Blame History

Readest Project Memory

Key Reference Documents

Paginator Scroll Knowledge

  • Issue #4112 scroll-anchoring — RESOLVED (PR #4349). Scroll-anchoring suppressed at scrollTop 0 when prepending a section in scrolled mode; fix patterns (prepend compensation, eager backward preload, no-blank nav) + test & dev-server gotchas
  • Reading ruler line/column-aware — ruler snaps to real lines; multi-column band spans one column; Range.getClientRects() returns tall block boxes that must be dropped; iframe frame-offset mapping; synthetic-key throttling
  • TOC expand + auto-scroll — #4059 collapse-by-default policy in tocTree.ts; pinned-sidebar mounts before progress → dynamic expansion breaks scroll-to-current via (1) spurious onScroll clearing pending and (2) Virtuoso scrollToIndex landing short after row growth (re-assert on rAF)
  • BooknoteView auto-scroll (#4352) — virtualizing the annotation/bookmark list dropped auto-scroll-to-nearest; two paths (reload: OverlayScrollbars resets scrollTop → re-apply in initialized via ref; tab-switch: synchronous scrollToIndex on fresh-mounted list wedges Virtuoso → use initialTopMostItemIndex + skip-gate). Mirrors TOCView. Includes dev-server/Fast-Refresh/screenshot-vs-DOM verification gotchas
  • Swipe page-turn bg flash — white↔black flash on swipe+animation only; #background was static screen-space and didn't track content during drag/snap; fix = sliding per-view full-bleed segments (computeBackgroundSegments) rebuilt on scroll + per-rAF synced to the view transform during snap
  • Duokan fullscreen cover hidden in scroll mode — #4379 data-duokan-page-fullscreen cover pinned position:absolute height:100% collapses against auto-height scroll container; gate fullscreen on this.#column + reset stale absolute props on toggle (setImageSize in paginator.js)
  • Paginated texture occlusion — #4399 host .foliate-viewer::before texture absent in paginated (shown in scrolled); opaque #background container (= fallbackBg) from the swipe-flash fix occludes it; shared textureAwareBackground helper + hasTexture ? '' : fallbackBg container
  • Background overflows column (#4394, PR #4429) — paginated page bg stretched into the outer --_outer-min gutter → mixed cover/title 2-up spread shifted off-centre (~250px at 1920px). KEEP the grid (--_outer-min keeps margins symmetric); fix = clamp computeBackgroundSegments to [containerStart,containerEnd] (Math.max/Math.min) so bg stays in its column. 2 wrong tries first (bleed-gating, "page shouldn't be yellow"); foliate submodule needs dev-server RESTART to pick up edits

Critical Files (Most Bug-Prone)

  • src/utils/style.ts - Central EPUB CSS transformation hub (14+ bug fixes)
  • packages/foliate-js/paginator.js - Page layout, image sizing, backgrounds
  • src/services/tts/TTSController.ts - TTS state machine, section tracking
  • src/hooks/useSafeAreaInsets.ts - Safe area inset management
  • src/app/reader/components/FoliateViewer.tsx - Reader view orchestration
  • src/app/reader/components/annotator/Annotator.tsx - Annotation lifecycle

Sync Notes

  • KOSync CFI spine resolution — convert via the CFI's own spine (getXPointerFromCFI/getCFIFromXPointer), never new XCFI(primaryDoc, primaryIndex); primaryIndex lags during scroll → spine-mismatch throw
  • Empty-start CFI sync bugepubcfi(/6/24!/4,,/20/1:58) (empty-start range) from the cfi-inert skip-link transitional window; jumps to wrong section end; isMalformedLocationCfi → discard the synced value in useProgressSync (NOT the local open path); foliate fix doesn't repair already-synced values
  • Custom fonts disappear on cloud sync (#4410) — CRDT remove-wins: re-import-after-delete needs a reincarnation token or the pull re-applies the tombstone; addFont/addTexture minted none; fix mirrors dictionary (both cases) + OPDS token style; coverage matrix per kind

Testing

  • Tauri Rust↔JS parser parity tests — #4369 native Rust EPUB/MOBI parser; how to cross-check vs foliate-js in the .tauri.test.ts WebView suite (CWD disk path for Rust, Vite URL for JS, normalizer-based compare, cover presence-only, desc whitespace-collapse); the dcterms:modifiedpublished divergence fix

Build & Vendoring

  • pdfjs vendor wasm decoders — scanned PDFs blank in CI build only (0.11.2 regression); pdfjs 5.7.x moved JBIG2 to jbig2.wasm, copy-pdfjs-wasm allow-list dropped it; cpx no-errors on empty glob; local stale public/vendor (gitignored, not refreshed by tauri build) masked it; fix = copy wasm/*

Platform Compat

  • Window-state sanitizer (#4398) — Windows launch crash (WebView2 0x80070057) from invalid .window-state.json (-32000 minimized sentinel / 0×0); our plugin already has upstream #253 fix so bad files are stale; defense-in-depth window-state-sanitizer plugin registered BEFORE window-state (plugin init = registration order); coord threshold -16000 (~halfway to the -32000 sentinel; real desktops sit a few thousand px off origin) keeps multi-monitor negatives

Feature Notes

  • Manage Cache + iOS container layout'Cache' base = Library/Caches/<bundle> only (not all of Caches); iOS Documents/Inbox cleared too; WebKit cache + tmp out of reach; never touch App Support
  • D-pad Navigation — Android TV remote / keyboard arrow navigation design, key files, and pitfalls
  • Cloudflare Workers WebSocket — use fetch() Upgrade pattern (not ws npm); CF delivers binary frames as Blob (must serialize async decodes)
  • Share-a-Book Feature (in progress) — locked decisions for the /s/{token} share-link feature; plan at ~/.claude/plans/ok-we-will-learn-cosmic-acorn.md
  • readest.koplugin i18n — gettext loader at apps/readest.koplugin/i18n.lua, .po catalog at locales/<i18next-code>/translation.po, extract/apply scripts in scripts/
  • koplugin cover upload — #4374 uploadBook only shipped cached cloud covers; local-origin books uploaded blank. Fix = extractLocalCover via FileManagerBookInfo:getCoverImage(nil, file)writeToFile(path,"png"). KOReader checkout at /Users/chrox/dev/koreader

Patterns

  • Virtuoso + OverlayScrollbars — useOverlayScrollbars hook integration for overlay scrollbars on mobile webviews
  • Design system → DESIGN.md — codify recurring UI/UX rules in apps/readest-app/DESIGN.md; never pl/pr/ml/mr/text-left/text-right (RTL); §5 boxed list anatomy has uniform min-h-14 rows and chromeless controls

Reader UI Fixes

  • Android image callout freeze — long-press <img> fires WebView native callout that collides with app touch handlers → whole-app freeze; -webkit-touch-callout: none doesn't inherit so put .no-context-menu on an ancestor of the image (.no-context-menu img rule in globals.css); seen on book covers (#4345) + image preview/zoom (#4420, ImageViewer.tsx)
  • ProgressBar focus-ring line (#4397) — decorative .progressinfo footer was tabIndex={-1} → Android long-press focused it → stray content-width focus-ring line at the bottom every page; fix = drop tabIndex (role='presentation' must not be focusable); ffmpeg-the-video debugging + live-browser :focus-visible confirmation
  • Table dark-mode tint regression (#4419)blockquote, table * color-mix tint in getColorStyles must stay gated on overrideColor (gate added #2377, removed #4055, re-broke → #4419); safe now that #4392 light-bg rewriters handle #4028 zebra legibility; SAME rule paints vertical-TOC .space/▉ spacer cells (▉ U+2589 = blank glyph, contours=0) → "spacing changes" symptom; both fixed by the gate

Library Fixes

  • Tauri menu append race (#4389) — un-awaited Menu.append() (async IPC) in BookshelfItem.tsx → context-menu items shuffle order every open (native only, invisible in jsdom); fix = single await Menu.new({ items }) of ordered MenuItemOptions; order/inclusion extracted to pure getBookContextMenuItemIds for unit testing
  • TXT author recognition (#4390) — 【】-titled Chinese web-novels show author missing/garbage; they're TXT→EPUB (title==full filename is the tell, check txt.ts not foliate-js); extractTxtFilenameMetadata only handled 《》 + greedy header capture grabbed metadata blobs; fix = parseLabeledAuthor for any filename + isPlausibleAuthorName guard

Architecture Notes

  • foliate-js is a git submodule at packages/foliate-js/
  • Multiview paginator: loads adjacent sections in background, multiple View/Overlayer instances per book
  • Style overrides: getLayoutStyles() (always), getColorStyles() (when overriding color)
  • transformStylesheet() does regex-based EPUB CSS rewriting at load time
  • TTS uses independent section tracking (#ttsSectionIndex) decoupled from view
  • Safe area insets flow: Native plugin -> useSafeAreaInsets hook -> component styles
  • Dropdown menus use DropdownContext (not blur-based) for screen reader compat
  • Foliate touch-listener capture phase — to suppress reader gestures from the app, use {capture:true}; the paginator registers bubble-phase doc listeners first (during view.open())
  • iframe cross-realm instanceof — app-bundle code (style.ts, iframeEventHandlers.ts) runs in top realm; iframeEl instanceof Element is ALWAYS false → guards silently drop all iframe elements (passes jsdom, dead in app). Duck-type 'closest' in target instead. Bit PR #4391's touch routing + applyTableStyle dedupe

Workflow