Improve gallery video UX and add upload-to-publish media workflow.

Stage raw files in upload/, publish with make sync-media/publish, and polish the lightbox: autoplay, remembered volume, Escape to close, and image/video icons without poster or caption clutter.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-04 23:55:43 +12:00
parent 6c215d40e6
commit 3f5235daaf
22 changed files with 644 additions and 119 deletions

View File

@@ -33,9 +33,7 @@ templ GalleryGrid(images []gallery.Image) {
} else {
<span class="gallery-placeholder" aria-hidden="true"></span>
}
if img.IsVideo {
<span class="gallery-video-badge" aria-hidden="true">Video</span>
}
@GalleryMediaIcon(img.IsVideo)
if img.Collection != "" {
<span class="gallery-album">{ img.Collection }</span>
} else if img.Album != "" {
@@ -49,6 +47,20 @@ templ GalleryGrid(images []gallery.Image) {
}
}
templ GalleryMediaIcon(isVideo bool) {
<span class="gallery-media-icon" aria-hidden="true">
if isVideo {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"></path>
</svg>
} else {
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"></path>
</svg>
}
</span>
}
templ ImageModal(img gallery.Image, prevPath, nextPath string) {
<div
class="modal-backdrop"
@@ -65,21 +77,12 @@ templ ImageModal(img gallery.Image, prevPath, nextPath string) {
</button>
<figure class="modal-figure">
if img.IsVideo {
<div class="modal-video">
<video controls playsinline preload="auto" poster={ img.ThumbURL }>
<source src={ img.URL } type={ videoMIME(img.Filename) }/>
</video>
<p class="video-unavailable" hidden>
Playback is not supported in this browser.
<a href={ img.URL } download={ img.Filename }>Download the video</a>
</p>
<div class="modal-video-stack">
<video src={ img.URL } controls autoplay playsinline preload="auto"></video>
</div>
} else {
<img src={ img.URL } alt={ img.Filename }/>
}
if !img.Date.IsZero() {
<figcaption>{ modalCaption(img) }</figcaption>
}
</figure>
<nav class="modal-nav" aria-label="Gallery navigation">
if prevPath != "" {
@@ -124,13 +127,3 @@ func modalAriaLabel(img gallery.Image) string {
}
return "Image viewer"
}
func modalCaption(img gallery.Image) string {
if img.Collection != "" {
return img.Collection + " — " + formatDate(img.Date)
}
if img.Album != "" {
return gallery.AlbumLabel(img.Album) + " — " + formatDate(img.Date)
}
return formatDate(img.Date)
}