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 315faac4b5
commit c37a425276
4 changed files with 71 additions and 2 deletions
+35
View File
@@ -493,3 +493,38 @@ def test_gallery_links_docs_to_view(client):
assert "view?f=readme.md" in page.text # md -> viewer
assert "view?f=notes.txt" in page.text # txt -> viewer
assert 'href="readme.md" download' not in page.text # not a forced download
# ---- image viewer prev/next nav ---------------------------------------------
def test_view_image_prev_next_nav(client):
c, data = client
d = data / "run1"; d.mkdir()
for n in ("a.png", "b.png", "c.png"):
_touch(d / n)
r = c.get("/b/run1/view", params={"f": "b.png"}) # middle -> prev=a, next=c
assert r.status_code == 200
assert 'class="vnav vprev" href="?f=a.png"' in r.text
assert 'class="vnav vnext" href="?f=c.png"' in r.text
def test_view_image_nav_wraps(client):
c, data = client
d = data / "run1"; d.mkdir()
for n in ("a.png", "b.png", "c.png"):
_touch(d / n)
first = c.get("/b/run1/view", params={"f": "a.png"}).text
assert 'vprev" href="?f=c.png"' in first and 'vnext" href="?f=b.png"' in first # first wraps prev->last
last = c.get("/b/run1/view", params={"f": "c.png"}).text
assert 'vnext" href="?f=a.png"' in last and 'vprev" href="?f=b.png"' in last # last wraps next->first
def test_view_single_image_no_nav(client):
c, data = client
d = data / "run1"; d.mkdir()
_touch(d / "only.png")
r = c.get("/b/run1/view", params={"f": "only.png"})
assert r.status_code == 200
# no arrow anchors with a single image (the .vnav CSS rule is always present)
assert 'class="vnav vprev"' not in r.text and 'class="vnav vnext"' not in r.text