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:
@@ -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),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bookhoard/internal/database"
|
||||
"bookhoard/internal/handlers"
|
||||
"bookhoard/internal/services"
|
||||
"bookhoard/internal/sync"
|
||||
"bookhoard/internal/utils"
|
||||
"bookhoard/templates"
|
||||
"bytes"
|
||||
@@ -100,20 +101,25 @@ func registerReaderRoutes(cfg *Config) {
|
||||
ReadingDirection: textToString(mediaItem.ReadingDirection),
|
||||
LibraryID: libUUID.String(),
|
||||
FileURL: utils.ResolveMediaURL(mediaItem.LibraryID, pgtype.Text{String: mediaItem.FilePath, Valid: true}),
|
||||
TotalCharacters: mediaItem.TotalCharacters.Int64,
|
||||
EstimatedPages: sync.EstimatedPages(mediaItem.TotalCharacters.Int64),
|
||||
}
|
||||
// Progress conversion (inline)
|
||||
progressUUID, _ := uuid.FromBytes(progress.ID.Bytes[0:16])
|
||||
progressMediaUUID, _ := uuid.FromBytes(progress.MediaItemID.Bytes[0:16])
|
||||
progressUserUUID, _ := uuid.FromBytes(progress.UserID.Bytes[0:16])
|
||||
templateProgress := templates.ReadingProgress{
|
||||
ID: progressUUID.String(),
|
||||
MediaItemID: progressMediaUUID.String(),
|
||||
UserID: progressUserUUID.String(),
|
||||
CurrentPage: int(progress.CurrentPage.Int32),
|
||||
TotalPages: int(progress.TotalPages.Int32),
|
||||
Percentage: progress.Percentage.Float64,
|
||||
EpubCfi: textToString(progress.Epubcfi),
|
||||
LastReadAt: progress.LastReadAt.Time,
|
||||
ID: progressUUID.String(),
|
||||
MediaItemID: progressMediaUUID.String(),
|
||||
UserID: progressUserUUID.String(),
|
||||
CurrentPage: int(progress.CurrentPage.Int32),
|
||||
TotalPages: int(progress.TotalPages.Int32),
|
||||
Percentage: progress.Percentage.Float64 * 100,
|
||||
EpubCfi: textToString(progress.Epubcfi),
|
||||
LastReadAt: progress.LastReadAt.Time,
|
||||
Chapter: int(progress.Chapter.Int32),
|
||||
ChapterProgress: progress.ChapterProgress.Float64 * 100,
|
||||
FormatGroup: mediaItem.FormatGroup,
|
||||
}
|
||||
// Bookmarks conversion (inline, with loop)
|
||||
templateBookmarks := make([]templates.Bookmark, len(bookmarks))
|
||||
|
||||
@@ -229,7 +229,7 @@ templ BookDetail(user User, book handlers.MediaDetail, errorMessage string) {
|
||||
<div class="w-full rounded-full h-3" style="background-color: var(--bg-primary);">
|
||||
<div
|
||||
class="h-3 rounded-full transition-all"
|
||||
style="width: { book.ReadingProgress.Percentage.Float64 }%; background-color: var(--accent);"
|
||||
style={ fmt.Sprintf("width: %.1f%%; background-color: var(--accent);", book.ReadingProgress.Percentage.Float64 * 100) }
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -238,7 +238,7 @@ templ BookDetail(user User, book handlers.MediaDetail, errorMessage string) {
|
||||
<div>
|
||||
<p style="color: var(--text-secondary)">Progress</p>
|
||||
<p class="text-2xl font-bold" style="color: var(--accent);">
|
||||
{ fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64) }%
|
||||
{ fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64 * 100) }%
|
||||
</p>
|
||||
</div>
|
||||
if book.ReadingProgress.CurrentPage.Valid && book.ReadingProgress.TotalPages.Valid {
|
||||
|
||||
@@ -98,7 +98,7 @@ templ ProgressSyncModal(book handlers.MediaDetail) {
|
||||
style="background-color: var(--bg-primary); border-color: var(--border);"
|
||||
>
|
||||
<div class="text-5xl font-bold mb-4" style="color: var(--accent);">
|
||||
{ fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64) }%
|
||||
{ fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64 * 100) }%
|
||||
</div>
|
||||
<p class="capitalize text-lg mb-2" style="color: var(--text-primary);">
|
||||
{ book.ReadingProgress.LastSyncSource.String }
|
||||
|
||||
@@ -42,7 +42,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 22, Col: 74}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 22, Col: 74}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -65,7 +65,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(source)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 65, Col: 18}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 65, Col: 18}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -78,7 +78,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(data.Timestamp.Format("2006-01-02 15:04:05"))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 68, Col: 56}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 68, Col: 56}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -91,7 +91,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", data.Data["percentage"].(float64)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 73, Col: 66}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 73, Col: 66}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -109,7 +109,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.0f", data.Data["current_page"].(float64)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 80, Col: 73}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 80, Col: 73}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -122,7 +122,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.0f", data.Data["total_pages"].(float64)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 80, Col: 135}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 80, Col: 135}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -141,7 +141,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(data.Data["epubcfi"].(string))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 85, Col: 45}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 85, Col: 45}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -169,7 +169,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.LastSyncSource.String)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 94, Col: 105}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 94, Col: 105}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -180,9 +180,9 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64))
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f", book.ReadingProgress.Percentage.Float64*100))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 101, Col: 68}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 101, Col: 74}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -195,7 +195,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.LastSyncSource.String)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 104, Col: 50}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 104, Col: 50}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -213,7 +213,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.CurrentPage.Int32)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 108, Col: 52}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 108, Col: 52}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -226,7 +226,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.TotalPages.Int32)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 108, Col: 97}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 108, Col: 97}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -245,7 +245,7 @@ func ProgressSyncModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.LastReadAt.Time.Format("2006-01-02 15:04"))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 113, Col: 83}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 113, Col: 83}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -298,7 +298,7 @@ func NotesHighlightsModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(book.NotesCount)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 145, Col: 43}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 145, Col: 43}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -311,7 +311,7 @@ func NotesHighlightsModal(book handlers.MediaDetail) templ.Component {
|
||||
var templ_7745c5c3_Var17 string
|
||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(book.HighlightsCount)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 145, Col: 95}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail_modals.templ`, Line: 145, Col: 95}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
||||
+274
-261
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
package templates
|
||||
|
||||
import "bookhoard/internal/handlers"
|
||||
import "fmt"
|
||||
|
||||
templ Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage string) {
|
||||
<!DOCTYPE html>
|
||||
@@ -57,15 +58,23 @@ templ Progress(user User, progressData []handlers.ProgressWithMedia, errorMessag
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="w-full bg-gray-700 rounded-full h-3">
|
||||
<div class="h-3 rounded-full transition-all" style="width: { item.ProgressPercentage }%; background-color: var(--accent);"></div>
|
||||
<div class="h-3 rounded-full transition-all" style={ "width: " + fmt.Sprintf("%.1f", item.ProgressPercentage) + "%; background-color: var(--accent);" }></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
||||
<div>
|
||||
<p style="color: var(--text-secondary)">Current Position</p>
|
||||
<p style="color: var(--text-primary)">
|
||||
{ item.CurrentPage } / { item.TotalPages }
|
||||
</p>
|
||||
<p style="color: var(--text-secondary)">Current Position</p>
|
||||
<p style="color: var(--text-primary)">
|
||||
if item.FormatGroup == "reflowable" {
|
||||
if item.EstimatedPages > 0 {
|
||||
{ fmt.Sprintf("Page %d of %d (est.)", item.CurrentPage, item.EstimatedPages) }
|
||||
} else {
|
||||
{ fmt.Sprintf("%.1f%%", item.ProgressPercentage) }
|
||||
}
|
||||
} else {
|
||||
{ fmt.Sprintf("%d / %d", item.CurrentPage, item.TotalPages) }
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p style="color: var(--text-secondary)">Last Updated</p>
|
||||
|
||||
+65
-40
@@ -9,6 +9,7 @@ import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "bookhoard/internal/handlers"
|
||||
import "fmt"
|
||||
|
||||
func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
@@ -57,7 +58,7 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
var templ_7745c5c3_Var2 templ.SafeURL
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs("/media/" + item.MediaItemID.String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 45, Col: 56}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 46, Col: 56}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -70,7 +71,7 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 48, Col: 75}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 49, Col: 75}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -88,7 +89,7 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(item.Author)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 51, Col: 84}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 52, Col: 84}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -106,48 +107,72 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(item.ProgressPercentage)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 55, Col: 98}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 56, Col: 98}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "%</span></div></div><div class=\"mb-4\"><div class=\"w-full bg-gray-700 rounded-full h-3\"><div class=\"h-3 rounded-full transition-all\" style=\"width: { item.ProgressPercentage }%; background-color: var(--accent);\"></div></div></div><div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 text-sm\"><div><p style=\"color: var(--text-secondary)\">Current Position</p><p style=\"color: var(--text-primary)\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "%</span></div></div><div class=\"mb-4\"><div class=\"w-full bg-gray-700 rounded-full h-3\"><div class=\"h-3 rounded-full transition-all\" style=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(item.CurrentPage)
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues("width: " + fmt.Sprintf("%.1f", item.ProgressPercentage) + "%; background-color: var(--accent);")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 67, Col: 30}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 61, Col: 160}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, " / ")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\"></div></div></div><div class=\"grid grid-cols-1 md:grid-cols-3 gap-4 text-sm\"><div><p style=\"color: var(--text-secondary)\">Current Position</p><p style=\"color: var(--text-primary)\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.TotalPages)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 67, Col: 52}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
if item.FormatGroup == "reflowable" {
|
||||
if item.EstimatedPages > 0 {
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("Page %d of %d (est.)", item.CurrentPage, item.EstimatedPages))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 70, Col: 89}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.1f%%", item.ProgressPercentage))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 72, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d / %d", item.CurrentPage, item.TotalPages))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 75, Col: 71}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</p></div><div><p style=\"color: var(--text-secondary)\">Last Updated</p><p style=\"color: var(--text-primary)\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(item.LastUpdated)
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item.LastUpdated)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 72, Col: 67}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 81, Col: 67}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -155,12 +180,12 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceIcon)
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceIcon)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 77, Col: 51}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 86, Col: 51}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -168,12 +193,12 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceName)
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceName)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 78, Col: 70}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 87, Col: 70}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -186,12 +211,12 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceName)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceName)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 86, Col: 58}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 95, Col: 58}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -199,12 +224,12 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceType)
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(item.DeviceType)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 87, Col: 36}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 96, Col: 36}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -218,12 +243,12 @@ func Progress(user User, progressData []handlers.ProgressWithMedia, errorMessage
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(item.EpubCFI)
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(item.EpubCFI)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/progress.templ`, Line: 94, Col: 36}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `progress.templ`, Line: 103, Col: 36}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
@@ -155,7 +155,15 @@ templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
||||
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
||||
<!-- Progress display -->
|
||||
<div id="progress-display" x-text="progressText" data-progress-mode="pages" class="text-sm min-w-[4rem] text-center">
|
||||
{ fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages) }
|
||||
if progress.FormatGroup == "reflowable" {
|
||||
if metadata.EstimatedPages > 0 {
|
||||
{ fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages) }
|
||||
} else {
|
||||
{ fmt.Sprintf("%.0f%%", progress.Percentage) }
|
||||
}
|
||||
} else {
|
||||
{ fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages) }
|
||||
}
|
||||
</div>
|
||||
<!-- Separator -->
|
||||
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
||||
|
||||
+63
-39
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user