Skip to content

fix(chapters): don't flag re-dated chapters as updates; format dates - #2111

Open
blackstargit wants to merge 1 commit into
lnreader:masterfrom
blackstargit:fix/chapter-update-flood
Open

blackstargit wants to merge 1 commit into
lnreader:masterfrom
blackstargit:fix/chapter-update-flood

Conversation

@blackstargit

@blackstargit blackstargit commented Oct 25, 2026 •

Copy link
Copy Markdown

fix(chapters): don't flag re-dated chapters as updates; format dates

Problem

A library update marks an existing chapter as updated (updatedTime = now) whenever any field differs:
release time, position, page or chapter number. The Updates tab lists every chapter with updatedTime, so:

  • When a plugin starts sending release dates (e.g. the WebNovel plugin, fix(english/webnovel): add chapter dates and stats, fix ongoing status lnreader-plugins#2777),
    every chapter of every novel from that source lands in Updates on the next library update.
  • Plugins whose date fetch is best-effort flip releaseTime between a value and '', which floods Updates
    again on every failure and every recovery.
  • Each touched row fires the update_novel_stats_on_update trigger, which rescans the novel's chapters.
    That makes it O(n²) per novel for large libraries.

Change (insertChapters)

  • An empty incoming releaseTime keeps the stored one:
    COALESCE(NULLIF(excluded.releaseTime, ''), Chapter.releaseTime).
  • updatedTime is removed from the ON CONFLICT DO UPDATE SET. Naming it there fires the trigger even when
    the value is unchanged.
  • New chapters are still marked on insert. Existing chapters are marked only when renamed (e.g. a
    plugin drops its "🔒" locked marker when a chapter unlocks). The rename mark is written before the upsert,
    so a crash in between can't lose it.
  • The chapter drawer and the jump-to-chapter modal now format releaseTime with formatDate, like the
    novel chapter list. They used to print the raw string.

Tests

  • New db tests in ChapterQueries.test.ts:
    • '' → ISO fills the date without marking an update;
    • ISO → '' keeps the stored date;
    • position/page/number changes don't mark;
    • a mixed batch where a date-only change isn't marked, a 🔒 rename is marked, and a new chapter is marked.
  • RenderListChapter test: an ISO date is formatted, and a non-date string is shown unchanged.
  • tsc clean; jest --selectProjects rn 460/460. Tested on a device (Pixel 9 Pro XL, Android 17) with my
    library and the WebNovel plugin 1.1.0.

Notes

  • A plugin can no longer clear a stored date by sending ''/null. That's intentional.
  • Renames still count as updates, so a plugin that changes its chapter-name format causes one-time entries.

Library update marked any changed chapter as updated, so a plugin that
starts sending release dates (or one whose date fetch fails now and
then) put every chapter of every novel into Updates and fired the
per-row stats trigger for each.

- An empty incoming releaseTime keeps the stored one.
- updatedTime is left out of the ON CONFLICT SET; existing chapters are
  only marked updated when renamed (e.g. a "🔒" locked marker removed),
  marked before the upsert so a crash in between can't lose it.
  New chapters are still marked on insert.
- Chapter drawer and jump-to-chapter modal format releaseTime with
  formatDate, like the novel chapter list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect library chapter updates and two chapter-navigation views.

The PR appears safe to merge, with two non-blocking test improvements.

Findings

  1. P2 Date preservation test skips updates ▶
  2. P2 Blank dates pass this test ▶

Summary

The PR stops date and ordering changes from creating Updates entries. New and renamed chapters still receive updatedTime.

  • Library updates mark new chapters and renames, not metadata changes.
  • Chapter dates follow the app’s format in the drawer and jump results.

Acknowledged intent from blackstargit: empty or null dates cannot clear stored dates; chapter-name format changes can create one-time Updates entries; rename marks are saved before the upsert to survive interruption.

Reviews (1) · Last reviewed commit: "fix(chapters): don't flag re-dated chapt..." · Reviewed by Greptile

Comment on lines +535 to +539
await insertChapters(
novelId,
[{ path: '/chapter/1', name: 'Chapter 1', releaseTime: '' }],
touch,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Date preservation test skips updates

All other fields match, so the new where condition skips this row. The test would still pass if set.releaseTime reverted to excluded.releaseTime, leaving date loss during an actual update unchecked. Change another field, such as page, and assert that it changes while the stored date stays intact.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +63 to +67
const { rerender } = renderChapter({
...chapter,
releaseTime: '2024-03-05T10:20:30.000Z',
});
expect(screen.queryByText('2024-03-05T10:20:30.000Z')).toBeNull();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Blank dates pass this test

The ISO-date check only proves that the raw string disappeared. It also passes if valid dates render as blank text. Pass an explicit dateFormat with relativeTimestamps={false} and assert the expected date is visible. Keep the existing non-date check.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

This branch has not been deployed

No deployments
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.

2 participants