diff --git a/AGENTS.md b/AGENTS.md index b3e33df1..71b6fcbc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -161,14 +161,19 @@ of a server bug: stop and flag the user. the cache stale until the next API-path write — never "preview" rule changes via psql and expect them applied (2026-10-14: a live curl test flip looked ignored until the API path was used). -3. **User collections are not dashboard sections**: nothing sets - collection show_on_dashboard for user rows, and GetDashboardSections - skips empty user sections. Collection detail (JSON + SSR) must NOT - route user rows through the dashboard-section path — a 7ce7321 - regression did exactly that (static detail without library_id - returned zero books until 0a7fbd6). Only real system query types - (continue-reading etc.) route there; `query_type='filter'` is the - schema DEFAULT on every user row, not a query type. +3. **User collections are not dashboard query types** (amended 2026-10-19, + A2c): user collections ARE dashboard sections by default now — + GetUserCollectionsForDashboard no longer gates on show_on_dashboard + (which remains system-section provisioning state; hiding is + dashboard-prefs `hidden_collections` territory). GetDashboardSections + still skips genuinely empty user sections, but hide_finished + collections emit a Complete section instead of vanishing. Collection + detail (JSON + SSR) must still NOT route user rows through the + dashboard-section path — a 7ce7321 regression did exactly that + (static detail without library_id returned zero books until 0a7fbd6). + Only real system query types (continue-reading etc.) route there; + `query_type='filter'` is the schema DEFAULT on every user row, not a + query type. 4. **End-of-day arithmetic**: anchor the END bound to the START of the day, never to NOW(). `now.AddDate(0,0,1) − 1ns` carries this instant's clock time into tomorrow — a range "ending today" diff --git a/internal/database/queries.sql.go b/internal/database/queries.sql.go index 74eb1632..5f8ca7c8 100644 --- a/internal/database/queries.sql.go +++ b/internal/database/queries.sql.go @@ -13218,14 +13218,26 @@ WHERE COALESCE(lv.is_visible, true) = true AND mi.missing_scan_count = 0 AND ($2::uuid IS NULL OR mi.library_id = $2::uuid) - -- Fuzzy author filter - AND ($3 = '' OR word_similarity($3, COALESCE(mi.author, '')) > 0.3) + -- Fuzzy author filter — per-element against the authors[] array (A2c + -- §4.1): a co-authored book matches ANY one of its authors, and a + -- comma-joined param is multi-select (OR within the facet). + AND ($3 = '' OR EXISTS ( + SELECT 1 + FROM unnest(string_to_array($3, ',')) AS f + JOIN unnest(mi.authors) AS a ON true + WHERE word_similarity(f, COALESCE(a, '')) > 0.3 + )) -- Fuzzy series filter AND ($4 = '' OR word_similarity($4, COALESCE(mi.series, '')) > 0.3) -- Fuzzy genre filter AND ($5 = '' OR word_similarity($5, COALESCE(mi.genre, '')) > 0.3) - -- Fuzzy publisher filter - AND ($6 = '' OR word_similarity($6, COALESCE(mi.publisher, '')) > 0.3) + -- Fuzzy publisher filter — per-element against publishers[] (A2c §4.1). + AND ($6 = '' OR EXISTS ( + SELECT 1 + FROM unnest(string_to_array($6, ',')) AS f + JOIN unnest(mi.publishers) AS p ON true + WHERE word_similarity(f, COALESCE(p, '')) > 0.3 + )) -- Fuzzy language filter AND ($7 = '' OR word_similarity($7, COALESCE(mi.language, '')) > 0.3) -- Tags filter (NEW - fuzzy match against tags array) diff --git a/internal/database/queries/queries.sql b/internal/database/queries/queries.sql index edb7aca6..e2b773d9 100644 --- a/internal/database/queries/queries.sql +++ b/internal/database/queries/queries.sql @@ -679,14 +679,26 @@ WHERE COALESCE(lv.is_visible, true) = true AND mi.missing_scan_count = 0 AND (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid) - -- Fuzzy author filter - AND (sqlc.narg('author_filter') = '' OR word_similarity(sqlc.narg('author_filter'), COALESCE(mi.author, '')) > 0.3) + -- Fuzzy author filter — per-element against the authors[] array (A2c + -- §4.1): a co-authored book matches ANY one of its authors, and a + -- comma-joined param is multi-select (OR within the facet). + AND (sqlc.narg('author_filter') = '' OR EXISTS ( + SELECT 1 + FROM unnest(string_to_array(sqlc.narg('author_filter'), ',')) AS f + JOIN unnest(mi.authors) AS a ON true + WHERE word_similarity(f, COALESCE(a, '')) > 0.3 + )) -- Fuzzy series filter AND (sqlc.narg('series_filter') = '' OR word_similarity(sqlc.narg('series_filter'), COALESCE(mi.series, '')) > 0.3) -- Fuzzy genre filter AND (sqlc.narg('genre_filter') = '' OR word_similarity(sqlc.narg('genre_filter'), COALESCE(mi.genre, '')) > 0.3) - -- Fuzzy publisher filter - AND (sqlc.narg('publisher_filter') = '' OR word_similarity(sqlc.narg('publisher_filter'), COALESCE(mi.publisher, '')) > 0.3) + -- Fuzzy publisher filter — per-element against publishers[] (A2c §4.1). + AND (sqlc.narg('publisher_filter') = '' OR EXISTS ( + SELECT 1 + FROM unnest(string_to_array(sqlc.narg('publisher_filter'), ',')) AS f + JOIN unnest(mi.publishers) AS p ON true + WHERE word_similarity(f, COALESCE(p, '')) > 0.3 + )) -- Fuzzy language filter AND (sqlc.narg('language_filter') = '' OR word_similarity(sqlc.narg('language_filter'), COALESCE(mi.language, '')) > 0.3) -- Tags filter (NEW - fuzzy match against tags array) diff --git a/internal/handlers/collections.go b/internal/handlers/collections.go index 3bd8245a..f0ba5a2c 100644 --- a/internal/handlers/collections.go +++ b/internal/handlers/collections.go @@ -52,6 +52,12 @@ type UpdateCollectionRequest struct { Icon string `form:"icon" json:"icon"` AutoAssignRules []services.Rule `form:"auto_assign_rules" json:"auto_assign_rules"` ViewSettings map[string]interface{} `form:"view_settings" json:"view_settings"` + // A2c §3.3: playlist toggles — merged into view_settings server-side + // (nil = untouched). []string because the form posts a hidden "false" + // sibling next to the checkbox; the LAST value wins. JSON clients may + // send a single-element array (or omit — untouched). + HideFinished []string `form:"hide_finished" json:"hide_finished"` + ShowUpNext []string `form:"show_up_next" json:"show_up_next"` } type AddBooksRequest struct { @@ -404,6 +410,23 @@ func (h *CollectionHandler) UpdateCollection(c *echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) } + // A2c §3.3: playlist toggles ride the edit form as top-level fields and + // merge into view_settings server-side (the form can't bind a map). + // The form posts a hidden "false" sibling before the checkbox, so the + // LAST value is the checkbox state. + if v := optionalFlag(req.HideFinished); v != nil { + if req.ViewSettings == nil { + req.ViewSettings = map[string]interface{}{} + } + req.ViewSettings["hide_finished"] = *v + } + if v := optionalFlag(req.ShowUpNext); v != nil { + if req.ViewSettings == nil { + req.ViewSettings = map[string]interface{}{} + } + req.ViewSettings["show_up_next"] = *v + } + collection, err := h.collectionService.UpdateCollection( c.Request().Context(), collectionID, @@ -1336,3 +1359,13 @@ func (h *CollectionHandler) ReorderItems(c *echo.Context) error { } return c.JSON(http.StatusOK, map[string]string{"status": "reordered"}) } + +// optionalFlag interprets a multi-valued form flag: last value wins +// (hidden-false sibling precedes the checkbox), absent → nil (untouched). +func optionalFlag(values []string) *bool { + if len(values) == 0 { + return nil + } + v := strings.EqualFold(values[len(values)-1], "true") + return &v +} diff --git a/internal/router/frontend.go b/internal/router/frontend.go index 402f4f3d..9dfdb830 100644 --- a/internal/router/frontend.go +++ b/internal/router/frontend.go @@ -605,6 +605,19 @@ func registerFrontendRoutes(cfg *Config) { Icon: utils.PgTextString(collection.Icon), } + // A2c §3.3: playlist toggles from view_settings. + if len(collection.ViewSettings) > 0 { + var vs map[string]interface{} + if json.Unmarshal(collection.ViewSettings, &vs) == nil { + if b, ok := vs["hide_finished"].(bool); ok { + colData.HideFinished = b + } + if b, ok := vs["show_up_next"].(bool); ok { + colData.ShowUpNext = b + } + } + } + // Ensure default color if empty if colData.Color == "" { colData.Color = "blue" diff --git a/internal/services/collection_service.go b/internal/services/collection_service.go index 012c1421..76042696 100644 --- a/internal/services/collection_service.go +++ b/internal/services/collection_service.go @@ -155,6 +155,23 @@ func (s *CollectionService) GetUserCollections(ctx context.Context, userID uuid. // UpdateCollection updates a collection func (s *CollectionService) UpdateCollection(ctx context.Context, collectionID uuid.UUID, name, description, color, icon string, autoAssignRules []Rule, viewSettings map[string]any) (database.Collections, error) { + // A2c §3.3: the edit form carries only the toggles it renders — merge + // them OVER the stored view_settings so provenance keys + // (imported_from_series) and anything else on the row survive. + if len(viewSettings) > 0 { + existing, err := s.db.GetCollection(ctx, pgtype.UUID{Bytes: collectionID, Valid: true}) + if err == nil && len(existing.ViewSettings) > 0 { + var stored map[string]any + if json.Unmarshal(existing.ViewSettings, &stored) == nil { + merged := stored + for k, v := range viewSettings { + merged[k] = v + } + viewSettings = merged + } + } + } + // Convert rules to JSONB ([]byte) var rulesJSON []byte if len(autoAssignRules) > 0 { diff --git a/templates/book_detail.templ b/templates/book_detail.templ index cbe4f87e..e60571e7 100644 --- a/templates/book_detail.templ +++ b/templates/book_detail.templ @@ -63,7 +63,14 @@ templ BookDetail(user User, book handlers.MediaDetail, errorMessage string, tomb
{ book.Subtitle.String }
+ } + if len(book.Authors) > 0 { +") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var15 string - templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author.String) + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(book.Subtitle.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 68, Col: 32} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 67, Col: 91} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - if book.IsAudio() && len(book.Narrators) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "Progress conflict detected — click \"Sync Progress\" to review and resolve.
Progress conflict detected — click \"Sync Progress\" to review and resolve.
Position
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var36 string - templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(book.AudioCurrentLabel() + " / " + book.AudioDurationLabel()) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 289, Col: 144} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 90, "
Progress
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var37 string - templ_7745c5c3_Var37, 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: `book_detail.templ`, Line: 294, Col: 135} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "%
Page
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "
Position
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var38 string - templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.CurrentPage.Int32) + templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(book.AudioCurrentLabel() + " / " + book.AudioDurationLabel()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 300, Col: 87} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 299, Col: 144} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, " / ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var39 string - templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.TotalPages.Int32) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 300, Col: 131} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 95, "
Progress
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var39 string + templ_7745c5c3_Var39, 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: `book_detail.templ`, Line: 304, Col: 135} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "%
") + if book.ReadingProgress.CurrentPage.Valid && book.ReadingProgress.TotalPages.Valid { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "
Page
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var40 string - templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(book.LastReadLabel()) + templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.CurrentPage.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 305, Col: 111} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 310, Col: 87} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 97, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 99, " / ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var41 string - templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(FormatTimestamptzInTimezone(book.ReadingProgress.LastReadAt, user.Timezone)) + templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.TotalPages.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 306, Col: 140} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 310, Col: 131} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var41)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 98, "
Source
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var42 string - templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.LastSyncSource.String) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 312, Col: 110} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 100, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var42 string + templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinStringErrs(book.LastReadLabel()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 315, Col: 111} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 102, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var43 string + templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(FormatTimestamptzInTimezone(book.ReadingProgress.LastReadAt, user.Timezone)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 316, Col: 140} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 103, "
Source
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var44 string + templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(book.ReadingProgress.LastSyncSource.String) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 322, Col: 110} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var44 string - templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(book.TimeStatLabel()) + var templ_7745c5c3_Var46 string + templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(book.TimeStatLabel()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 324, Col: 110} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 334, Col: 110} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 105, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.BookStats.TotalMinutes >= 60 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 106, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var45 string - templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%dh %dmin", book.BookStats.TotalMinutes/60, book.BookStats.TotalMinutes%60)) + var templ_7745c5c3_Var47 string + templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%dh %dmin", book.BookStats.TotalMinutes/60, book.BookStats.TotalMinutes%60)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 326, Col: 157} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 336, Col: 157} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 107, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 112, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 108, "") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var46 string - templ_7745c5c3_Var46, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d min", book.BookStats.TotalMinutes)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 328, Col: 119} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var46)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 109, "
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 110, "Sessions
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var47 string - templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", book.BookStats.SessionCount)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 333, Col: 114} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var47)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 111, "
Time listened
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var48 string - templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(book.TimeListenedLabel()) + templ_7745c5c3_Var48, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d min", book.BookStats.TotalMinutes)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 338, Col: 106} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 338, Col: 119} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var48)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 113, "
Pages Synced
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var49 string - templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", book.BookStats.TotalPages)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 343, Col: 113} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "
Finished
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "Sessions
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var49 string + templ_7745c5c3_Var49, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", book.BookStats.SessionCount)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 343, Col: 114} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var49)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "
Time listened
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var50 string + templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.JoinStringErrs(book.TimeListenedLabel()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 348, Col: 106} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var50)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "
Pages Synced
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var51 string + templ_7745c5c3_Var51, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", book.BookStats.TotalPages)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 353, Col: 113} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var51)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "
Finished
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if book.BookStats.Finished { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "✓
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "✓
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "—
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "—
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "Publisher
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var50 string - templ_7745c5c3_Var50, templ_7745c5c3_Err = templ.JoinStringErrs(book.Publisher.String) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 364, Col: 69} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var50)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "
Published
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var51 string - templ_7745c5c3_Var51, templ_7745c5c3_Err = templ.JoinStringErrs(book.DatePublished.Time.Format("01-02-2006")) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 370, Col: 92} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var51)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "
ISBN
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "
Publisher
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var52 string - templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(book.Isbn.String) + templ_7745c5c3_Var52, templ_7745c5c3_Err = templ.JoinStringErrs(book.Publisher.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 376, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 374, Col: 69} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var52)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "
Language
") + if book.DatePublished.Valid { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, "
Published
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var53 string - templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(book.Language.String) + templ_7745c5c3_Var53, templ_7745c5c3_Err = templ.JoinStringErrs(book.DatePublished.Time.Format("01-02-2006")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 382, Col: 87} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 380, Col: 92} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var53)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, "
Narrator
") + if book.Isbn.Valid && book.Isbn.String != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, "
ISBN
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var54 string - templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(book.Narrators, ", ")) + templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(book.Isbn.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 388, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 386, Col: 64} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, "
Duration
") + if book.Language.Valid && book.Language.String != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, "
Language
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var55 string - templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(book.AudioDurationLabel()) + templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(book.Language.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 394, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 392, Col: 87} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var55)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, "
Abridged
Yes
Edition
") + if book.IsAudio() && len(book.Narrators) > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, "
Narrator
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var56 string - templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(book.Edition.String) + templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(book.Narrators, ", ")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 406, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 398, Col: 82} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56)) if templ_7745c5c3_Err != nil { @@ -1207,15 +1206,15 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string, tombs return templ_7745c5c3_Err } } - if book.PageCount.Valid && book.PageCount.Int32 > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, "
Pages
") + if book.IsAudio() && book.AudioDuration() > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, "
Duration
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var57 string - templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(book.PageCount.Int32) + templ_7745c5c3_Var57, templ_7745c5c3_Err = templ.JoinStringErrs(book.AudioDurationLabel()) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 412, Col: 68} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 404, Col: 94} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var57)) if templ_7745c5c3_Err != nil { @@ -1226,512 +1225,556 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string, tombs return templ_7745c5c3_Err } } - if book.Genre.Valid && book.Genre.String != "" { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "
Genre
") + if book.IsAudio() && book.Abridged { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "
Abridged
Yes
Edition
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var58 string - templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(book.Genre.String) + templ_7745c5c3_Var58, templ_7745c5c3_Err = templ.JoinStringErrs(book.Edition.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 418, Col: 65} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 416, Col: 67} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var58)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "
Series Count
") + if book.PageCount.Valid && book.PageCount.Int32 > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, "
Pages
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var59 string - templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(book.SeriesCount.Int32) + templ_7745c5c3_Var59, templ_7745c5c3_Err = templ.JoinStringErrs(book.PageCount.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 424, Col: 70} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 422, Col: 68} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var59)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, " items
Volume
Vol. ") + if book.Genre.Valid && book.Genre.String != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "
Genre
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var60 string - templ_7745c5c3_Var60, templ_7745c5c3_Err = templ.JoinStringErrs(book.Volume.Int32) + templ_7745c5c3_Var60, templ_7745c5c3_Err = templ.JoinStringErrs(book.Genre.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 430, Col: 70} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 428, Col: 65} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var60)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "
Imprint
") + if book.SeriesCount.Valid && book.SeriesCount.Int32 > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 145, "
Series Count
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var61 string - templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(book.Imprint.String) + templ_7745c5c3_Var61, templ_7745c5c3_Err = templ.JoinStringErrs(book.SeriesCount.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 436, Col: 67} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 434, Col: 70} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var61)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 145, "
Copyright
") + if book.Volume.Valid && book.Volume.Int32 > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "
Volume
Vol. ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var62 string - templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(book.CopyrightYear.Int32) + templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(book.Volume.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 442, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 440, Col: 70} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "
Manga Type
") + if book.Imprint.Valid && book.Imprint.String != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "
Imprint
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var63 string - templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ReplaceAll(book.MangaType.String, "_", " ")) + templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(book.Imprint.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 448, Col: 118} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 446, Col: 67} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var63)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "
Scan Info
") + if book.CopyrightYear.Valid && book.CopyrightYear.Int32 > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "
Copyright
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var64 string - templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.JoinStringErrs(book.ScanInformation.String) + templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.JoinStringErrs(book.CopyrightYear.Int32) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 454, Col: 94} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 452, Col: 72} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var64)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "
Alternate Series
") + if book.MangaType.Valid && book.MangaType.String != "" && book.MangaType.String != "unknown" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 153, "
Manga Type
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var65 string - templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(altSeries) + templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ReplaceAll(book.MangaType.String, "_", " ")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 460, Col: 57} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 458, Col: 118} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 153, "
Contributors
") + if book.ScanInformation.Valid && book.ScanInformation.String != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 155, "
Scan Info
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var66 string - templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(book.Contributors, ", ")) + templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.JoinStringErrs(book.ScanInformation.String) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 466, Col: 85} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 464, Col: 94} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var66)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 155, "
Format
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + if altSeries := getAlternateSeries(book.AlternateInfo); altSeries != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 157, "
Alternate Series
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var67 string + templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.JoinStringErrs(altSeries) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 470, Col: 57} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var67)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "
File Size
") + if len(book.Contributors) > 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, "
Contributors
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var68 string - templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(formatFileSize(book.FileSize.Int64)) + templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(book.Contributors, ", ")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 476, Col: 82} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 476, Col: 85} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, "
Format
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var69 string + templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(book.MimeType.String) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 481, Col: 67} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var69)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "
File Size
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var70 string + templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(formatFileSize(book.FileSize.Int64)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 486, Col: 82} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var70)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "
Location
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "
Location
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var69 string - templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(book.FileLocation) + var templ_7745c5c3_Var71 string + templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.JoinStringErrs(book.FileLocation) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 482, Col: 113} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 492, Col: 113} } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var69)) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var71)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, "
Markdown — renders like notes. Saving an empty review deletes it.
Markdown — renders like notes. Saving an empty review deletes it.