From 7397085ecbb2310422ac2c75c291449d7aea023f Mon Sep 17 00:00:00 2001 From: Admin Date: Sun, 1 Mar 2026 22:22:42 +0500 Subject: [PATCH] =?UTF-8?q?Fix=20ranking=20pagination:=20sliding=20=C2=B12?= =?UTF-8?q?=20window=20around=20current=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rankingPageNums now takes a current page parameter and always renders first 2, last 2, and current±2 — so navigating to page 3 shows 1 2 3 4 5 … 80 81 instead of only the fixed quarter-mark anchors. --- scraper/internal/server/ui.go | 45 ++++++++++++++--------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/scraper/internal/server/ui.go b/scraper/internal/server/ui.go index 7c127e3..7bd867c 100644 --- a/scraper/internal/server/ui.go +++ b/scraper/internal/server/ui.go @@ -881,47 +881,38 @@ type pageNum struct { Num int } -// rankingPageNums builds the dynamic pagination list for 100 pages with -// smart ellipsis: always show the first 3, last 3, and a sliding window of -// 3 around the ends — compressed with "…" separators between runs. -// -// For a flat 100-page list it produces: -// -// 1 2 3 … 6 7 8 … 93 94 95 … 98 99 100 -// -// (The middle range is omitted intentionally; users click individual pages.) -func rankingPageNums(total int) []pageNum { +// rankingPageNums builds a pagination list with smart ellipsis. +// It always shows: first 2, last 2, and a ±2 window around current. +// Gaps between non-consecutive runs are filled with a sentinel (Num==0) for "…". +// Pass current=0 when there is no concept of a current page (e.g. fetch bar). +func rankingPageNums(total, current int) []pageNum { if total <= 0 { return nil } - // Build the set of visible page numbers using a sliding-window approach. show := make(map[int]bool) - // Always show first 3 and last 3. - for i := 1; i <= 3 && i <= total; i++ { + // First 2 and last 2. + for i := 1; i <= 2 && i <= total; i++ { show[i] = true } - for i := total - 2; i <= total; i++ { + for i := total - 1; i <= total; i++ { if i >= 1 { show[i] = true } } - // For large ranges, show a few pages near the 1/4 and 3/4 marks. - if total > 12 { - q1 := total / 4 - q3 := total * 3 / 4 - for _, p := range []int{q1 - 1, q1, q1 + 1, q3 - 1, q3, q3 + 1} { - if p >= 1 && p <= total { - show[p] = true + // ±2 window around current page. + if current > 0 { + for i := current - 2; i <= current+2; i++ { + if i >= 1 && i <= total { + show[i] = true } } } - // Collect sorted visible pages. + // Collect and sort. pages := make([]int, 0, len(show)) for p := range show { pages = append(pages, p) } - // Sort pages slice. for i := 0; i < len(pages); i++ { for j := i + 1; j < len(pages); j++ { if pages[j] < pages[i] { @@ -930,11 +921,11 @@ func rankingPageNums(total int) []pageNum { } } - // Build output with ellipsis sentinels (Num==0) between non-consecutive pages. + // Build output with ellipsis sentinels between non-consecutive pages. out := make([]pageNum, 0, len(pages)*2) for i, p := range pages { if i > 0 && p > pages[i-1]+1 { - out = append(out, pageNum{0}) // ellipsis + out = append(out, pageNum{0}) } out = append(out, pageNum{p}) } @@ -1015,8 +1006,8 @@ func (s *Server) handleRanking(w http.ResponseWriter, r *http.Request) { }{ Books: toRankingViewItems(pageItems, s.writer.LocalSlugs()), CachedAt: cachedAt, - FetchNums: rankingPageNums(100), - DisplayNums: rankingPageNums(totalPages), + FetchNums: rankingPageNums(100, 0), + DisplayNums: rankingPageNums(totalPages, currentPage), CurrentPage: currentPage, TotalPages: totalPages, TotalItems: totalItems,