mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
Improve CreatePaginator with flexible margins and validation
This commit improves the CreatePaginator function by adding support for customisable page margins and dropdown offsets. It also introduces input validation and error handling to ensure proper usage.
This commit is contained in:
@@ -176,7 +176,7 @@
|
||||
|
||||
<!-- Pagination -->
|
||||
{{- url := unfinishedQuery(.QueriesC, "page") }}
|
||||
{{- paginationData := createPaginator(url, "#checkpoint", .Page, -1) }}
|
||||
{{- paginationData := createPaginator(url, "#checkpoint", .Page, -1, 1, 5) }}
|
||||
{{- yield pagination(data=paginationData) }}
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
@@ -160,42 +160,81 @@ func ParseTimeCustomFormat(date time.Time, format string) string {
|
||||
return date.Format(format)
|
||||
}
|
||||
|
||||
// CreatePaginator generates pagination data based on the current page and maximum number of pages
|
||||
func CreatePaginator(base, ending string, current_page, max_page int) PaginationData {
|
||||
// CreatePaginator generates pagination data based on the current page and maximum number of pages.
|
||||
// It returns a PaginationData struct containing all necessary information for rendering pagination controls.
|
||||
//
|
||||
// Parameters:
|
||||
// - base: The base part of the pagination URL
|
||||
// - ending: The ending part of the pagination URL
|
||||
// - current_page: The current page being displayed
|
||||
// - max_page: Maximum number of pages (-1 if unknown)
|
||||
// - page_margin: Number of pages to display before and after the current page
|
||||
// - dropdown_offset: Number of pages to include in dropdown before and after current page
|
||||
func CreatePaginator(base, ending string, current_page, max_page, page_margin, dropdown_offset int) (PaginationData, error) {
|
||||
// Validate input parameters
|
||||
if current_page < 1 {
|
||||
return PaginationData{}, fmt.Errorf("current_page must be greater than or equal to 1, got %d", current_page)
|
||||
}
|
||||
if max_page != -1 && max_page < current_page {
|
||||
return PaginationData{}, fmt.Errorf("max_page (%d) must be greater than or equal to current_page (%d) when specified", max_page, current_page)
|
||||
}
|
||||
if page_margin < 0 {
|
||||
return PaginationData{}, fmt.Errorf("page_margin must be non-negative, got %d", page_margin)
|
||||
}
|
||||
if dropdown_offset < 0 {
|
||||
return PaginationData{}, fmt.Errorf("dropdown_offset must be non-negative, got %d", dropdown_offset)
|
||||
}
|
||||
|
||||
hasMaxPage := max_page != -1
|
||||
|
||||
pageUrl := func(page int) string {
|
||||
return fmt.Sprintf(`%s%d%s`, base, page, ending)
|
||||
}
|
||||
|
||||
// Number of pages to show on each side of the current page
|
||||
//
|
||||
// NOTE: values higher than 1 can cause issues on small devices where the pagination element is too wide
|
||||
const peek = 1
|
||||
hasMaxPage := max_page != -1
|
||||
// Helper function to generate a range of pages
|
||||
generatePageRange := func(start, end int) []PageInfo {
|
||||
if start > end {
|
||||
return []PageInfo{}
|
||||
}
|
||||
pages := make([]PageInfo, 0, end-start+1)
|
||||
for i := start; i <= end; i++ {
|
||||
pages = append(pages, PageInfo{Number: i, URL: pageUrl(i)})
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
// Calculate the range of pages to display
|
||||
start := max(1, current_page-peek)
|
||||
end := current_page + peek
|
||||
start := max(1, current_page-page_margin)
|
||||
end := current_page + page_margin
|
||||
if hasMaxPage {
|
||||
end = min(max_page, end)
|
||||
}
|
||||
|
||||
// Generate page information for the range
|
||||
pages := make([]PageInfo, 0, end-start+1)
|
||||
for i := start; i <= end; i++ {
|
||||
pages = append(pages, PageInfo{Number: i, URL: pageUrl(i)})
|
||||
pages := generatePageRange(start, end)
|
||||
|
||||
var lastPage int
|
||||
if len(pages) > 0 {
|
||||
lastPage = pages[len(pages)-1].Number
|
||||
} else {
|
||||
lastPage = current_page
|
||||
}
|
||||
|
||||
lastPage := pages[len(pages)-1].Number
|
||||
|
||||
// Generate dropdown pages (previous 5, current, next 5)
|
||||
dropdownStart := max(1, current_page-5)
|
||||
dropdownEnd := current_page + 5
|
||||
// Generate dropdown pages
|
||||
dropdownStart := max(1, current_page-dropdown_offset)
|
||||
dropdownEnd := current_page + dropdown_offset
|
||||
if hasMaxPage {
|
||||
dropdownEnd = min(max_page, dropdownEnd)
|
||||
}
|
||||
dropdownPages := make([]PageInfo, 0, dropdownEnd-dropdownStart+1)
|
||||
for i := dropdownStart; i <= dropdownEnd; i++ {
|
||||
dropdownPages = append(dropdownPages, PageInfo{Number: i, URL: pageUrl(i)})
|
||||
dropdownPages := generatePageRange(dropdownStart, dropdownEnd)
|
||||
|
||||
// Calculate previous and next URLs
|
||||
var previousURL, nextURL string
|
||||
if current_page > 1 {
|
||||
previousURL = pageUrl(current_page - 1)
|
||||
}
|
||||
if !hasMaxPage || current_page < max_page {
|
||||
nextURL = pageUrl(current_page + 1)
|
||||
}
|
||||
|
||||
// Create and return the PaginationData struct
|
||||
@@ -205,14 +244,14 @@ func CreatePaginator(base, ending string, current_page, max_page int) Pagination
|
||||
Pages: pages,
|
||||
HasPrevious: current_page > 1,
|
||||
HasNext: !hasMaxPage || current_page < max_page,
|
||||
PreviousURL: pageUrl(current_page - 1),
|
||||
NextURL: pageUrl(current_page + 1),
|
||||
PreviousURL: previousURL,
|
||||
NextURL: nextURL,
|
||||
FirstURL: pageUrl(1),
|
||||
LastURL: pageUrl(max_page),
|
||||
HasMaxPage: hasMaxPage,
|
||||
LastPage: lastPage,
|
||||
DropdownPages: dropdownPages,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetNovelGenre returns the genre name for a given genre ID
|
||||
@@ -316,8 +355,14 @@ func GetTemplateFunctions() map[string]any {
|
||||
"parseTimeCustomFormat": func(date time.Time, format string) string {
|
||||
return ParseTimeCustomFormat(date, format)
|
||||
},
|
||||
"createPaginator": func(base, ending string, current_page, max_page int) PaginationData {
|
||||
return CreatePaginator(base, ending, current_page, max_page)
|
||||
"createPaginator": func(base, ending string, current_page, max_page, page_margin, dropdown_offset int) PaginationData {
|
||||
paginationData, err := CreatePaginator(base, ending, current_page, max_page, page_margin, dropdown_offset)
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating paginator: %v", err)
|
||||
// Return an empty PaginationData in case of error
|
||||
return PaginationData{}
|
||||
}
|
||||
return paginationData
|
||||
},
|
||||
"joinArtworkIds": func(artworks []core.ArtworkBrief) string {
|
||||
ids := []string{}
|
||||
|
||||
Reference in New Issue
Block a user