chore: delete dead progress handlers, no-op scar, split fused helper line

Batch H1 step 4:
- Handler GetUniversalProgress (progress.go) deleted — no route mounts
  it; only /api/progress/:id/history (GetProgressHistory) and the SSR
  /progress page exist. Note: the bruno universal-progress suite
  documents GET/PUT /api/progress/:id + /api/progress/device/:device_id
  — those routes do NOT exist server-side; that suite is stale
  documentation, flagged in the plan.
- Handler GetAllProgress deleted — unregistered near-copy of
  GetAllProgressData (which the /progress SSR page uses and stays).
- series.go: dropped the `_ = libTypes` no-op (libTypes IS used by the
  Badge line right below — the assignment stays).
- router/helpers.go: visibleLibraryIDsFor's signature and first
  statement were fused onto one line; split for readability. No
  behavior change.
This commit is contained in:
John O'Keefe committed 2026-10-17 10:29:00 -04:00
1 parent 8fc74c908a
commit 721139dc16
3 files changed
+5 -140

No files matched your search

+3 -138
View File
@@ -6,13 +6,11 @@ import (
"bookhoard/internal/utils"
"context"
"encoding/json"
"errors"
"net/http"
"strconv"
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"github.com/labstack/echo/v5"
)
@@ -31,72 +29,6 @@ func getDeviceIcon(deviceType string) string {
}
}
// GetUniversalProgress retrieves progress with all location references
func (h *Handler) GetUniversalProgress(c *echo.Context) error {
user := MustGetAuthenticatedUser(c)
mediaItemID, err := uuid.Parse(c.Param("id"))
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "invalid media item ID")
}
progress, err := h.db.GetUniversalProgress(context.Background(), database.GetUniversalProgressParams{
MediaItemID: pgtype.UUID{Bytes: mediaItemID, Valid: true},
UserID: pgtype.UUID{Bytes: user.ID.Bytes, Valid: true},
})
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return c.JSON(http.StatusOK, map[string]interface{}{
"media_item_id": mediaItemID,
"progress": nil,
})
}
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get progress")
}
response := map[string]interface{}{
"book_id": progress.MediaItemID.Bytes,
"format_group": progress.FormatGroup,
"universal_progress": map[string]interface{}{
"percentage": progress.Percentage.Float64,
},
"location_references": map[string]interface{}{
"percentage": progress.Percentage.Float64,
"page": int(progress.CurrentPage.Int32),
"total_pages": int(progress.TotalPages.Int32),
},
}
if progress.Epubcfi.Valid {
response["location_references"].(map[string]interface{})["epubcfi"] = progress.Epubcfi.String
}
if progress.Chapter.Valid {
response["location_references"].(map[string]interface{})["chapter"] = int(progress.Chapter.Int32)
}
if progress.ChapterProgress.Valid {
response["location_references"].(map[string]interface{})["chapter_progress"] = progress.ChapterProgress.Float64
}
if progress.CharacterOffset.Valid {
response["location_references"].(map[string]interface{})["character"] = progress.CharacterOffset.Int64
}
deviceSync := map[string]interface{}{}
if progress.LastSyncDevice.Valid {
deviceSync["device"] = progress.LastSyncDevice.String
}
if progress.LastSyncSource.Valid {
deviceSync["source"] = progress.LastSyncSource.String
}
if progress.LastSyncTimestamp.Valid {
deviceSync["last_sync"] = progress.LastSyncTimestamp.Time
}
if len(deviceSync) > 0 {
response["device_sync"] = deviceSync
}
return c.JSON(http.StatusOK, response)
}
// UpdateUniversalProgress updates progress with automatic conversion
// GetProgressHistory retrieves reading session history
func (h *Handler) GetProgressHistory(c *echo.Context) error {
@@ -168,76 +100,9 @@ func audioDurationFrom(raw []byte) float64 {
return payload.DurationSeconds
}
// GetAllProgress retrieves all progress for a user with sync source info
func (h *Handler) GetAllProgress(c *echo.Context) error {
user := MustGetAuthenticatedUser(c)
progressList := []ProgressWithMedia{}
mediaItems, err := h.db.ListMediaItems(c.Request().Context(), database.ListMediaItemsParams{
Limit: 1000, Offset: 0,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get media items")
}
for _, mediaItem := range mediaItems {
progress, err := h.db.GetUniversalProgress(c.Request().Context(), database.GetUniversalProgressParams{
MediaItemID: mediaItem.ID,
UserID: user.ID,
})
if err != nil {
continue
}
coverPath := utils.ResolveMediaURL(mediaItem.LibraryID, mediaItem.CoverImagePath)
author := ""
if mediaItem.Author.Valid {
author = mediaItem.Author.String
}
epubcfi := ""
if progress.Epubcfi.Valid {
epubcfi = progress.Epubcfi.String
}
deviceName := ""
if progress.LastSyncDevice.Valid {
deviceName = progress.LastSyncDevice.String
}
lastUpdated := ""
if progress.LastReadAt.Valid {
lastUpdated = utils.FormatTimeInTimezone(progress.LastReadAt.Time, user.Timezone.String)
}
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,
ProgressPercentage: progress.Percentage.Float64 * 100,
EpubCFI: epubcfi,
LastUpdated: lastUpdated,
DeviceIcon: getDeviceIcon(deviceName),
FormatGroup: mediaItem.FormatGroup,
EstimatedPages: wsync.EstimatedPages(mediaItem.TotalCharacters.Int64),
})
}
return c.JSON(http.StatusOK, map[string]interface{}{
"progress": progressList,
"total": len(progressList),
})
}
// GetAllProgressData retrieves all progress for a user with sync source info.
// The registered /progress SSR page renders this (frontend.go); the old
// GetAllProgress HTTP handler (an unregistered near-copy) was deleted.
func (h *Handler) GetAllProgressData(c *echo.Context) ([]ProgressWithMedia, error) {
user := MustGetAuthenticatedUser(c)
-1
View File
@@ -157,7 +157,6 @@ func (h *SeriesHandler) GetSeriesBooks(c *echo.Context) error {
for _, item := range books {
itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
libTypes := LibraryTypeMap(c.Request().Context(), h.db)
_ = libTypes
bookCards = append(bookCards, BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
+2 -1
View File
@@ -252,7 +252,8 @@ func resolveLibrary(c *echo.Context, cfg *Config, userUUID string) LibraryResolu
// visibleLibraryIDsFor returns the requester's visible-library id set (for
// membership checks) plus the ids themselves (for SQL ANY() filters).
func visibleLibraryIDsFor(c *echo.Context, cfg *Config) (map[string]bool, []pgtype.UUID, error) { userUUIDStr, ok := c.Get("user_id").(string)
func visibleLibraryIDsFor(c *echo.Context, cfg *Config) (map[string]bool, []pgtype.UUID, error) {
userUUIDStr, ok := c.Get("user_id").(string)
if !ok {
return nil, nil, echo.NewHTTPError(http.StatusUnauthorized, "invalid user")
}