feat: paginate public share directories (#132)

* feat: paginate public share directories

* feat: add cursor pagination to public share listings

Unify share and VFS directory payloads, pass cursor through the share
API, and add prev/next controls plus tests for cursor-mode adapters.

---------

Co-authored-by: shiyu <im@shiyu.dev>
This commit is contained in:
XiaoQing235
2026-08-27 22:21:08 +08:00
committed by GitHub
co-authored by shiyu
parent 4d907c7bfd
commit 0763d457d5
11 changed files with 486 additions and 88 deletions
+7 -25
View File
@@ -5,6 +5,7 @@ from urllib.parse import quote
from fastapi import HTTPException, Request, UploadFile
from fastapi.responses import Response
from api.response import dir_listing
from domain.config import ConfigService
from domain.tasks import TaskService
from .thumbnail import (
@@ -293,31 +294,12 @@ class VirtualFSRouteMixin(VirtualFSTempLinkMixin):
async def list_directory(cls, full_path: str, page_num: int, page_size: int, sort_by: str, sort_order: str):
full_path = cls._normalize_path(full_path)
result = await cls.list_virtual_dir(full_path, page_num, page_size, sort_by, sort_order)
pagination = {
"mode": result.get("pagination_mode", "paged"),
"page_size": result.get("page_size", page_size),
}
if pagination["mode"] == "cursor":
pagination.update(
{
"cursor": result.get("cursor"),
"next_cursor": result.get("next_cursor"),
"has_next": bool(result.get("has_next")),
}
)
else:
pagination.update(
{
"total": result["total"],
"page": result["page"],
"pages": result["pages"],
}
)
return {
"path": full_path,
"entries": result["items"],
"pagination": pagination,
}
return dir_listing(
result,
path=full_path,
page_num=page_num,
page_size=page_size,
)
@classmethod
async def delete(cls, full_path: str):
+9 -25
View File
@@ -1,3 +1,5 @@
from api.response import dir_listing
from .common import VirtualFSCommonMixin
from .resolver import VirtualFSResolverMixin
from .listing import VirtualFSListingMixin
@@ -47,28 +49,10 @@ class VirtualFSService(
result = await cls.list_virtual_dir_with_permission(
full_path, user_id, page_num, page_size, sort_by, sort_order, cursor
)
pagination = {
"mode": result.get("pagination_mode", "paged") if isinstance(result, dict) else "paged",
"page_size": result.get("page_size", page_size) if isinstance(result, dict) else page_size,
}
if pagination["mode"] == "cursor":
pagination.update(
{
"cursor": result.get("cursor") if isinstance(result, dict) else cursor,
"next_cursor": result.get("next_cursor") if isinstance(result, dict) else None,
"has_next": bool(result.get("has_next")) if isinstance(result, dict) else False,
}
)
else:
pagination.update(
{
"total": result.get("total", 0) if isinstance(result, dict) else 0,
"page": result.get("page", page_num) if isinstance(result, dict) else page_num,
"pages": result.get("pages", 0) if isinstance(result, dict) else 0,
}
)
return {
"path": full_path,
"entries": result.get("items", []) if isinstance(result, dict) else [],
"pagination": pagination,
}
return dir_listing(
result,
path=full_path,
page_num=page_num,
page_size=page_size,
cursor=cursor,
)