Skip to content

feat: auto-mark documents as completed on reaching last page#27

Open
specbug wants to merge 1 commit into
mainfrom
completed-docs
Open

feat: auto-mark documents as completed on reaching last page#27
specbug wants to merge 1 commit into
mainfrom
completed-docs

Conversation

@specbug
Copy link
Copy Markdown
Owner

@specbug specbug commented May 24, 2026

Summary

Adds reading completion as a first-class state. Finished docs stop blending into the Reading list and pick up a quiet visual marker everywhere they appear, without changing any reading behavior (you can still open, scroll, annotate, and review them as before).

  • Backend stamps PDFFile.completed_at the first time PATCH /files/{id}/position reports last_read_position >= total_pages - 1. Auto-only — never cleared, never re-triggered. Silently skipped when total_pages is unknown.
  • LibraryScreen splits the list into READING (current sort applies) and COMPLETED (always sorted by completedAt desc). Completed docs end up at the bottom but in a self-contained, named section.
  • DocGlyph inverts to a sealed-stamp variant when doc.completed === true: solid ink fill, paper-colored starburst, small grayscale tick inset bottom-right. Per DESIGN.md §3, completion is not an accent moment, so the whole change is grayscale.
  • PdfScreen topbar adds a mono FINISHED · YYYY·MM·DD tag next to the author whenever a doc is completed. The position-save promise patches fileMetadata.completed_at from the response, so the tag flips in place the instant the user reaches the last page — no refresh required.

Schema + migration

  • New column: pdf_files.completed_at DATETIME NULL.
  • In-app idempotent migration _migrate_pdf_file_completed_at runs on every backend boot (mirrors _migrate_pdf_file_title).
  • Standalone migration script: apps/api/scripts/migrations/migrate_add_completed_at.py for explicit runs against deployed databases.
  • PDFFileResponse.completed_at exposed; adapters.toLibraryDoc projects it as { completed, completedAt }.

Docs

  • CLAUDE.md — new capability bullet, Database Schema paragraph for completed_at, current-branch block refreshed.
  • apps/webapp/DESIGN.md — DocGlyph entry gets a "Completed variant" subsection; per-screen intent table notes Library sectioning and the PdfScreen FINISHED tag.

Test plan

  • FastAPI TestClient end-to-end against a forked database:
    • page 3/5 → completed_at stays None
    • page 4/5 (last) → completed_at stamped
    • scroll back to page 1 → completed_at preserved
    • row with total_pages = NULL at position 999 → completed_at stays None
  • Standalone migration script run on a real-data DB fork — adds column, leaves existing rows with NULL.
  • bun run build compiles (one pre-existing ESLint warning in PdfScreen.js:1027 for scrollToPageIndex dep, unrelated to this change).
  • Visual smoke in browser with a seeded library: Library shows READING · N + COMPLETED · N sections; completed glyphs render the sealed-stamp variant; opening a completed doc shows the FINISHED · … topbar tag.

Co-Authored-By: Claude noreply@anthropic.com

Adds reading-completion as a first-class state so finished docs stop blending
into the Reading list. Backend stamps `PDFFile.completed_at` the first time
`update_read_position` lands on the last page (auto-only, never cleared, and
silently skipped when total_pages is unknown). Frontend surfaces the state in
three places, all grayscale per DESIGN.md:

- LibraryScreen splits the document list into `READING` and `COMPLETED`
  sections. Completed always sorts by completedAt desc regardless of the
  active segmented sort, so the most recently finished sits on top.
- DocGlyph inverts to a sealed-stamp variant for completed docs (solid ink
  fill, paper-colored starburst, small tick inset). No accent involved.
- PdfScreen topbar adds a mono `FINISHED · YYYY·MM·DD` tag next to the
  author. The position-save promise now patches `fileMetadata.completed_at`
  from the response so the tag appears live the instant the user reaches
  the last page — no refresh required.

Backend wiring:
- `PDFFile.completed_at` nullable `DateTime(timezone=True)`.
- In-app idempotent migration `_migrate_pdf_file_completed_at` (mirrors
  `_migrate_pdf_file_title`) plus standalone
  `scripts/migrations/migrate_add_completed_at.py` for explicit runs.
- `PDFFileResponse.completed_at` exposed; `adapters.toLibraryDoc` projects
  it as `{ completed, completedAt }`.

Docs:
- `CLAUDE.md` — capabilities bullet, Database Schema note, current-branch
  block refreshed.
- `apps/webapp/DESIGN.md` — DocGlyph completed variant + per-screen intent
  notes for Library / PDF.

Smoke-tested end to end via FastAPI TestClient against a forked database:
sub-last-page position update keeps completed_at null, last-page update
stamps it, scrolling back preserves the stamp, and rows with NULL
total_pages stay null even at impossible positions.

Co-Authored-By: Claude <noreply@anthropic.com>
@specbug specbug added the claude PR created by Claude label May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude PR created by Claude

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant