diff --git a/browse/js/tree.js b/browse/js/tree.js index 31183fd..918fc07 100644 --- a/browse/js/tree.js +++ b/browse/js/tree.js @@ -280,18 +280,43 @@ // table); the tree.setSort() method still works but only via // programmatic callers — there's no UI for changing sort yet. + // True when this zip node lives inside another zip (so its bytes + // can't be fetched as a standalone server resource — we go through + // the parent JSZip / inner-zip download path instead). In server + // mode the URL of a zip-member-inside-a-zip contains ".zip/"; in + // FS-API mode zipParentId is set. + function zipNestedInsideZip(node) { + if (node.zipParentId != null) return true; + if (state.source === 'server') { + return pathFor(node).toLowerCase().indexOf('.zip/') !== -1; + } + return false; + } + // Load a folder's children (lazy; idempotent re-loads). Dispatches // by node kind: - // - regular folder → server JSON listing OR FS-API enumeration - // - zip file → fetch+JSZip; entries become virtual children - // - zip child dir → already-listed entries from the parent zip - // (zips are enumerated whole, so child dirs - // are pre-populated when the zip expands) + // - regular folder → server JSON listing OR FS-API enumeration + // - top-level zip, server mode → server's virtual-directory listing + // of the zip's members (no whole-zip + // download — zddc-server extracts on demand) + // - zip otherwise → fetch+JSZip; entries become virtual children + // - zip child dir → already-listed entries from the parent zip + // (the whole zip was enumerated when it + // expanded, so child dirs are pre-seeded) async function loadChildren(node) { if (node.loaded) return; try { if (node.isZip) { - await loadZipChildren(node); + if (state.source === 'server' && !zipNestedInsideZip(node)) { + // zddc-server serves "<…>.zip/" as a virtual + // directory: GET it as a listing, GET a member URL + // to extract just that file. Same shape as any + // server directory, so no JSZip on the client. + setChildren(node.id, + await loader.fetchServerChildren(pathFor(node) + '/')); + } else { + await loadZipChildren(node); + } } else if (node._zipSyntheticDir) { // Synthetic dir node materialized when a zip's entry // list referenced "a/b/file" but had no "a/" entry.