Skip to content

Fix progress clobber, cancellation propagation, and reader recomposition#71

Merged
Aatricks merged 5 commits into
mainfrom
fix/progress-clobber-and-reader-jank
Jul 2, 2026
Merged

Fix progress clobber, cancellation propagation, and reader recomposition#71
Aatricks merged 5 commits into
mainfrom
fix/progress-clobber-and-reader-jank

Conversation

@Aatricks

@Aatricks Aatricks commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Fixes from a full-codebase review (findings verified against source before fixing).

Changes

  • Library refresh no longer reverts reading progress. refreshLibraryUpdates used to snapshot all rows, fetch chapter counts for seconds, then bulk-REPLACE whole rows — clobbering any progress written during the window. It now groups by (baseTitle, sourceName) and writes only totalChapters/hasUpdates through targeted UPDATE queries, which also stops one source's chapter count from being stamped onto another source's rows.
  • CancellationException propagates again. New Result.rethrowCancellation() applied at the confirmed runCatching sites (BaseViewModel, repositories, openNewChapter), so cancelled loads no longer flash error states, fabricate retryable results, or poison the 3s inspect memo. Also hardens the image-dimension flush against crashes and makes openNewChapter single-flight.
  • Reader: edge-blur recapture reads scroll offsets inside a snapshotFlow instead of as composition-read LaunchedEffect keys, removing whole-ContentArea recomposition + effect churn on every scrolled pixel. Verified on-device (S22, 120Hz): no frame-time regression (~0.8% jank, p95 5ms), blur recapture still works after scroll settles.
  • Reader sheets survive process death (rememberSaveable).
  • ChapterListCache writes atomically (temp + rename).

Verification

  • 391 unit tests green (42 new/converted, including a mid-refresh progress-preservation test), detekt clean, no baseline changes, both flavors assemble.
  • On-device smoke test: scroll, controls, edge blur, logcat clean.

Aatricks added 5 commits July 1, 2026 22:05
…ndaries

Cancelled coroutines were being treated as failures: BaseViewModel flashed
'unknown error' states, ContentRepository fabricated retryable results (and
inspectCache memoized them for 3s), and repositories logged cancellations as
errors. Add Result.rethrowCancellation() and apply it at the confirmed sites.

Also guard ImageDimensionManager's dimension flush against persistAll
failures crashing the scope, and make openNewChapter single-flight so rapid
taps don't run concurrent fetches.
…ource

refreshLibraryUpdates snapshotted all rows, spent seconds on network
fetches, then bulk-inserted the stale copies with whole-row REPLACE —
reverting any reading progress written during the refresh window. It also
grouped by baseTitle alone, stamping one source's chapter count onto every
source's rows for multi-source series.

Group by (baseTitle, sourceName) and write only totalChapters/hasUpdates
through targeted UPDATE queries, leaving progress fields untouched.
…ecomposition

The recapture effect used listState.firstVisibleItemScrollOffset (and index/
currentPage) as LaunchedEffect keys, so composition read the scroll offset
directly: every scrolled pixel recomposed the whole ContentArea and
cancelled/relaunched the effect, even with controls hidden. Read the values
inside a snapshotFlow instead; collectLatest preserves the settle debounce.
Chapter list, settings, and the Cloudflare dialog used plain remember, so
process death while open silently closed them. Use rememberSaveable.
save() wrote directly to the target file; a crash or concurrent save could
leave corrupt JSON (load degrades to a refetch, but avoidably). Write to a
temp file and rename, mirroring WebOfflineChapterStore.writeManifest.
@Aatricks Aatricks merged commit 5310f69 into main Jul 2, 2026
4 checks passed
@Aatricks Aatricks deleted the fix/progress-clobber-and-reader-jank branch July 2, 2026 02:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant