From 562b1055509ed8fc72ba64b06e06dbc9ea29cfd9 Mon Sep 17 00:00:00 2001 From: ZDDC Date: Thu, 7 May 2026 13:43:17 -0500 Subject: [PATCH] feat(browse): double-click a folder to navigate into it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single-click still expands the folder inline; double-click swaps the view's root onto the folder. In server mode it loads the folder's URL (zddc-server returns a fresh browse instance scoped there); in FS-API mode it re-roots state.rootHandle onto the folder's handle and re- enumerates. Files and zips are unchanged — files have a single-click preview, zips have inline JSZip expansion. Help panel updated to document the new behavior. Co-Authored-By: Claude Opus 4.7 (1M context) --- browse/js/events.js | 48 ++++++++++++++++++++++++++++++++++++++++++++ browse/template.html | 4 ++++ 2 files changed, 52 insertions(+) diff --git a/browse/js/events.js b/browse/js/events.js index 1ff1830..b42d50e 100644 --- a/browse/js/events.js +++ b/browse/js/events.js @@ -202,6 +202,54 @@ // Browser handles target=_blank natively for middle // click; don't preventDefault, just don't intercept. }); + + // Double-click on a folder → "navigate into" it. Distinct + // from single-click (which expands inline) so users keep + // both UX models. Server mode jumps to the folder URL — + // zddc-server returns a fresh browse instance scoped to + // that directory. FS-API mode swaps state.rootHandle to + // the folder's handle and re-loads, so the user sees + // only that subtree at the root level. + // + // Files: dblclick is left alone — the single-click preview + // is already a "look at this file" action; a separate + // navigate-into doesn't apply. + // ZIPs: skipped too — they're inspected via inline + // expansion (JSZip), not navigated into. + tbody.addEventListener('dblclick', function (e) { + var row = e.target.closest('tr.tree-row'); + if (!row) return; + if (row.dataset.isdir !== 'true') return; + var id = parseInt(row.dataset.id, 10); + var node = state.nodes.get(id); + if (!node) return; + e.preventDefault(); + navigateIntoFolder(node); + }); + } + } + + async function navigateIntoFolder(node) { + if (state.source === 'server') { + var url = window.app.modules.tree.pathFor(node); + if (!url.endsWith('/')) url += '/'; + window.location.assign(url); + return; + } + if (state.source === 'fs') { + if (!node.handle || node.handle.kind !== 'directory') return; + state.rootHandle = node.handle; + state.currentPath = node.handle.name + '/'; + var raw; + try { + raw = await loader.fetchFsChildren(node.handle); + } catch (e) { + statusError('Failed to enter ' + node.name + ': ' + e.message); + return; + } + tree.setRoot(raw); + tree.render(); + statusInfo('Entered ' + node.name); } } diff --git a/browse/template.html b/browse/template.html index 1ee3c04..63dbd8e 100644 --- a/browse/template.html +++ b/browse/template.html @@ -126,6 +126,10 @@
Click a folder
Toggle expand/collapse on that folder.
+
Double-click a folder
+
Navigate into the folder — it becomes the new root of the + view. Server mode loads the folder's URL; local mode re-roots + onto that folder's handle.
Shift-click a folder
Recursive expand or collapse — applies to the whole subtree.
Click a file