#5 — Double-click on a folder no longer toggles collapse.
Root cause: the single-click handler called tree.render() immediately,
which replaced the clicked row element. The browser's double-click
detection requires the second click to land on the SAME target as the
first, so dblclick never fired for folders.
Fix: defer the single-click toggle by 220ms. A pending dblclick within
the window cancels the toggle and runs navigateIntoFolder instead.
Modifier-clicks (shift/alt for recursive) and ZIP expands skip the
deferral — they're never followed by a dblclick navigation.
#3 — Browse at /<project>/ now always shows the four canonical
folders (archive, working, staging, reviewing) even when they don't
yet exist on disk. Each missing folder is synthesized client-side as
a "virtual" row: muted icon + label + "(empty)" hint, double-clickable
to navigate. zddc-server already serves an empty listing for these
paths (commit 3fc3717), so navigation into a virtual folder works
without 404 and the user lands in a sensible empty workspace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
77 lines
3 KiB
JavaScript
77 lines
3 KiB
JavaScript
// app.js — bootstrap. Runs after every other module's IIFE has
|
|
// registered its functions on window.app.modules.
|
|
(function () {
|
|
'use strict';
|
|
|
|
var state = window.app.state;
|
|
var loader = window.app.modules.loader;
|
|
var tree = window.app.modules.tree;
|
|
var events = window.app.modules.events;
|
|
|
|
// Canonical folders that should appear at the root of a project
|
|
// view even if they don't yet exist on disk. Matches the four
|
|
// stage cards on the project landing page. zddc-server returns an
|
|
// empty listing for these paths (see commit 3fc3717), so
|
|
// navigating into a virtual folder works without 404.
|
|
var CANONICAL_PROJECT_FOLDERS = ['archive', 'working', 'staging', 'reviewing'];
|
|
|
|
// Decide whether `path` looks like a project root — i.e. exactly
|
|
// one path segment after the leading slash. /Project-1/ → yes;
|
|
// / → no; /Project-1/working/ → no.
|
|
function isProjectRoot(path) {
|
|
if (!path || path === '/') return false;
|
|
var trimmed = path.replace(/^\/+|\/+$/g, '');
|
|
if (!trimmed) return false;
|
|
return trimmed.indexOf('/') < 0;
|
|
}
|
|
|
|
// Merge virtual entries for any canonical folders absent from the
|
|
// server's listing. Each virtual entry is shaped like a normal
|
|
// directory entry so the tree renderer treats it the same way.
|
|
function withVirtualCanonicals(entries, path) {
|
|
if (!isProjectRoot(path)) return entries;
|
|
var present = Object.create(null);
|
|
entries.forEach(function (e) { if (e.isDir) present[e.name] = true; });
|
|
var augmented = entries.slice();
|
|
CANONICAL_PROJECT_FOLDERS.forEach(function (name) {
|
|
if (!present[name]) {
|
|
augmented.push({
|
|
name: name,
|
|
isDir: true,
|
|
size: 0,
|
|
modTime: null,
|
|
ext: '',
|
|
url: path.replace(/\/$/, '') + '/' + name + '/',
|
|
virtual: true
|
|
});
|
|
}
|
|
});
|
|
return augmented;
|
|
}
|
|
|
|
async function bootstrap() {
|
|
events.init();
|
|
|
|
// Try server auto-detect. If this page is served by zddc-server
|
|
// (or any server with a Caddy-shaped JSON listing), load the
|
|
// current directory automatically. Otherwise show the empty
|
|
// state with the "Select Directory" button.
|
|
var detected = await loader.autoDetectServerMode();
|
|
if (detected) {
|
|
var entries = withVirtualCanonicals(detected.entries, detected.path);
|
|
tree.setRoot(entries);
|
|
events.showBrowseRoot();
|
|
tree.render();
|
|
events.statusInfo('Loaded ' + detected.entries.length + ' item'
|
|
+ (detected.entries.length === 1 ? '' : 's')
|
|
+ ' from ' + detected.path);
|
|
}
|
|
// Else: empty state stays visible; user can click Select Directory.
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', bootstrap);
|
|
} else {
|
|
bootstrap();
|
|
}
|
|
})();
|