fix(progress): correct percentage display and add format-aware progress

Fix two bugs in progress display across book detail, progress page, reader,
and sync modal templates:

1. Percentage was stored as 0.0-1.0 fraction but displayed as-if 0-100
   (showing 0.5% instead of 50%). Multiply by 100 at the data source in
   both GetAllProgress and GetAllProgressData handlers, and in the reader
   route's ReadingProgress construction.

2. Progress bar width was never evaluated — { expr } inside style=".."
   was rendered as literal text by templ, resulting in 0% width bars for
   all items. Fixed by using templ's style={ expr } attribute syntax
   which evaluates the Go expression (uses SanitizeStyleAttributeValues).

Also add format-aware progress display:
- Reader template: shows "45% · Page 89/196" for reflowable (estimated
  pages), "127/342" for comics/PDFs (actual pages)
- Progress page: shows "Page X of Y (est.)" for reflowable, "X / Y"
  for fixed layout
- Add FormatGroup and EstimatedPages to ProgressWithMedia struct
- Remove hardcoded totalPages=200 fallback in progress handler (now 0)
- Add fmt import to progress.templ for string formatting
This commit is contained in:
2026-04-24 14:03:03 -04:00
parent 192c978a38
commit d38804e910
10 changed files with 477 additions and 385 deletions
+19 -12
View File
@@ -139,7 +139,7 @@ func (h *Handler) UpdateUniversalProgress(c *echo.Context) error {
}
currentPage := 0
totalPages := 200
totalPages := 0
if req.Location.Page != nil {
currentPage = *req.Location.Page
}
@@ -261,6 +261,8 @@ type ProgressWithMedia struct {
ProgressPercentage float64 `json:"-"`
EpubCFI string `json:"-"`
LastUpdated string `json:"-"`
FormatGroup string `json:"format_group"`
EstimatedPages int `json:"estimated_pages"`
}
// GetAllProgress retrieves all progress for a user with sync source info
@@ -318,10 +320,12 @@ func (h *Handler) GetAllProgress(c *echo.Context) error {
LastReadAt: progress.LastReadAt.Time,
Epubcfi: epubcfi,
LastSyncDevice: deviceName,
ProgressPercentage: progress.Percentage.Float64,
ProgressPercentage: progress.Percentage.Float64 * 100,
EpubCFI: epubcfi,
LastUpdated: lastUpdated,
DeviceIcon: getDeviceIcon(deviceName),
FormatGroup: mediaItem.FormatGroup,
EstimatedPages: wsync.EstimatedPages(mediaItem.TotalCharacters.Int64),
})
}
@@ -371,16 +375,19 @@ func (h *Handler) GetAllProgressData(c *echo.Context) ([]ProgressWithMedia, erro
}
progressList = append(progressList, ProgressWithMedia{
MediaItemID: progress.MediaItemID.Bytes,
Title: mediaItem.Title,
Author: author,
CoverImagePath: coverPath,
Percentage: progress.Percentage.Float64,
CurrentPage: progress.CurrentPage.Int32,
TotalPages: progress.TotalPages.Int32,
LastReadAt: progress.LastReadAt.Time,
Epubcfi: epubcfi,
LastSyncDevice: deviceName,
MediaItemID: progress.MediaItemID.Bytes,
Title: mediaItem.Title,
Author: author,
CoverImagePath: coverPath,
Percentage: progress.Percentage.Float64,
CurrentPage: progress.CurrentPage.Int32,
TotalPages: progress.TotalPages.Int32,
LastReadAt: progress.LastReadAt.Time,
Epubcfi: epubcfi,
LastSyncDevice: deviceName,
ProgressPercentage: progress.Percentage.Float64 * 100,
FormatGroup: mediaItem.FormatGroup,
EstimatedPages: wsync.EstimatedPages(mediaItem.TotalCharacters.Int64),
})
}