aboutsummaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
Diffstat (limited to 'public')
-rw-r--r--public/app.css16
-rw-r--r--public/app.js37
-rw-r--r--public/index.html4
3 files changed, 51 insertions, 6 deletions
diff --git a/public/app.css b/public/app.css
index fd7612e..1e51b9b 100644
--- a/public/app.css
+++ b/public/app.css
@@ -58,6 +58,7 @@ html, body {
transition: opacity .15s;
}
.preview.hot { opacity: .85; }
+.preview.hidden { visibility: hidden; }
.preview img {
width: 100%;
height: 100%;
@@ -65,6 +66,21 @@ html, body {
display: block;
border-radius: 6px;
}
+.preview.loading img { visibility: hidden; }
+.preview .spinner {
+ position: absolute;
+ inset: 0;
+ margin: auto;
+ width: 28px;
+ height: 28px;
+ border: 3px solid rgba(255, 255, 255, .25);
+ border-top-color: rgba(125, 211, 252, .9);
+ border-radius: 50%;
+ animation: spin .8s linear infinite;
+ display: none;
+}
+.preview.slow .spinner { display: block; }
+@keyframes spin { to { transform: rotate(360deg); } }
@keyframes lock {
0% { transform: scale(.2); opacity: 0; }
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)
})
diff --git a/public/index.html b/public/index.html
index b31e8ce..9475e4e 100644
--- a/public/index.html
+++ b/public/index.html
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark">
<title>pathways</title>
- <link rel="stylesheet" href="/app.css?v=52">
+ <link rel="stylesheet" href="/app.css?v=56">
</head>
<body>
<main id="stage">
@@ -29,6 +29,6 @@
<span id="progress-text"></span>
</div>
<div id="toast" role="status" aria-live="polite"></div>
- <script src="/app.js?v=52"></script>
+ <script src="/app.js?v=56"></script>
</body>
</html>