add a query arg to the List endpoint used to determine what page a child item is on

This commit is contained in:
Cyberes 2024-03-23 17:38:28 -06:00
parent 933670c63a
commit 6a5526ba3e
1 changed files with 84 additions and 44 deletions

View File

@ -2,6 +2,7 @@ package file
import ( import (
"crazyfs/api/helpers" "crazyfs/api/helpers"
"crazyfs/cacheitem"
"crazyfs/config" "crazyfs/config"
"crazyfs/file" "crazyfs/file"
"crazyfs/responseitem" "crazyfs/responseitem"
@ -10,6 +11,11 @@ import (
"strconv" "strconv"
) )
const (
sortFolders = "folders"
sortDefault = sortFolders
)
func APIList(w http.ResponseWriter, r *http.Request) { func APIList(w http.ResponseWriter, r *http.Request) {
if helpers.CheckInitialCrawl() { if helpers.CheckInitialCrawl() {
helpers.HandleRejectDuringInitialCrawl(w) helpers.HandleRejectDuringInitialCrawl(w)
@ -25,11 +31,11 @@ func APIList(w http.ResponseWriter, r *http.Request) {
var err error var err error
sortArg := r.URL.Query().Get("sort") sortArg := r.URL.Query().Get("sort")
var folderSorting string var sortType string
if sortArg == "default" || sortArg == "" { if sortArg == sortDefault || sortArg == "" {
folderSorting = "default" sortType = sortDefault
} else if sortArg == "folders" { } else if sortArg == sortFolders {
folderSorting = "folders" sortType = sortFolders
} else { } else {
helpers.Return400Msg("folders arg must be 'default' (to not do any sorting) or 'first' (to sort the folders to the front of the list)", w) helpers.Return400Msg("folders arg must be 'default' (to not do any sorting) or 'first' (to sort the folders to the front of the list)", w)
return return
@ -80,11 +86,6 @@ func APIList(w http.ResponseWriter, r *http.Request) {
} }
} }
// Create a copy of the cached Item, so we don't modify the Item in the cache
item := responseitem.NewResponseItem(cacheItem)
response := map[string]interface{}{}
// Pagination // Pagination
var paginationLimit int var paginationLimit int
if r.URL.Query().Get("limit") != "" { if r.URL.Query().Get("limit") != "" {
@ -102,17 +103,58 @@ func APIList(w http.ResponseWriter, r *http.Request) {
paginationLimit = 100 paginationLimit = 100
} }
// Generate the listing.
pageParam := r.URL.Query().Get("page")
response := map[string]interface{}{}
item, pages, responseError := generateListing(cacheItem, paginationLimit, sortType, pageParam)
if responseError != "" {
helpers.Return400Msg(responseError, w)
return
}
resolveItemName := r.URL.Query().Get("resolve")
if resolveItemName != "" {
var resolvedChild *responseitem.ResponseItem
var resolvedChildPage int
for i := range pages {
for _, child := range pages[i] {
if child.Name == resolveItemName {
resolvedChild = child
resolvedChildPage = i
break
}
}
if resolvedChild != nil {
break
}
}
if resolvedChild == nil {
helpers.Return400Msg("failed to find item", w)
return
}
item.Children = make([]*responseitem.ResponseItem, 1)
item.Children[0] = resolvedChild
response["resolved_page"] = resolvedChildPage
}
if r.URL.Query().Get("page") != "" || resolveItemName != "" {
response["total_pages"] = len(pages) + 1 // We add 1 to the count because arrays are zero-indexed.
}
response["item"] = item
helpers.WriteJsonResponse(response, true, w, r)
}
func generateListing(cacheItem *cacheitem.Item, paginationLimit int, sortType string, pageParam string) (*responseitem.ResponseItem, [][]*responseitem.ResponseItem, string) {
if sortType == "" {
panic("sortType was an empty string")
}
item := responseitem.NewResponseItem(cacheItem)
totalItems := len(item.Children) totalItems := len(item.Children)
totalPages := totalItems / paginationLimit totalPages := totalItems / paginationLimit
if totalItems%paginationLimit != 0 {
totalPages++
}
if r.URL.Query().Get("page") != "" { if sortType == sortFolders {
response["total_pages"] = totalPages
}
if folderSorting == "folders" {
var dirs, files []*responseitem.ResponseItem var dirs, files []*responseitem.ResponseItem
for _, child := range item.Children { for _, child := range item.Children {
if child.IsDir { if child.IsDir {
@ -121,45 +163,43 @@ func APIList(w http.ResponseWriter, r *http.Request) {
files = append(files, child) files = append(files, child)
} }
} }
item.Children = make([]*responseitem.ResponseItem, len(item.Children))
item.Children = append(dirs, files...) item.Children = append(dirs, files...)
} }
// Set the children to an empty array so that the JSON encoder doesn't return it as nil. var pages [][]*responseitem.ResponseItem
var paginatedChildren []*responseitem.ResponseItem // this var will be either the full cacheitem list or a paginated list depending on the query args
if item.Children != nil {
paginatedChildren = item.Children
} else {
paginatedChildren = make([]*responseitem.ResponseItem, 0)
}
pageParam := r.URL.Query().Get("page") var page int
if pageParam != "" { if pageParam != "" {
page, err := strconv.Atoi(pageParam) pageInt, err := strconv.Atoi(pageParam)
if err != nil || page < 1 || page > totalPages { if err != nil || pageInt < 1 {
// Don't return an error, just truncate things return nil, nil, "invalid page number"
page = totalPages
} }
if pageInt > totalPages {
start := (page - 1) * paginationLimit // Don't return an error, just set it to the max page number.
end := start + paginationLimit pageInt = totalPages
if start >= 0 { // avoid segfaults
if start > len(item.Children) {
start = len(item.Children)
}
if end > len(item.Children) {
end = len(item.Children)
}
paginatedChildren = paginatedChildren[start:end]
} }
pageInt--
page = pageInt
} else {
page = 0
} }
for i := 0; i < len(item.Children); i += paginationLimit {
end := i + paginationLimit
if end > len(item.Children) {
end = len(item.Children)
}
pages = append(pages, item.Children[i:end])
}
paginatedChildren := pages[page]
// Erase the children of the children so we aren't displaying things recursively. // Erase the children of the children so we aren't displaying things recursively.
for i := range paginatedChildren { for i := range paginatedChildren {
paginatedChildren[i].Children = nil paginatedChildren[i].Children = nil
} }
item.Children = paginatedChildren item.Children = paginatedChildren
response["item"] = item return item, pages, ""
helpers.WriteJsonResponse(response, true, w, r)
} }