watch: sync watchlist status between watch and details page

This commit is contained in:
2026-04-18 06:26:13 +02:00
parent 9bddd30daf
commit c8e8b80b75
4 changed files with 41 additions and 12 deletions

View File

@@ -11,7 +11,9 @@ import (
"strings"
"time"
"mal/internal/database"
"mal/internal/jikan"
"mal/internal/shared/middleware"
"mal/internal/templates"
)
@@ -75,7 +77,8 @@ func (h *Handler) HandleWatchPage(w http.ResponseWriter, r *http.Request) {
}
title := anime.DisplayTitle()
data, err := h.svc.BuildWatchPageData(ctx, malID, title, episode, mode)
userID := watchlistUserIDFromRequest(r)
data, err := h.svc.BuildWatchPageData(ctx, malID, title, episode, mode, userID)
if err != nil {
log.Printf("watch page error for mal_id=%d: %v", malID, err)
http.Error(w, "Failed to load playback", http.StatusBadGateway)
@@ -87,6 +90,7 @@ func (h *Handler) HandleWatchPage(w http.ResponseWriter, r *http.Request) {
MalID: data.MalID,
Title: data.Title,
CurrentEpisode: data.CurrentEpisode,
CurrentStatus: data.CurrentStatus,
InitialMode: data.InitialMode,
AvailableModes: data.AvailableModes,
ModeSources: convertModeSources(data.ModeSources),
@@ -96,6 +100,15 @@ func (h *Handler) HandleWatchPage(w http.ResponseWriter, r *http.Request) {
templates.WatchPage(anime, pageData).Render(r.Context(), w)
}
func watchlistUserIDFromRequest(r *http.Request) string {
user, ok := r.Context().Value(middleware.UserContextKey).(*database.User)
if !ok || user == nil {
return ""
}
return user.ID
}
func convertModeSources(sources map[string]ModeSource) map[string]templates.ModeSource {
result := make(map[string]templates.ModeSource, len(sources))
for k, v := range sources {

View File

@@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"io"
"mal/internal/database"
"net/http"
"net/url"
"sort"
@@ -22,6 +23,7 @@ type Service struct {
allAnimeClient *allAnimeClient
jikanClient *jikan.Client
httpClient *http.Client
db database.Querier
}
type sourceScore struct {
@@ -33,15 +35,16 @@ type sourceScore struct {
refererScore int
}
func NewService(jikanClient *jikan.Client) *Service {
func NewService(jikanClient *jikan.Client, db database.Querier) *Service {
return &Service{
allAnimeClient: newAllAnimeClient(),
jikanClient: jikanClient,
httpClient: &http.Client{Timeout: 12 * time.Second},
db: db,
}
}
func (s *Service) BuildWatchPageData(ctx context.Context, malID int, title string, episode string, mode string) (WatchPageData, error) {
func (s *Service) BuildWatchPageData(ctx context.Context, malID int, title string, episode string, mode string, userID string) (WatchPageData, error) {
if malID <= 0 {
return WatchPageData{}, errors.New("invalid mal id")
}
@@ -94,6 +97,17 @@ func (s *Service) BuildWatchPageData(ctx context.Context, malID int, title strin
segments := s.fetchSkipSegments(ctx, malID, normalizedEpisode)
currentStatus := ""
if userID != "" && s.db != nil {
entry, err := s.db.GetWatchListEntry(ctx, database.GetWatchListEntryParams{
UserID: userID,
AnimeID: int64(malID),
})
if err == nil {
currentStatus = entry.Status
}
}
watchTitle := strings.TrimSpace(resolvedTitle)
if watchTitle == "" {
watchTitle = strings.TrimSpace(title)
@@ -106,6 +120,7 @@ func (s *Service) BuildWatchPageData(ctx context.Context, malID int, title strin
MalID: malID,
Title: watchTitle,
CurrentEpisode: normalizedEpisode,
CurrentStatus: currentStatus,
InitialMode: initialMode,
AvailableModes: availableModes,
ModeSources: modeSources,

View File

@@ -41,12 +41,13 @@ type SkipSegment struct {
}
type WatchPageData struct {
MalID int
Title string
CurrentEpisode string
InitialMode string
AvailableModes []string
ModeSources map[string]ModeSource
Episodes []EpisodeListItem
Segments []SkipSegment
MalID int
Title string
CurrentEpisode string
CurrentStatus string
InitialMode string
AvailableModes []string
ModeSources map[string]ModeSource
Episodes []EpisodeListItem
Segments []SkipSegment
}

View File

@@ -28,7 +28,7 @@ func NewRouter(cfg Config) http.Handler {
animeSvc := anime.NewService(cfg.JikanClient, cfg.DB)
animeHandler := anime.NewHandler(animeSvc)
playbackSvc := playback.NewService(cfg.JikanClient)
playbackSvc := playback.NewService(cfg.JikanClient, cfg.DB)
playbackHandler := playback.NewHandler(playbackSvc, cfg.JikanClient)
// Serve static files