From 35a367d569d7e7ed1f5c57eb46358a1055a4b2a8 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Fri, 12 Jun 2026 13:39:58 +0200 Subject: [PATCH] refactor: pass watch order mode and paginate command palette --- internal/anime/command_palette.go | 52 +++++++++++++++++++++---------- internal/anime/handler.go | 5 ++- internal/anime/service.go | 4 +-- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/internal/anime/command_palette.go b/internal/anime/command_palette.go index 61833da..7e4a955 100644 --- a/internal/anime/command_palette.go +++ b/internal/anime/command_palette.go @@ -1,18 +1,19 @@ package anime import ( - "context" "fmt" "mal/internal/db" "mal/internal/domain" "mal/internal/server" "net/http" + "strconv" "strings" - "time" "github.com/gin-gonic/gin" ) +const commandPaletteAnimeLimit = 24 + type commandPaletteItem struct { ID string `json:"id"` Type string `json:"type"` @@ -23,6 +24,12 @@ type commandPaletteItem struct { Icon string `json:"icon,omitempty"` } +type commandPaletteResponse struct { + Items []commandPaletteItem `json:"items"` + HasNextPage bool `json:"hasNextPage"` + NextPage int `json:"nextPage,omitempty"` +} + func (h *AnimeHandler) HandleCommandPalette(c *gin.Context) { user := server.CurrentUser(c) if user == nil { @@ -31,24 +38,40 @@ func (h *AnimeHandler) HandleCommandPalette(c *gin.Context) { } query := strings.TrimSpace(c.Query("q")) - items := make([]commandPaletteItem, 0, 12) + page, err := strconv.Atoi(c.DefaultQuery("page", "1")) + if err != nil || page < 1 { + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid page"}) + return + } + + items := make([]commandPaletteItem, 0, commandPaletteAnimeLimit) if query != "" { + hasNextPage := false if len(query) >= 2 { - items = append(items, h.commandPaletteAnimeResults(c, query)...) + var animeItems []commandPaletteItem + animeItems, hasNextPage = h.commandPaletteAnimeResults(c, query, page) + items = append(items, animeItems...) } - items = append(items, h.commandPaletteNavigationItems(query)...) - items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...) - items = append(items, h.commandPalettePersonalItems(c, user.ID, query)...) - c.JSON(http.StatusOK, items) + if page == 1 { + items = append(items, h.commandPaletteNavigationItems(query)...) + items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...) + items = append(items, h.commandPalettePersonalItems(c, user.ID, query)...) + } + + c.JSON(http.StatusOK, commandPaletteResponse{ + Items: items, + HasNextPage: hasNextPage, + NextPage: page + 1, + }) return } items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...) items = append(items, h.commandPaletteNavigationItems(query)...) items = append(items, h.commandPalettePersonalItems(c, user.ID, query)...) - c.JSON(http.StatusOK, items) + c.JSON(http.StatusOK, commandPaletteResponse{Items: items}) } func (h *AnimeHandler) commandPaletteNavigationItems(query string) []commandPaletteItem { @@ -71,13 +94,10 @@ func (h *AnimeHandler) commandPaletteNavigationItems(query string) []commandPale return filtered } -func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string) []commandPaletteItem { - searchCtx, cancel := context.WithTimeout(c.Request.Context(), 800*time.Millisecond) - defer cancel() - - res, err := h.svc.SearchAdvanced(searchCtx, query, "", "", "", "", nil, 0, true, 1, 24) +func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string, page int) ([]commandPaletteItem, bool) { + res, err := h.svc.SearchAdvanced(c.Request.Context(), query, "", "", "", "", nil, 0, true, page, commandPaletteAnimeLimit) if err != nil { - return nil + return nil, false } animes := wrapAnimes(res.Animes) @@ -92,7 +112,7 @@ func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string) Image: anime.ImageURL(), }) } - return items + return items, res.HasNextPage } func (h *AnimeHandler) commandPalettePersonalItems(c *gin.Context, userID string, query string) []commandPaletteItem { diff --git a/internal/anime/handler.go b/internal/anime/handler.go index 40de2e7..c7164e6 100644 --- a/internal/anime/handler.go +++ b/internal/anime/handler.go @@ -756,11 +756,12 @@ func (h *AnimeHandler) HandleHTMLWatchOrder(c *gin.Context) { } userID := server.CurrentUserID(c) + mode := jikan.NormalizeWatchOrderMode(c.Query("mode")) relationsCtx, cancel := context.WithTimeout(c.Request.Context(), watchOrderTimeout) defer cancel() - relations, err := h.svc.GetRelations(relationsCtx, id) + relations, err := h.svc.GetRelations(relationsCtx, id, mode) if err != nil { observability.Warn( "relations_fetch_failed", @@ -774,6 +775,7 @@ func (h *AnimeHandler) HandleHTMLWatchOrder(c *gin.Context) { c.HTML(http.StatusOK, "anime.gohtml", gin.H{ "_fragment": "watch_order_loading", "AnimeID": id, + "Mode": string(mode), }) return } @@ -790,6 +792,7 @@ func (h *AnimeHandler) HandleHTMLWatchOrder(c *gin.Context) { "_fragment": "watch_order", "Relations": relations, "AnimeID": id, + "Mode": string(mode), "WatchlistMap": watchlistMap, }) } diff --git a/internal/anime/service.go b/internal/anime/service.go index b1674fd..79f45eb 100644 --- a/internal/anime/service.go +++ b/internal/anime/service.go @@ -588,8 +588,8 @@ func (s *animeService) GetRecommendations(ctx context.Context, id int) ([]domain return out, nil } -func (s *animeService) GetRelations(ctx context.Context, id int) ([]jikan.RelationEntry, error) { - return s.jikan.GetFullRelations(ctx, id) +func (s *animeService) GetRelations(ctx context.Context, id int, mode jikan.WatchOrderMode) ([]jikan.RelationEntry, error) { + return s.jikan.GetFullRelations(ctx, id, mode) } func (s *animeService) WarmDetailSections(id int) {