refactor: pass watch order mode and paginate command palette
This commit is contained in:
@@ -1,18 +1,19 @@
|
|||||||
package anime
|
package anime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"mal/internal/db"
|
"mal/internal/db"
|
||||||
"mal/internal/domain"
|
"mal/internal/domain"
|
||||||
"mal/internal/server"
|
"mal/internal/server"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const commandPaletteAnimeLimit = 24
|
||||||
|
|
||||||
type commandPaletteItem struct {
|
type commandPaletteItem struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@@ -23,6 +24,12 @@ type commandPaletteItem struct {
|
|||||||
Icon string `json:"icon,omitempty"`
|
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) {
|
func (h *AnimeHandler) HandleCommandPalette(c *gin.Context) {
|
||||||
user := server.CurrentUser(c)
|
user := server.CurrentUser(c)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
@@ -31,24 +38,40 @@ func (h *AnimeHandler) HandleCommandPalette(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query := strings.TrimSpace(c.Query("q"))
|
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 != "" {
|
if query != "" {
|
||||||
|
hasNextPage := false
|
||||||
if len(query) >= 2 {
|
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)...)
|
if page == 1 {
|
||||||
items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...)
|
items = append(items, h.commandPaletteNavigationItems(query)...)
|
||||||
items = append(items, h.commandPalettePersonalItems(c, user.ID, query)...)
|
items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...)
|
||||||
c.JSON(http.StatusOK, items)
|
items = append(items, h.commandPalettePersonalItems(c, user.ID, query)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, commandPaletteResponse{
|
||||||
|
Items: items,
|
||||||
|
HasNextPage: hasNextPage,
|
||||||
|
NextPage: page + 1,
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...)
|
items = append(items, h.commandPaletteContinueItems(c, user.ID, query)...)
|
||||||
items = append(items, h.commandPaletteNavigationItems(query)...)
|
items = append(items, h.commandPaletteNavigationItems(query)...)
|
||||||
items = append(items, h.commandPalettePersonalItems(c, user.ID, 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 {
|
func (h *AnimeHandler) commandPaletteNavigationItems(query string) []commandPaletteItem {
|
||||||
@@ -71,13 +94,10 @@ func (h *AnimeHandler) commandPaletteNavigationItems(query string) []commandPale
|
|||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string) []commandPaletteItem {
|
func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string, page int) ([]commandPaletteItem, bool) {
|
||||||
searchCtx, cancel := context.WithTimeout(c.Request.Context(), 800*time.Millisecond)
|
res, err := h.svc.SearchAdvanced(c.Request.Context(), query, "", "", "", "", nil, 0, true, page, commandPaletteAnimeLimit)
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
res, err := h.svc.SearchAdvanced(searchCtx, query, "", "", "", "", nil, 0, true, 1, 24)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
animes := wrapAnimes(res.Animes)
|
animes := wrapAnimes(res.Animes)
|
||||||
@@ -92,7 +112,7 @@ func (h *AnimeHandler) commandPaletteAnimeResults(c *gin.Context, query string)
|
|||||||
Image: anime.ImageURL(),
|
Image: anime.ImageURL(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return items
|
return items, res.HasNextPage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AnimeHandler) commandPalettePersonalItems(c *gin.Context, userID string, query string) []commandPaletteItem {
|
func (h *AnimeHandler) commandPalettePersonalItems(c *gin.Context, userID string, query string) []commandPaletteItem {
|
||||||
|
|||||||
@@ -756,11 +756,12 @@ func (h *AnimeHandler) HandleHTMLWatchOrder(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userID := server.CurrentUserID(c)
|
userID := server.CurrentUserID(c)
|
||||||
|
mode := jikan.NormalizeWatchOrderMode(c.Query("mode"))
|
||||||
|
|
||||||
relationsCtx, cancel := context.WithTimeout(c.Request.Context(), watchOrderTimeout)
|
relationsCtx, cancel := context.WithTimeout(c.Request.Context(), watchOrderTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
relations, err := h.svc.GetRelations(relationsCtx, id)
|
relations, err := h.svc.GetRelations(relationsCtx, id, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
observability.Warn(
|
observability.Warn(
|
||||||
"relations_fetch_failed",
|
"relations_fetch_failed",
|
||||||
@@ -774,6 +775,7 @@ func (h *AnimeHandler) HandleHTMLWatchOrder(c *gin.Context) {
|
|||||||
c.HTML(http.StatusOK, "anime.gohtml", gin.H{
|
c.HTML(http.StatusOK, "anime.gohtml", gin.H{
|
||||||
"_fragment": "watch_order_loading",
|
"_fragment": "watch_order_loading",
|
||||||
"AnimeID": id,
|
"AnimeID": id,
|
||||||
|
"Mode": string(mode),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -790,6 +792,7 @@ func (h *AnimeHandler) HandleHTMLWatchOrder(c *gin.Context) {
|
|||||||
"_fragment": "watch_order",
|
"_fragment": "watch_order",
|
||||||
"Relations": relations,
|
"Relations": relations,
|
||||||
"AnimeID": id,
|
"AnimeID": id,
|
||||||
|
"Mode": string(mode),
|
||||||
"WatchlistMap": watchlistMap,
|
"WatchlistMap": watchlistMap,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -588,8 +588,8 @@ func (s *animeService) GetRecommendations(ctx context.Context, id int) ([]domain
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *animeService) GetRelations(ctx context.Context, id int) ([]jikan.RelationEntry, error) {
|
func (s *animeService) GetRelations(ctx context.Context, id int, mode jikan.WatchOrderMode) ([]jikan.RelationEntry, error) {
|
||||||
return s.jikan.GetFullRelations(ctx, id)
|
return s.jikan.GetFullRelations(ctx, id, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *animeService) WarmDetailSections(id int) {
|
func (s *animeService) WarmDetailSections(id int) {
|
||||||
|
|||||||
Reference in New Issue
Block a user