Fix thumbnail loading and startup gallery refresh.

Refresh gallery metadata after thumbnail generation so new thumb URLs are available immediately, and lazy-load gallery thumbnails with IntersectionObserver to avoid fetching all images on initial page load.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-03 00:16:38 +12:00
parent 45b31be9a7
commit a9095727bf
3 changed files with 55 additions and 1 deletions

View File

@@ -70,6 +70,17 @@ func New(imagesDir, staticDir string, mailCfg *mail.Config) (*Server, error) {
} else {
log.Print("gallery thumbnails: ready")
}
// Thumbnail URLs are resolved during gallery.List. Re-list after derivative
// generation so newly-created thumbs appear immediately on first load.
if refreshed, err := gallery.List(imagesDir); err != nil {
log.Printf("gallery refresh after thumbnails: %v", err)
} else {
srv.Images = refreshed
if hero, hasHero := gallery.SelectHero(refreshed); hasHero {
srv.Hero = hero
srv.HasHero = true
}
}
return srv, nil
}

View File

@@ -22,7 +22,9 @@ templ GalleryGrid(images []gallery.Image) {
>
if img.ThumbURL != "" {
<img
src={ img.ThumbURL }
src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="
data-src={ img.ThumbURL }
class="lazy-thumb"
alt={ fmt.Sprintf("%s — %s", gallery.AlbumLabel(img.Album), formatDate(img.Date)) }
loading="lazy"
decoding="async"

View File

@@ -34,6 +34,47 @@ templ Layout(title string, preloadImage string, content templ.Component) {
</footer>
<div id="modal-root"></div>
<script src="/static/htmx.min.js" defer></script>
<script>
(function () {
function hydrateLazyThumbs(root) {
var lazyImages = root.querySelectorAll("img[data-src]");
if (!lazyImages.length) return;
if (!("IntersectionObserver" in window)) {
lazyImages.forEach(function (img) {
img.src = img.dataset.src;
img.removeAttribute("data-src");
});
return;
}
var observer = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting) return;
var img = entry.target;
img.src = img.dataset.src;
img.removeAttribute("data-src");
observer.unobserve(img);
});
},
{ rootMargin: "300px 0px" },
);
lazyImages.forEach(function (img) {
observer.observe(img);
});
}
document.addEventListener("DOMContentLoaded", function () {
hydrateLazyThumbs(document);
});
document.body.addEventListener("htmx:afterSwap", function (event) {
hydrateLazyThumbs(event.target);
});
})();
</script>
</body>
</html>
}