diff options
| author | dax <me@dax.ist> | 2026-08-05 09:19:53 +0100 |
|---|---|---|
| committer | dax <me@dax.ist> | 2026-08-05 09:19:53 +0100 |
| commit | e0663c2f0681662fb599bbf0ac0d45ab8385aa79 (patch) | |
| tree | 654fee764b20e9dbf985a87c80d539ffe27c217c /public/app.js | |
| parent | 51847eceda8057c2e6daaf394cf337f231b750b2 (diff) | |
preview loading/blank state: hide old thumb instantly while new loads, 1s spinner fallback; keep preview hidden until scroll or mouse move, reset after click/keyboard navigation
Diffstat (limited to 'public/app.js')
| -rw-r--r-- | public/app.js | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/public/app.js b/public/app.js index f323b22..4a55cb9 100644 --- a/public/app.js +++ b/public/app.js @@ -34,6 +34,7 @@ let panY = 0 let scale = 1 let userZoomed = false let drag = null +let previewsShown = false const TOUCH = typeof window.matchMedia === "function" && window.matchMedia("(hover: none)").matches @@ -323,6 +324,7 @@ function adjacentTile(id, dir) { } function traverseFrom(id, dir) { + previewsShown = false followEnabled = false const back = adjacentTile(id, dir) if (back) { @@ -377,18 +379,40 @@ function renderTileZones(id) { if (!best) return const els = [] const preview = document.createElement("div") - preview.className = "preview" + preview.className = "preview hidden" const previewImg = document.createElement("img") previewImg.alt = "" - previewImg.loading = "lazy" preview.appendChild(previewImg) + const spinner = document.createElement("div") + spinner.className = "spinner" + preview.appendChild(spinner) let hotDir = null + let loadTimer = 0 + const doneLoading = () => { + clearTimeout(loadTimer) + preview.classList.remove("loading", "slow") + } + previewImg.onload = doneLoading + previewImg.onerror = doneLoading const showAt = (x) => { + previewsShown = true + preview.classList.remove("hidden") preview.style.left = x.p.rect.x + "px" preview.style.top = x.p.rect.y + "px" preview.style.width = x.p.rect.w + "px" preview.style.height = x.p.rect.h + "px" - previewImg.src = x.p.info.thumb + const next = new URL(x.p.info.thumb, location.href).href + if (previewImg.src === next && previewImg.complete) { + doneLoading() + return + } + clearTimeout(loadTimer) + preview.classList.add("loading") + preview.classList.remove("slow") + previewImg.src = next + loadTimer = setTimeout(() => { + if (preview.classList.contains("loading")) preview.classList.add("slow") + }, 1000) } const reset = () => { hotDir = null @@ -424,7 +448,7 @@ function renderTileZones(id) { els.push(z) } world.appendChild(preview) - showAt(best) + if (previewsShown && best) showAt(best) zones.set(id, { els, key, preview, reset }) } @@ -496,6 +520,10 @@ stage.addEventListener("pointerdown", (e) => { }) stage.addEventListener("pointermove", (e) => { + if (!previewsShown) { + const entry = zones.get(cur && cur.id) + if (entry && entry.reset) entry.reset() + } if (pointers.has(e.pointerId)) { pointers.set(e.pointerId, { x: e.clientX, y: e.clientY }) if (pointers.size === 2 && pinchDist > 0) { @@ -541,6 +569,7 @@ stage.addEventListener("pointerup", (e) => { const id = Number(tile.dataset.id) followEnabled = false if (cur && cur.id === id) return + previewsShown = false setCurrent(id, tiles.get(id).rect) }) |
