diff --git a/static/js/folders.js b/static/js/folders.js
index 8edf8b1..833bec2 100644
--- a/static/js/folders.js
+++ b/static/js/folders.js
@@ -22,22 +22,45 @@
// lead: chips before the folders (the library's Angefangen/Ungelesen …): [{id, label, count, on}],
// picked with onPick({lead: id}). active: null = all, '' = without a folder, else a name.
+ // The folders fold away (a "Ordner" chip), per area (the list's element id), remembered on
+ // this device; folded, only the folder chosen stays in sight.
+ function areaKey(el) {
+ const owner = el.id ? el : el.parentElement && el.parentElement.closest('[id]');
+ return 'diora_folders_folded_' + (owner ? owner.id : 'x');
+ }
+
+ function folded(el) {
+ try { return localStorage.getItem(areaKey(el)) === '1'; } catch (e) { return false; }
+ }
+
function chips(el, o) {
const lead = o.lead || [];
const leadOn = lead.some(c => c.on);
+ const folders = o.folders || [];
+ const fold = folders.length > 0 && folded(el);
let h = '
';
if (!lead.length) h += chip('dfo-all', 'Alle', null, o.active == null && !leadOn, 'data-dfo-all="1"');
lead.forEach(c => { h += chip('', c.label, c.count, !!c.on, 'data-dfo-lead="' + esc(c.id) + '"'); });
- if (lead.length && (o.folders || []).length) h += '';
- (o.folders || []).forEach(f => {
+ if (lead.length && folders.length) h += '';
+ if (folders.length) {
+ h += '';
+ }
+ folders.forEach(f => {
+ if (fold && o.active !== f.name) return;
h += chip('', f.name, f.count, o.active === f.name, 'data-dfo-folder="' + esc(f.name) + '"');
});
- if (o.none) h += chip('dfo-none', 'Ohne Ordner', o.none, o.active === '', 'data-dfo-folder=""');
- if (o.onManage) h += '';
+ if (o.none && (!fold || o.active === '')) h += chip('dfo-none', 'Ohne Ordner', o.none, o.active === '', 'data-dfo-folder=""');
+ if (o.onManage && !fold) h += '';
el.innerHTML = h + '
';
el.onclick = e => {
const b = e.target.closest('button');
if (!b) return;
+ if (b.dataset.dfoFold) {
+ try { localStorage.setItem(areaKey(el), fold ? '0' : '1'); } catch (err) {}
+ chips(el, o);
+ return;
+ }
if (b.dataset.dfoManage) { o.onManage(); return; }
if (b.dataset.dfoAll) { o.onPick(null); return; }
if (b.dataset.dfoLead != null) { o.onPick({lead: b.dataset.dfoLead}); return; }
@@ -188,6 +211,7 @@
'.dfo-count { opacity: .7; font-size: 12px; }',
'.dfo-none { font-style: italic; }',
'.dfo-manage { min-width: 34px; padding: 0 8px; }',
+ '.dfo-fold { border-style: dashed; }',
'.dfo-sep { flex: none; width: 1px; height: 20px; background: var(--border-strong, #444); margin: 0 2px; }',
// Above the book view (900), below the page's dialogs (990): a name is asked for on top.
'.dfo-scrim { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 950; background: var(--scrim, rgba(0,0,0,.5)); display: flex; align-items: flex-end; justify-content: center; }',
diff --git a/static/js/sw.js b/static/js/sw.js
index 77c5ebd..08eeb26 100644
--- a/static/js/sw.js
+++ b/static/js/sw.js
@@ -2,7 +2,7 @@
* diora service worker — caches the app shell for offline use.
*/
-const CACHE = 'diora-v158';
+const CACHE = 'diora-v159';
const SHELL = [
'/static/css/app.css',
'/static/js/app/01-core.js',