Three issues from initial v0.0.12 dev/prod testing:
1. Online listings empty.
directory.go was missing Vary: Accept on its responses, so
browser/CDN cached the HTML response (the embedded browse.html)
and served it again when browse's JS later fetched the same URL
with Accept: application/json. JSON parse failed, autoDetect
returned null, empty state showed. Adds Vary: Accept on both
branches and changes browse.html cache-control to no-cache so
deployed updates land immediately.
2. Top-level folder rows tall, shrink as subtree expands.
The .browse-table had flex:1 in a flex column. <table> in flex
doesn't reliably distribute height across rows — with few rows,
each row stretched. Wrap the table in a div with overflow:auto
and drop flex:1 from the table itself.
3. Recursive expand/collapse.
Shift-click (or alt-click) on a folder now expand-all or
collapse-all its subtree. Plain click still toggles just that
folder. Implementation: tree.expandSubtree() walks BFS, loading
each level's children in parallel, re-rendering between levels
so the user sees progress. tree.collapseSubtree() recursively
marks the subtree collapsed (children stay loaded for instant
re-expand).
82 lines
3.6 KiB
HTML
82 lines
3.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>ZDDC Browse</title>
|
|
<link rel="icon" type="image/svg+xml" href="{{FAVICON}}">
|
|
<style>
|
|
{{CSS_PLACEHOLDER}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="app-header">
|
|
<div class="header-left">
|
|
<svg class="app-header__logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" aria-hidden="true">
|
|
<rect width="64" height="64" rx="12" fill="#1e3a5f"/>
|
|
<g fill="#fff">
|
|
<rect x="14" y="18" width="36" height="7"/>
|
|
<polygon points="43,25 50,25 21,43 14,43"/>
|
|
<rect x="14" y="43" width="36" height="7"/>
|
|
</g>
|
|
</svg>
|
|
<div class="header-title-group">
|
|
<span class="app-header__title">ZDDC Browse</span>
|
|
<span class="build-timestamp">{{BUILD_LABEL}}</span>
|
|
</div>
|
|
<button id="addDirectoryBtn" class="btn btn-primary">Select Directory</button>
|
|
</div>
|
|
<div class="header-right">
|
|
<button id="theme-btn" class="btn btn-secondary" title="Theme: auto (follows OS)" aria-label="Theme: auto (follows OS)">◐</button>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="appMain">
|
|
<div id="emptyState" class="empty-state">
|
|
<div class="empty-state__inner">
|
|
<h2>ZDDC Browse</h2>
|
|
<p>A simple directory listing for ZDDC archives — and any directory.
|
|
Pick how you want to browse:</p>
|
|
<ul>
|
|
<li><b>Online</b> — when this page is served by zddc-server, the
|
|
listing for the current directory loads automatically.</li>
|
|
<li><b>Local</b> — click <i>Select Directory</i> to pick any folder
|
|
on your computer (Chromium-based browsers).</li>
|
|
</ul>
|
|
<p>Once loaded: click a folder to expand it, <b>shift-click</b>
|
|
to expand its entire subtree (or collapse it again),
|
|
click column headers to sort, type in the filter to narrow
|
|
by name. Click any file to open it.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="browseRoot" class="browse-root hidden">
|
|
<div class="toolbar">
|
|
<span class="toolbar__path" id="currentPath"></span>
|
|
<input type="search" id="filterInput" class="toolbar__filter"
|
|
placeholder="Filter by name (substring)..." />
|
|
<span class="toolbar__count" id="entryCount"></span>
|
|
</div>
|
|
<div class="browse-table-wrap">
|
|
<table class="browse-table" id="browseTable">
|
|
<thead>
|
|
<tr>
|
|
<th data-sort="name" class="col-name sortable">Name <span class="sort-arrow"></span></th>
|
|
<th data-sort="size" class="col-size sortable">Size <span class="sort-arrow"></span></th>
|
|
<th data-sort="ext" class="col-ext sortable">Type <span class="sort-arrow"></span></th>
|
|
<th data-sort="date" class="col-date sortable">Modified <span class="sort-arrow"></span></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="browseTbody"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<div id="statusBar" class="status-bar"></div>
|
|
|
|
<script>
|
|
{{JS_PLACEHOLDER}}
|
|
</script>
|
|
</body>
|
|
</html>
|