feat(booth): prev/next arrows in the image viewer

Zooming an image now shows ‹ / › arrows at the left/right edges that step
to the previous/next image in the booth (gallery sorted-rel order), wrapping
around, plus keyboard ←/→. Arrows are hidden when a booth has a single image.
booth_view_file computes neighbors via a new booth_image_names() helper and
passes prev_url/next_url to view.html. 3 new tests, suite 47 passing;
deployed + verified live on nh3-dev :8090.
This commit is contained in:
vh
2026-08-05 01:30:30 -07:00
parent 54ed0778d3
commit 6872e524de
4 changed files with 71 additions and 2 deletions
+19 -1
View File
@@ -77,6 +77,15 @@ def render_doc(text: str, kind: str) -> tuple[str, bool]:
return text, False
def booth_image_names(child: Path) -> list[str]:
"""Image files in a booth, in gallery (sorted-rel) order — for viewer prev/next."""
return sorted(
p.relative_to(child).as_posix()
for p in child.rglob("*")
if p.is_file() and not p.name.startswith(".") and classify(p.name) == "image"
)
def classify(name: str) -> str:
"""image | video | audio | other, by extension."""
ext = Path(name).suffix.lower()
@@ -525,7 +534,16 @@ def create_app(
file_url = quote(f, safe="/")
common = {**base_ctx, "name": name, "name_url": quote(name, safe=""), "file": f, "file_url": file_url}
if classify(target.name) == "image":
return templates.TemplateResponse(request, "view.html", common)
# prev/next image nav (wraps around; only when >1 image in the booth)
names = booth_image_names(booth)
prev_url = next_url = None
if f in names and len(names) > 1:
i = names.index(f)
prev_url = quote(names[(i - 1) % len(names)], safe="/")
next_url = quote(names[(i + 1) % len(names)], safe="/")
return templates.TemplateResponse(
request, "view.html", {**common, "prev_url": prev_url, "next_url": next_url}
)
# .md renders, .txt/.log show as text — viewable in-booth, no download
dk = doc_kind(target.name)
if dk: