improve gallery

This commit is contained in:
lelo 2026-02-28 19:07:28 +00:00
parent 68c15fb367
commit 8efca53e8e
3 changed files with 121 additions and 19 deletions

View File

@ -623,6 +623,14 @@ footer .audio-player-container {
border-radius: 12px;
background: linear-gradient(145deg, #ffffff, #f6f8fc);
box-shadow: var(--card-shadow);
aspect-ratio: 1 / 1;
}
.image-item .image-link {
display: block;
width: 100%;
height: 100%;
line-height: 0;
}
/* the filename overlay, centered at bottom */
@ -651,11 +659,12 @@ footer .audio-player-container {
.thumbnail {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
.thumbnail-fallback {
object-fit: contain;
object-fit: cover;
background: #e5e5e5;
}

View File

@ -22,6 +22,7 @@
position: fixed;
z-index: 3000;
inset: 0;
--gallery-edge-gap: 10px;
background-color: rgba(0, 0, 0, 0.82);
background-image:
radial-gradient(circle at 50% 15%, rgba(42, 42, 42, 0.52), rgba(8, 8, 8, 0.95) 56%, #000 100%);
@ -33,7 +34,7 @@
#gallery-stage {
position: absolute;
inset: 82px 22px 96px;
inset: var(--gallery-edge-gap);
cursor: pointer;
}
@ -42,8 +43,8 @@
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: min(96vw, calc(100vw - 80px));
max-height: calc(100vh - 190px);
max-width: calc(100vw - (var(--gallery-edge-gap) * 2));
max-height: calc(100vh - (var(--gallery-edge-gap) * 2));
object-fit: contain;
margin: auto;
display: block;
@ -258,7 +259,7 @@
#gallery-filename,
#gallery-position {
color: #fff;
background: rgba(0, 0, 0, 0.6);
background: rgba(0, 0, 0, 0.42);
border: 1px solid rgba(255, 255, 255, 0.16);
border-radius: 8px;
padding: 0.45rem 0.72rem;
@ -285,10 +286,10 @@
background:
linear-gradient(
90deg,
rgba(255, 255, 255, 0.95) 0%,
rgba(255, 255, 255, 0.95) var(--filename-progress),
rgba(0, 0, 0, 0.62) var(--filename-progress),
rgba(0, 0, 0, 0.62) 100%
rgba(255, 255, 255, 0.56) 0%,
rgba(255, 255, 255, 0.56) var(--filename-progress),
rgba(0, 0, 0, 0.44) var(--filename-progress),
rgba(0, 0, 0, 0.44) 100%
);
z-index: 0;
}
@ -310,7 +311,7 @@
left: 0;
width: 100%;
height: 100%;
padding: 0.45rem 0.72rem;
padding: inherit;
box-sizing: border-box;
z-index: 2;
overflow: hidden;
@ -365,13 +366,17 @@
}
@media (max-width: 860px) {
#gallery-modal {
--gallery-edge-gap: 8px;
}
#gallery-stage {
inset: 74px 10px 110px;
inset: var(--gallery-edge-gap);
}
#gallery-modal-content {
max-width: calc(100vw - 20px);
max-height: calc(100vh - 210px);
max-width: calc(100vw - (var(--gallery-edge-gap) * 2));
max-height: calc(100vh - (var(--gallery-edge-gap) * 2));
border-radius: 10px;
}
@ -453,13 +458,17 @@
}
@media (max-height: 520px) and (orientation: landscape) {
#gallery-modal {
--gallery-edge-gap: 6px;
}
#gallery-stage {
inset: 44px 10px 60px;
inset: var(--gallery-edge-gap);
}
#gallery-modal-content {
max-width: calc(100vw - 20px);
max-height: calc(100vh - 112px);
max-width: calc(100vw - (var(--gallery-edge-gap) * 2));
max-height: calc(100vh - (var(--gallery-edge-gap) * 2));
border-radius: 8px;
}

View File

@ -29,6 +29,7 @@ if (typeof currentGalleryIndex === "undefined") {
}
let currentExifRequestId = 0;
const previewRefreshInFlight = new Set();
function encodeGalleryPath(relUrl) {
if (!relUrl) {
@ -40,6 +41,73 @@ function encodeGalleryPath(relUrl) {
.join('/');
}
function findBrowserThumbnailByRelUrl(relUrl) {
if (!relUrl) {
return null;
}
const links = document.querySelectorAll('.image-link[data-url]');
for (const link of links) {
if ((link.dataset.url || '') === relUrl) {
return link.querySelector('img.thumbnail');
}
}
return null;
}
function isFallbackThumbnail(imgEl) {
if (!imgEl) {
return false;
}
const src = imgEl.getAttribute('src') || '';
return imgEl.classList.contains('thumbnail-fallback') || src.startsWith('data:image/');
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function refreshBrowserThumbnailIfMissing(relUrl) {
if (!relUrl || previewRefreshInFlight.has(relUrl)) {
return;
}
const thumbImg = findBrowserThumbnailByRelUrl(relUrl);
if (!thumbImg || !isFallbackThumbnail(thumbImg)) {
return;
}
const baseThumbUrl = thumbImg.dataset.thumbUrl;
if (!baseThumbUrl) {
return;
}
previewRefreshInFlight.add(relUrl);
const separator = baseThumbUrl.includes('?') ? '&' : '?';
try {
for (let attempt = 0; attempt < 2; attempt++) {
const refreshUrl = `${baseThumbUrl}${separator}_=${Date.now()}-${attempt}`;
const response = await fetch(refreshUrl, { method: 'GET', cache: 'no-store' }).catch(() => null);
if (response && response.ok && response.status !== 204) {
thumbImg.classList.remove('thumbnail-fallback');
if (typeof handleThumbnailLoad === 'function') {
thumbImg.onload = () => handleThumbnailLoad(thumbImg);
}
if (typeof handleThumbnailError === 'function') {
thumbImg.onerror = () => handleThumbnailError(thumbImg);
}
thumbImg.src = refreshUrl;
return;
}
if (attempt === 0) {
await delay(250);
}
}
} finally {
previewRefreshInFlight.delete(relUrl);
}
}
function escapeHtml(value) {
return String(value === undefined || value === null ? '' : value).replace(/[&<>"']/g, (char) => ({
'&': '&amp;',
@ -276,6 +344,11 @@ function showGalleryNav() {
}, 1000);
}
function hideGalleryNav() {
clearTimeout(navHideTimer);
document.querySelectorAll('.gallery-nav').forEach(btn => btn.classList.add('nav-hidden'));
}
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
@ -375,6 +448,7 @@ function showGalleryImage(relUrl) {
clearTimeout(loaderTimeout);
loader.style.display = 'none';
updateFilenameDisplay(relUrl);
refreshBrowserThumbnailIfMissing(relUrl);
// Select all current images in the gallery stage
const existingImages = stage.querySelectorAll('img');
@ -449,8 +523,12 @@ function showGalleryImage(relUrl) {
function preloadNextImage() {
if (currentGalleryIndex < currentGalleryImages.length - 1) {
const nextRelUrl = currentGalleryImages[currentGalleryIndex + 1];
const nextImage = new Image();
nextImage.src = '/media/' + currentGalleryImages[currentGalleryIndex + 1];
nextImage.onload = function () {
refreshBrowserThumbnailIfMissing(nextRelUrl);
};
nextImage.src = '/media/' + nextRelUrl;
}
}
@ -703,7 +781,6 @@ function handlePinchStart(e) {
pinchStartMidY = (e.touches[0].pageY + e.touches[1].pageY) / 2;
pinchStartTranslateX = currentTranslateX;
pinchStartTranslateY = currentTranslateY;
showGalleryNav();
return;
}
@ -736,7 +813,11 @@ function handlePinchMove(e) {
currentTranslateX = pinchStartTranslateX + (midX - pinchStartMidX);
currentTranslateY = pinchStartTranslateY + (midY - pinchStartMidY);
applyImageTransform(e.currentTarget);
showGalleryNav();
if (currentScale > 1.01) {
showGalleryNav();
} else {
hideGalleryNav();
}
return;
}
@ -776,6 +857,9 @@ function handlePinchEnd(e) {
currentScale = 1;
currentTranslateX = 0;
currentTranslateY = 0;
applyImageTransform(image);
hideGalleryNav();
return;
}
applyImageTransform(image);
showGalleryNav();