feat(annotations + player): bookmark rows in the banner, stacked volume panel, badge parity for comics/manga
Annotations banner: audio/text bookmarks join notes and highlights — third row kind (bookmark glyph indicator, H:MM:SS / Page N / Chapter N friendly labels), edit-note/delete actions branch by kind, and the banner's export now covers all annotations. The archived ledger (ListDeletedAnnotationsForBook) already tombstoned bookmarks equally and Restore/Purge take annotation_type=bookmark — verified live: delete → restore brings the row back with its note intact. Volume: the dragger sits BELOW the mute icon in the panel (stacked flyout shape) with the horizontal slider from the last round. Badges: the real fix for comics/manga — format_group only knows 'comic_archive' (manga_type is unreliable across sources), so the comic/manga split is resolved from the LIBRARY type server-side. handlers.MediaBadgeKind + BookInfo.Badge at every construction site (dashboard SSR + sections API, collections, series, and the bookshelf search grid — which was also missing FormatGroup entirely, so no card ever badged there). Both renderers (templ + dashboard.ts) switch on the resolved badge. Verified: All-Books grid renders 2 Comic + 3 Manga badges, dashboard the audiobook one. Infra: header.templ main.js src gains ?v=<stamp> — browsers keyed an intermediate bundle by URL and served it across rebuilds (the stale 'Add note' the user saw); bump the stamp when JS stale-shadows.
This commit is contained in:
1 parent
2c714dcb60
commit
89665fb2bc
19 files changed
+273
-92
No files matched your search
@@ -73,8 +73,9 @@ func (h *DashboardHandler) GetSections(c *echo.Context) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
libTypes := LibraryTypeMap(c.Request().Context(), h.db)
|
||||
|
||||
sectionData := BuildSections(sections, libraryID, libraryType)
|
||||
sectionData := BuildSections(sections, libraryID, libraryType, libTypes)
|
||||
sectionData = MarkActiveConflictsSections(c.Request().Context(), h.db, user.ID, sectionData)
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{"sections": sectionData})
|
||||
@@ -182,7 +183,7 @@ func (h *DashboardHandler) RestoreSystemCollection(c *echo.Context) error {
|
||||
// active library is audiobooks, system-collection titles/descriptions
|
||||
// swap to the listening wording at display time — the stored names stay
|
||||
// generic so restores and settings keep working across library types.
|
||||
func BuildSections(sections []services.DashboardSection, currentLibraryID, libraryType string) []SectionData {
|
||||
func BuildSections(sections []services.DashboardSection, currentLibraryID, libraryType string, libTypes map[string]string) []SectionData {
|
||||
var result []SectionData
|
||||
|
||||
audioScope := libraryType == "audiobooks"
|
||||
@@ -208,6 +209,7 @@ func BuildSections(sections []services.DashboardSection, currentLibraryID, libra
|
||||
Author: textToString(item.Author),
|
||||
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
|
||||
FormatGroup: item.FormatGroup,
|
||||
Badge: MediaBadgeKind(item.FormatGroup, libTypes[uuid.UUID(item.LibraryID.Bytes).String()]),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user