refactor: reduce cyclomatic complexity of HandleBrowse
This commit is contained in:
@@ -448,29 +448,33 @@ func (h *AnimeHandler) HandleScheduleSection(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
|
type browseQuery struct {
|
||||||
q := c.Query("q")
|
q string
|
||||||
animeType := c.Query("type")
|
animeType string
|
||||||
status := c.Query("status")
|
status string
|
||||||
orderBy := c.Query("order_by")
|
orderBy string
|
||||||
sort := c.Query("sort")
|
sort string
|
||||||
sfw := c.Query("sfw") != "false"
|
sfw bool
|
||||||
|
studioID int
|
||||||
|
genres []int
|
||||||
|
page int
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBrowseQuery(c *gin.Context) (browseQuery, error) {
|
||||||
studioID := 0
|
studioID := 0
|
||||||
if raw := strings.TrimSpace(c.Query("studio")); raw != "" {
|
if raw := strings.TrimSpace(c.Query("studio")); raw != "" {
|
||||||
id, err := strconv.Atoi(raw)
|
id, err := strconv.Atoi(raw)
|
||||||
if err != nil || id < 0 {
|
if err != nil || id < 0 {
|
||||||
server.RespondHTMLOrJSONError(c, http.StatusBadRequest, "invalid studio id")
|
return browseQuery{}, fmt.Errorf("invalid studio id")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
studioID = id
|
studioID = id
|
||||||
}
|
}
|
||||||
|
|
||||||
var genres []int
|
genres := make([]int, 0, len(c.QueryArray("genres")))
|
||||||
for _, g := range c.QueryArray("genres") {
|
for _, g := range c.QueryArray("genres") {
|
||||||
id, err := strconv.Atoi(g)
|
id, err := strconv.Atoi(g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.RespondHTMLOrJSONError(c, http.StatusBadRequest, "invalid genre id")
|
return browseQuery{}, fmt.Errorf("invalid genre id")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if id > 0 {
|
if id > 0 {
|
||||||
genres = append(genres, id)
|
genres = append(genres, id)
|
||||||
@@ -479,33 +483,139 @@ func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
|
|||||||
|
|
||||||
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.RespondHTMLOrJSONError(c, http.StatusBadRequest, "invalid page")
|
return browseQuery{}, fmt.Errorf("invalid page")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
page = 1
|
page = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := h.svc.SearchAdvanced(c.Request.Context(), q, animeType, status, orderBy, sort, genres, studioID, sfw, page, 24)
|
return browseQuery{
|
||||||
|
q: c.Query("q"),
|
||||||
|
animeType: c.Query("type"),
|
||||||
|
status: c.Query("status"),
|
||||||
|
orderBy: c.Query("order_by"),
|
||||||
|
sort: c.Query("sort"),
|
||||||
|
sfw: c.Query("sfw") != "false",
|
||||||
|
studioID: studioID,
|
||||||
|
genres: genres,
|
||||||
|
page: page,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func browseStudioName(ctx context.Context, svc Service, studioID int) string {
|
||||||
|
if studioID <= 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
name, err := svc.GetProducerNameByID(ctx, studioID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.RespondError(
|
return ""
|
||||||
c,
|
}
|
||||||
http.StatusInternalServerError,
|
|
||||||
"browse_search_failed",
|
return name
|
||||||
"anime",
|
}
|
||||||
"failed to load browse results",
|
|
||||||
map[string]any{
|
func browseTemplateData(
|
||||||
"q": q,
|
q browseQuery,
|
||||||
"type": animeType,
|
studioName string,
|
||||||
"status": status,
|
genresList []domain.Genre,
|
||||||
"order_by": orderBy,
|
animes []domain.Anime,
|
||||||
"sort": sort,
|
user any,
|
||||||
"studio": studioID,
|
watchlistMap map[int64]bool,
|
||||||
"sfw": sfw,
|
hasNextPage bool,
|
||||||
"page": page,
|
) gin.H {
|
||||||
},
|
return gin.H{
|
||||||
err,
|
"CurrentPath": "/browse",
|
||||||
)
|
"Query": q.q,
|
||||||
|
"Type": q.animeType,
|
||||||
|
"Status": q.status,
|
||||||
|
"OrderBy": q.orderBy,
|
||||||
|
"Sort": q.sort,
|
||||||
|
"Genres": q.genres,
|
||||||
|
"Studio": q.studioID,
|
||||||
|
"StudioName": studioName,
|
||||||
|
"SFW": q.sfw,
|
||||||
|
"GenresList": genresList,
|
||||||
|
"Animes": animes,
|
||||||
|
"HasNextPage": hasNextPage,
|
||||||
|
"NextPage": q.page + 1,
|
||||||
|
"User": user,
|
||||||
|
"WatchlistMap": watchlistMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *AnimeHandler) searchBrowse(ctx context.Context, query browseQuery) (jikan.SearchResult, error) {
|
||||||
|
return h.svc.SearchAdvanced(
|
||||||
|
ctx,
|
||||||
|
query.q,
|
||||||
|
query.animeType,
|
||||||
|
query.status,
|
||||||
|
query.orderBy,
|
||||||
|
query.sort,
|
||||||
|
query.genres,
|
||||||
|
query.studioID,
|
||||||
|
query.sfw,
|
||||||
|
query.page,
|
||||||
|
24,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func browseScrollData(
|
||||||
|
query browseQuery,
|
||||||
|
studioName string,
|
||||||
|
animes []domain.Anime,
|
||||||
|
watchlistMap map[int64]bool,
|
||||||
|
hasNextPage bool,
|
||||||
|
) gin.H {
|
||||||
|
return gin.H{
|
||||||
|
"_fragment": "anime_card_scroll",
|
||||||
|
"Animes": animes,
|
||||||
|
"NextPage": query.page + 1,
|
||||||
|
"HasNextPage": hasNextPage,
|
||||||
|
"Query": query.q,
|
||||||
|
"Type": query.animeType,
|
||||||
|
"Status": query.status,
|
||||||
|
"OrderBy": query.orderBy,
|
||||||
|
"Sort": query.sort,
|
||||||
|
"Genres": query.genres,
|
||||||
|
"Studio": query.studioID,
|
||||||
|
"StudioName": studioName,
|
||||||
|
"SFW": query.sfw,
|
||||||
|
"WatchlistMap": watchlistMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *AnimeHandler) respondBrowseSearchError(c *gin.Context, query browseQuery, err error) {
|
||||||
|
server.RespondError(
|
||||||
|
c,
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
"browse_search_failed",
|
||||||
|
"anime",
|
||||||
|
"failed to load browse results",
|
||||||
|
map[string]any{
|
||||||
|
"q": query.q,
|
||||||
|
"type": query.animeType,
|
||||||
|
"status": query.status,
|
||||||
|
"order_by": query.orderBy,
|
||||||
|
"sort": query.sort,
|
||||||
|
"studio": query.studioID,
|
||||||
|
"sfw": query.sfw,
|
||||||
|
"page": query.page,
|
||||||
|
},
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
|
||||||
|
query, err := parseBrowseQuery(c)
|
||||||
|
if err != nil {
|
||||||
|
server.RespondHTMLOrJSONError(c, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := h.searchBrowse(c.Request.Context(), query)
|
||||||
|
if err != nil {
|
||||||
|
h.respondBrowseSearchError(c, query, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,54 +623,15 @@ func (h *AnimeHandler) HandleBrowse(c *gin.Context) {
|
|||||||
userID := server.CurrentUserID(c)
|
userID := server.CurrentUserID(c)
|
||||||
animes := wrapAnimes(res.Animes)
|
animes := wrapAnimes(res.Animes)
|
||||||
watchlistMap := h.watchlistMapForAnimes(c.Request.Context(), userID, animes)
|
watchlistMap := h.watchlistMapForAnimes(c.Request.Context(), userID, animes)
|
||||||
|
studioName := browseStudioName(c.Request.Context(), h.svc, query.studioID)
|
||||||
|
|
||||||
studioName := ""
|
if c.GetHeader("HX-Request") == "true" && query.page > 1 {
|
||||||
if studioID > 0 {
|
c.HTML(http.StatusOK, "browse.gohtml", browseScrollData(query, studioName, animes, watchlistMap, res.HasNextPage))
|
||||||
name, err := h.svc.GetProducerNameByID(c.Request.Context(), studioID)
|
|
||||||
if err == nil {
|
|
||||||
studioName = name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GetHeader("HX-Request") == "true" && page > 1 {
|
|
||||||
c.HTML(http.StatusOK, "browse.gohtml", gin.H{
|
|
||||||
"_fragment": "anime_card_scroll",
|
|
||||||
"Animes": animes,
|
|
||||||
"NextPage": page + 1,
|
|
||||||
"HasNextPage": res.HasNextPage,
|
|
||||||
"Query": q,
|
|
||||||
"Type": animeType,
|
|
||||||
"Status": status,
|
|
||||||
"OrderBy": orderBy,
|
|
||||||
"Sort": sort,
|
|
||||||
"Genres": genres,
|
|
||||||
"Studio": studioID,
|
|
||||||
"StudioName": studioName,
|
|
||||||
"SFW": sfw,
|
|
||||||
"WatchlistMap": watchlistMap,
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
genresList, _ := h.svc.GetGenres(c.Request.Context())
|
genresList, _ := h.svc.GetGenres(c.Request.Context())
|
||||||
browseData := gin.H{
|
browseData := browseTemplateData(query, studioName, genresList, animes, user, watchlistMap, res.HasNextPage)
|
||||||
"CurrentPath": "/browse",
|
|
||||||
"Query": q,
|
|
||||||
"Type": animeType,
|
|
||||||
"Status": status,
|
|
||||||
"OrderBy": orderBy,
|
|
||||||
"Sort": sort,
|
|
||||||
"Genres": genres,
|
|
||||||
"Studio": studioID,
|
|
||||||
"StudioName": studioName,
|
|
||||||
"SFW": sfw,
|
|
||||||
"GenresList": genresList,
|
|
||||||
"Animes": animes,
|
|
||||||
"HasNextPage": res.HasNextPage,
|
|
||||||
"NextPage": page + 1,
|
|
||||||
"User": user,
|
|
||||||
"WatchlistMap": watchlistMap,
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GetHeader("HX-Request") == "true" {
|
if c.GetHeader("HX-Request") == "true" {
|
||||||
browseData["_fragment"] = "browse_content"
|
browseData["_fragment"] = "browse_content"
|
||||||
|
|||||||
Reference in New Issue
Block a user