feat(reader): wire up reading progress save and restore

The web reader had all the infrastructure for progress persistence
(updateReadingProgress/getReadingProgress API functions, PUT/GET
endpoints, database queries) but the reader.ts never called them.

Changes:
- Add debounced (2s) saveProgress call on every relocate event that
  PUTs percentage, current_page, total_pages, and epubcfi to the
  existing /api/media-items/:id/progress endpoint
- Replace renderer.next() with view.init({ lastLocation }) to restore
  the reader to the last saved position on load (CFI first, then
  fraction fallback, then default first page)
- Pass savedPercentage and savedCfi from server-side progress data
  through readerInitExpr config to the JS initReader function
- Add mediaItemId and saveTimeout to the Alpine data object

This fixes both the blank /progress page and the missing progress
section on book detail pages — both were empty because the
reading_progress table never received any data from the web reader.
This commit is contained in:
2026-04-23 21:08:30 -04:00
parent a4962a87b2
commit 0269403a5d
3 changed files with 288 additions and 118 deletions
+9 -3
View File
@@ -5,14 +5,20 @@ import (
"fmt"
)
func readerInitExpr(metadata ReaderMetadata) string {
config := map[string]string{
func readerInitExpr(metadata ReaderMetadata, progress ReadingProgress) string {
config := map[string]interface{}{
"mediaItemId": metadata.MediaItemID,
"fileUrl": metadata.FileURL,
"formatGroup": metadata.FormatGroup,
"readingDirection": metadata.ReadingDirection,
"mangaType": metadata.MangaType,
}
if progress.Percentage > 0 {
config["savedPercentage"] = progress.Percentage
}
if progress.EpubCfi != "" {
config["savedCfi"] = progress.EpubCfi
}
jsonBytes, _ := json.Marshal(config)
return fmt.Sprintf("initReader(%s)", string(jsonBytes))
}
@@ -32,7 +38,7 @@ templ Reader(user User, metadata ReaderMetadata, progress ReadingProgress, bookm
</head>
<body
x-data="readerShell"
x-init={ readerInitExpr(metadata) }
x-init={ readerInitExpr(metadata, progress) }
class="theme-tokyo-night h-screen overflow-hidden"
>
@ReaderChrome(user, metadata, progress)