|
@@ -259,10 +259,16 @@ es.onmessage = ev => {
|
|
|
};
|
|
};
|
|
|
renderBell(); renderNotifs();
|
|
renderBell(); renderNotifs();
|
|
|
const P = new URLSearchParams(location.search);
|
|
const P = new URLSearchParams(location.search);
|
|
|
-const size0 = +(P.get("size") ?? 50);
|
|
|
|
|
|
|
+// Persistence: URL params (deep links) win; without them the last view is
|
|
|
|
|
+// restored from localStorage — bare reloads (server restart, new tab,
|
|
|
|
|
+// binary update) keep the column/settings state.
|
|
|
|
|
+const LS = (() => {
|
|
|
|
|
+ try { return JSON.parse(localStorage.getItem("report-view") || "{}"); } catch { return {}; }
|
|
|
|
|
+})();
|
|
|
|
|
+const pick = (k, dflt) => P.get(k) ?? (LS[k] ?? dflt);
|
|
|
|
|
+const size0 = +(pick("size", 50));
|
|
|
// distinct TP values from the data, for the exact-TP filter
|
|
// distinct TP values from the data, for the exact-TP filter
|
|
|
const TPVALS = [...new Set(DATA.map(r => r.tp))].sort((a, b) => a - b);
|
|
const TPVALS = [...new Set(DATA.map(r => r.tp))].sort((a, b) => a - b);
|
|
|
-const tpParam = P.get("tp");
|
|
|
|
|
for (const v of TPVALS) {
|
|
for (const v of TPVALS) {
|
|
|
const o = document.createElement("option");
|
|
const o = document.createElement("option");
|
|
|
o.value = String(v);
|
|
o.value = String(v);
|
|
@@ -270,17 +276,17 @@ for (const v of TPVALS) {
|
|
|
document.getElementById("tp").appendChild(o);
|
|
document.getElementById("tp").appendChild(o);
|
|
|
}
|
|
}
|
|
|
const S = {
|
|
const S = {
|
|
|
- q: P.get("q") ?? "",
|
|
|
|
|
- group: P.get("group") ?? "",
|
|
|
|
|
- sort: P.get("sort") ?? "name",
|
|
|
|
|
- dir: P.get("dir") ? +P.get("dir") : 1,
|
|
|
|
|
|
|
+ q: pick("q", ""),
|
|
|
|
|
+ group: pick("group", ""),
|
|
|
|
|
+ sort: pick("sort", "name"),
|
|
|
|
|
+ dir: pick("dir", 1) * 1 || 1,
|
|
|
size: [25, 50, 100, 0].includes(size0) ? size0 : 50,
|
|
size: [25, 50, 100, 0].includes(size0) ? size0 : 50,
|
|
|
- page: Math.max(0, +(P.get("page") ?? 0)),
|
|
|
|
|
- hidden: new Set((P.get("hidden") ?? "title,image,port,parent").split(",").filter(Boolean)),
|
|
|
|
|
- closed: new Set((P.get("closed") ?? "").split("|").map(decodeURIComponent).filter(Boolean)),
|
|
|
|
|
- openRow: P.get("open") ?? null,
|
|
|
|
|
- medal: P.get("medal") ?? "",
|
|
|
|
|
- tp: tpParam != null && TPVALS.includes(+tpParam) ? tpParam : "",
|
|
|
|
|
|
|
+ page: Math.max(0, +(P.get("page") ?? 0)), // page stays URL-only (fresh view = top)
|
|
|
|
|
+ hidden: new Set(String(pick("hidden", "title,image,port,parent")).split(",").filter(Boolean)),
|
|
|
|
|
+ closed: new Set(String(pick("closed", "")).split("|").map(decodeURIComponent).filter(Boolean)),
|
|
|
|
|
+ openRow: pick("open", null),
|
|
|
|
|
+ medal: pick("medal", ""),
|
|
|
|
|
+ tp: TPVALS.includes(+(pick("tp", ""))) ? String(pick("tp", "")) : "",
|
|
|
};
|
|
};
|
|
|
document.getElementById("q").value = S.q;
|
|
document.getElementById("q").value = S.q;
|
|
|
document.getElementById("group").value = S.group;
|
|
document.getElementById("group").value = S.group;
|
|
@@ -296,7 +302,7 @@ function syncUrl() {
|
|
|
if (S.size !== 50) p.set("size", String(S.size));
|
|
if (S.size !== 50) p.set("size", String(S.size));
|
|
|
if (S.page) p.set("page", String(S.page));
|
|
if (S.page) p.set("page", String(S.page));
|
|
|
const hidden = [...S.hidden].sort();
|
|
const hidden = [...S.hidden].sort();
|
|
|
- if (hidden.join(",") !== ["title", "image", "port"].sort().join(",")) p.set("hidden", hidden.join(","));
|
|
|
|
|
|
|
+ if (hidden.join(",") !== ["title", "image", "port", "parent"].sort().join(",")) p.set("hidden", hidden.join(","));
|
|
|
const closed = [...S.closed].map(encodeURIComponent);
|
|
const closed = [...S.closed].map(encodeURIComponent);
|
|
|
if (closed.length) p.set("closed", closed.join("|"));
|
|
if (closed.length) p.set("closed", closed.join("|"));
|
|
|
if (S.openRow) p.set("open", S.openRow);
|
|
if (S.openRow) p.set("open", S.openRow);
|
|
@@ -304,6 +310,13 @@ function syncUrl() {
|
|
|
if (S.tp) p.set("tp", S.tp);
|
|
if (S.tp) p.set("tp", S.tp);
|
|
|
const qs = p.toString();
|
|
const qs = p.toString();
|
|
|
history.replaceState(null, "", qs ? "?" + qs : location.pathname);
|
|
history.replaceState(null, "", qs ? "?" + qs : location.pathname);
|
|
|
|
|
+ try {
|
|
|
|
|
+ localStorage.setItem("report-view", JSON.stringify({
|
|
|
|
|
+ q: S.q, group: S.group, sort: S.sort, dir: S.dir, size: S.size,
|
|
|
|
|
+ hidden: [...S.hidden], closed: [...S.closed], openRow: S.openRow,
|
|
|
|
|
+ medal: S.medal, tp: S.tp,
|
|
|
|
|
+ }));
|
|
|
|
|
+ } catch { /* private mode etc. — URL still carries the state */ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const esc = s => String(s).replace(/[&<>"]/g, c => ({"&":"&","<":"<",">":">",'"':"""}[c]));
|
|
const esc = s => String(s).replace(/[&<>"]/g, c => ({"&":"&","<":"<",">":">",'"':"""}[c]));
|