c23c21d37d
* feat(kosync): compare reflowable conflicts via locally-resolved CFI percentage KOReader reports progress as a percentage from its own pagination, which isn't directly comparable to Readest's progress. For reflowable books, resolve the remote XPointer to a local CFI and compute the equivalent fraction (getRemoteLocalFraction), comparing that against the local percentage and falling back to the reported percentage only when it can't be resolved locally (non-XPointer progress or a missing section). The resolved fraction also drives the conflict-dialog remote preview so the shown value matches what was compared. Loosen the conflict threshold to 0.01 when the remote progress was last pushed from this same device (remote.device_id === local deviceId), so sub-page drift between a push and the next pull doesn't prompt. Render sync percentages with 2 decimals via formatProgressPercentage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(reader): correct scrolled-mode reopen drift over background-image sections Bump the foliate-js submodule to include the scrolled-mode reopen drift fix for sections with background images, and add a browser regression test plus its EPUB fixture. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(library): redirect to login on pull-to-refresh when signed out Guard the pull-to-refresh handlers so an unauthenticated user is sent to the login screen instead of attempting a library pull and OPDS subscription check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(memory): add kosync conflict + toc/scrolled-restore notes Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(reader): prevent CFI crash on inert-only section bodies Reopening/paginating across a background-image or otherwise content-less section could crash with "Cannot destructure property 'nodeType' of 'param' as it is undefined" in foliate's fromRange, aborting the relocate so the reading position was never saved. Bumps the foliate-js submodule to 569cc06 (visible-range walker skips cfi-inert skip-links; isTextNode/isElementNode are null-safe) and adds a regression test reproducing the exact crash. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(kosync): keep auto-push working when a pull finds no real conflict In the 'prompt' strategy, pullProgress set syncState to 'conflict' unconditionally on every pull that returned remote progress, even when promptedSync found no actual difference. Since auto-push only runs while 'synced', and a pull fires on every book-open and window re-activation, progress stopped being pushed. promptedSync now returns whether a real conflict was surfaced, and pullProgress only stays in 'conflict' for genuine conflicts (otherwise 'synced'). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(settings): show most recent sync time and reorder settings tabs Library settings menu now reports the latest of the book/config/note sync timestamps as "Synced …" instead of only the books timestamp. Reorder the settings tabs so Integrations precedes TTS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.7 KiB
5.7 KiB
Readest Project Memory
Key Reference Documents
- Bug Fixing Patterns - Common bug categories, root causes, and fix strategies
- CSS & Style Fixes - EPUB CSS override patterns and the style.ts pipeline
- TTS Fixes - Text-to-Speech architecture and bug patterns
- Layout & UI Fixes - Safe insets, z-index, platform-specific UI issues
- Platform Compat Fixes - Android, iOS, Linux, macOS platform-specific bugs
- Annotator & Reader Fixes - Highlight, selection, accessibility bugs
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)
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, backgroundssrc/services/tts/TTSController.ts- TTS state machine, section trackingsrc/hooks/useSafeAreaInsets.ts- Safe area inset managementsrc/app/reader/components/FoliateViewer.tsx- Reader view orchestrationsrc/app/reader/components/annotator/Annotator.tsx- Annotation lifecycle
Sync Notes
- KOSync CFI spine resolution — convert via the CFI's own spine (
getXPointerFromCFI/getCFIFromXPointer), nevernew XCFI(primaryDoc, primaryIndex); primaryIndex lags during scroll → spine-mismatch throw
Feature Notes
- Manage Cache + iOS container layout —
'Cache'base =Library/Caches/<bundle>only (not all of Caches); iOSDocuments/Inboxcleared 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
wsnpm); 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,.pocatalog atlocales/<i18next-code>/translation.po, extract/apply scripts inscripts/
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; neverpl/pr/ml/mr/text-left/text-right(RTL); §5 boxed list anatomy has uniformmin-h-14rows and chromeless controls
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 (duringview.open())
Workflow
- Test file filter — use
pnpm test <path>without--to run a single file - Always rebase before PR — rebase onto origin/main before creating PRs
- New branch per PR — always create a fresh branch from main for each new PR/issue
- Upgrade gstack locally — always upgrade from the project's .claude/skills/gstack, not global
- No lookbehind regex — never use
(?<=)or(?<!)in JS/TS; build check rejects them - Use worktree — never
git worktree adddirectly; alwayspnpm worktree:newbefore PR review, issue fix, or feature work - en/translation.json holds ONLY plural variants + proper nouns — non-plural strings stay out (defaultValue: key is the en source); plural strings (
_('...', { count })) need hand-added_one/_otherentries or the singular renders as "1 days" - Never push on every change — hold pushes during active bug iteration; commit locally only until user confirms or work hits a clean done-state
- No test seams in production code — production must never import or call
__reset*ForTests; cross-module test resets belong in the test file's beforeEach/afterEach