From 56b3a602c8e992a2bc197844e1ab3de8743b8012 Mon Sep 17 00:00:00 2001 From: dax Date: Tue, 4 Aug 2026 10:26:40 +0000 Subject: Code review cleanup: cache placement/adjacency, drop dead code - Cache choosePlacement and adjacentTile results per (id,dir); invalidate on addTile. Avoids O(n^3) placement scoring on every pointermove. - setCurrent now re-renders only affected navs (prev + new) instead of refreshAllNav; remove refreshAllNav entirely. - Add pointercancel handler so interrupted touch/trackpad gestures don't leave a stuck drag. - Remove dead code: placeRect, photoConnections + /api/photo route and THUMBS const on server, dangling info var in pointerup. - Trim .gitignore, remove .DS_Store, bump cache-bust to ?v=20. --- public/app.js | 38 ++++++++++++++++++++++++-------------- public/index.html | 4 ++-- 2 files changed, 26 insertions(+), 16 deletions(-) (limited to 'public') diff --git a/public/app.js b/public/app.js index 800a822..95f64d4 100644 --- a/public/app.js +++ b/public/app.js @@ -155,11 +155,6 @@ function bestPlacement(w, h, from, dir) { return best ? { rect: best, cost: bestCost } : null } -function placeRect(w, h, from, dir) { - const p = bestPlacement(w, h, from, dir) - return p ? p.rect : null -} - function addTile(info, rect) { const el = document.createElement("div") el.className = "tile" @@ -177,18 +172,22 @@ function addTile(info, rect) { requestAnimationFrame(() => el.classList.add("lock")) tiles.set(info.id, { el, info, rect }) rectOf.set(info.id, rect) + placementCache.clear() + adjacencyCache.clear() renderNav(info.id) return el } function setCurrent(id, rect) { + const prevId = cur && cur.id for (const t of tiles.values()) t.el.classList.remove("current") cur = { id, rect } tiles.get(id).el.classList.add("current") if (!userZoomed) scale = worldScale() center() getExits(id) - refreshAllNav() + if (prevId && prevId !== id) renderNav(prevId) + renderNav(id) } function renderNav(id) { @@ -223,10 +222,6 @@ function renderNav(id) { t.el.appendChild(nav) } -function refreshAllNav() { - for (const id of tiles.keys()) if (exitsCache.has(id)) renderNav(id) -} - async function getExits(id) { if (exitsCache.has(id)) return exitsCache.get(id) if (exitPending.has(id)) return exitPending.get(id) @@ -251,7 +246,12 @@ async function getExits(id) { return p } +const placementCache = new Map() +const adjacencyCache = new Map() + function choosePlacement(id, dir) { + const key = id + ":" + dir + if (placementCache.has(key)) return placementCache.get(key) const exits = exitsCache.get(id) const ex = exits && exits.find((e) => e.dir === dir) if (!ex) return null @@ -290,10 +290,14 @@ function choosePlacement(id, dir) { const best = scored[0] const next = ex.next && !rectOf.has(ex.next.id) ? scored.find((s) => s.id === ex.next.id) : null const chosen = next && next.cost - best.cost <= FIT_TOLERANCE ? next : best - return { id: chosen.id, info: chosen.info, rect: chosen.rect } + const out = { id: chosen.id, info: chosen.info, rect: chosen.rect } + placementCache.set(key, out) + return out } function adjacentTile(id, dir) { + const key = id + ":" + dir + if (adjacencyCache.has(key)) return adjacencyCache.get(key) const r = tiles.get(id).rect let best = null let bestDist = Infinity @@ -311,7 +315,9 @@ function adjacentTile(id, dir) { : Math.abs(q.y + q.h / 2 - (r.y + r.h / 2)) if (d < bestDist) { bestDist = d; best = t } } - return best ? best.info.id : null + const out = best ? best.info.id : null + adjacencyCache.set(key, out) + return out } function traverseFrom(id, dir) { @@ -326,7 +332,6 @@ function traverseFrom(id, dir) { hideGhost() addTile(chosen.info, chosen.rect) setCurrent(chosen.id, chosen.rect) - refreshAllNav() refreshAllZones() } @@ -448,11 +453,16 @@ stage.addEventListener("pointerup", (e) => { world.style.transition = "" if (wasDrag || !tile) return const id = Number(tile.dataset.id) - const info = tiles.get(id).info if (cur && cur.id === id) return setCurrent(id, tiles.get(id).rect) }) +stage.addEventListener("pointercancel", () => { + if (!drag) return + drag = null + world.style.transition = "" +}) + let zoomTimer = 0 stage.addEventListener("wheel", (e) => { e.preventDefault() diff --git a/public/index.html b/public/index.html index ee844d7..4c13a5a 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ pathways - +
@@ -16,6 +16,6 @@

four paths, one per direction. walk them.

- + -- cgit v1.3.1