nicokaiser / hugo-theme-gallery

Gallery Theme for Hugo
https://nicokaiser.github.io/hugo-theme-gallery/
MIT License
336 stars 98 forks source link

Make image URLs permalinks #56

Closed LNA-DEV closed 6 months ago

LNA-DEV commented 6 months ago

If you click on a image you have a link which you could send to someone. Like https://nicokaiser.github.io/hugo-theme-gallery/featured-album/#0.

But if I now upload a new image all those ids change. Is there a way setting those ids to the image name or a hash of the image? This would improve the usability a lot I think.

nicokaiser commented 6 months ago

The problem here is that we do not have very much information about the PhotoSwipe elements. Using the index is easy since it is already in the currSlide objects (so we do not have to calculate something or derive something from filenames – which must be escaped, etc...). When opening the page, the index in the URL hash can be easily used to address the corresponding image. When using something else, all images (lightbox elements) need to be searched for the URL hash, which makes things way more complex.

In theory we could use something like

  lightbox.on("change", () => {
    history.replaceState("", document.title, "#" + lightbox.pswp.currSlide.data?.element?.dataset?.id);
  });
nicokaiser commented 6 months ago

This might work – although it is highly untested in edge cases:

diff --git a/assets/js/lightbox.js b/assets/js/lightbox.js
index 18e1111..ac0c792 100644
--- a/assets/js/lightbox.js
+++ b/assets/js/lightbox.js
@@ -59,7 +59,9 @@ if (gallery) {
   });

   lightbox.on("change", () => {
-    history.replaceState("", document.title, "#" + lightbox.pswp.currSlide.index);
+    const currSlide = lightbox.pswp.currSlide;
+    const id = currSlide.data?.element?.dataset?.id || currSlide.index;
+    history.replaceState("", document.title, "#" + id);
   });

   lightbox.on("close", () => {
@@ -75,7 +77,8 @@ if (gallery) {
   lightbox.init();

   if (window.location.hash.substring(1).length > 0) {
-    const index = parseInt(window.location.hash.substring(1), 10);
+    const id = window.location.hash.substring(1);
+    const index = Array.from(gallery.querySelectorAll("a")).findIndex((el) => el.dataset?.id === id);
     if (!Number.isNaN(index) && index >= 0 && index < gallery.querySelectorAll("a").length) {
       lightbox.loadAndOpen(index, { gallery });
     }
diff --git a/layouts/partials/gallery.html b/layouts/partials/gallery.html
index ef1224e..0a6a40b 100644
--- a/layouts/partials/gallery.html
+++ b/layouts/partials/gallery.html
@@ -25,7 +25,7 @@
       {{ $thumbnail := $image.Filter (slice images.AutoOrient (images.Process "fit 600x600")) }}
       {{ $full := $image.Filter (slice images.AutoOrient (images.Process "fit 1600x1600")) }}
       {{ $color := index $thumbnail.Colors 0 | default "transparent" }}
-      <a class="gallery-item" href="{{ $image.RelPermalink }}" data-pswp-src="{{ $full.RelPermalink }}" data-pswp-width="{{ $full.Width }}" data-pswp-height="{{ $full.Height }}" title="{{ .Title }}" itemscope itemtype="https://schema.org/ImageObject" style="aspect-ratio: {{ $thumbnail.Width }} / {{ $thumbnail.Height }}">
+      <a class="gallery-item" href="{{ $image.RelPermalink }}" data-id="{{ $image.RelPermalink | crypto.FNV32a }}" data-pswp-src="{{ $full.RelPermalink }}" data-pswp-width="{{ $full.Width }}" data-pswp-height="{{ $full.Height }}" title="{{ .Title }}" itemscope itemtype="https://schema.org/ImageObject" style="aspect-ratio: {{ $thumbnail.Width }} / {{ $thumbnail.Height }}">
         <img loading="lazy" width="{{ $thumbnail.Width }}" height="{{ $thumbnail.Height }}" src="{{ $thumbnail.RelPermalink }}" style="background-color: {{ $color }}" alt="{{ .Title }}" />
         <meta itemprop="contentUrl" content="{{ $image.RelPermalink }}" />
         {{ with site.Params.Author }}

I'd like to keep this beyond the scope of this theme and keep the simplicity of using the index for "permanent" URLs for images...

LNA-DEV commented 6 months ago

Just played a bit with it. Seems to work pretty well. Thanks.

I think this would be nice to have in the theme but I can understand your point :smile: