watch: sync watchlist status between watch and details page
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user