bitview: initial history support

This commit is contained in:
nym21
2025-08-31 14:50:36 +02:00
parent 8c75fbd0a4
commit cc6913c854
3 changed files with 126 additions and 62 deletions
@@ -97,9 +97,30 @@ const signals = {
}-${paramKey}`,
);
/** @type { ((this: Window, ev: PopStateEvent) => any) | undefined} */
let popstateCallback;
let serialized = /** @type {string | null} */ (null);
if (options.save.serializeParam !== false) {
serialized = new URLSearchParams(window.location.search).get(paramKey);
// popstateCallback =
// /** @type {(this: Window, ev: PopStateEvent) => any} */ (
// (_) => {
// serialized = new URLSearchParams(window.location.search).get(
// paramKey,
// );
// set(() =>
// serialized ? save.deserialize(serialized) : initialValue,
// );
// }
// );
// if (!popstateCallback) throw "Unreachable";
// window.addEventListener("popstate", popstateCallback);
// signals.onCleanup(() => {
// if (popstateCallback)
// window.removeEventListener("popstate", popstateCallback);
// });
}
if (serialized === null) {
try {
+32 -18
View File
@@ -2205,15 +2205,29 @@ function main() {
vecIdToIndexes,
});
// window.addEventListener("popstate", (_) => {
// const urlSelected = utils.url.pathnameToSelectedId();
// const option = options.list.find(
// (option) => urlSelected === option.id,
// );
// if (option) {
// options.selected.set(option);
// }
// });
window.addEventListener("popstate", (event) => {
const path = window.document.location.pathname
.split("/")
.filter((v) => v);
let folder = options.tree;
while (path.length) {
const id = path.shift();
const res = folder.find((v) => id === utils.stringToId(v.name));
if (!res) throw "Option not found";
if (path.length >= 1) {
if (!("tree" in res)) {
throw "Unreachable";
}
folder = res.tree;
} else {
if ("tree" in res) {
throw "Unreachable";
}
options.selected.set(res);
}
}
});
function initSelected() {
let firstRun = true;
@@ -2239,14 +2253,6 @@ function main() {
let firstTimeLoadingExplorer = true;
signals.createEffect(options.selected, (option) => {
if (previousElement) {
previousElement.hidden = true;
utils.url.resetParams(option);
utils.url.pushHistory(option.path);
} else {
utils.url.replaceHistory({ pathname: option.path });
}
/** @type {HTMLElement} */
let element;
@@ -2364,7 +2370,15 @@ function main() {
}
}
element.hidden = false;
if (element !== previousElement) {
if (previousElement) previousElement.hidden = true;
element.hidden = false;
}
if (!previousElement) {
utils.url.replaceHistory({ pathname: option.path });
}
previousElement = element;
});
}
+73 -44
View File
@@ -104,6 +104,8 @@
*
* @typedef {ExplorerOption | ChartOption | TableOption | SimulationOption | UrlOption} Option
*
* @typedef {(AnyPartialOption | PartialOptionsGroup)[]} PartialOptionsTree
*
* @typedef {Object} PartialOptionsGroup
* @property {string} name
* @property {PartialOptionsTree} tree
@@ -112,8 +114,6 @@
* @property {string} name
* @property {OptionsTree} tree
*
* @typedef {(AnyPartialOption | PartialOptionsGroup)[]} PartialOptionsTree
*
* @typedef {(Option | OptionsGroup)[]} OptionsTree
*
*/
@@ -4154,9 +4154,14 @@ export function initOptions({
}) {
const LS_SELECTED_KEY = `selected_id`;
const urlPath_ = window.document.location.pathname.substring(1).split("/");
const urlPath_ = window.document.location.pathname
.split("/")
.filter((v) => v);
const urlPath = urlPath_.length ? urlPath_ : undefined;
const savedPath = utils.storage.read(LS_SELECTED_KEY)?.split("/");
const savedPath = utils.storage
.read(LS_SELECTED_KEY)
?.split("/")
.filter((v) => v);
/** @type {Signal<Option>} */
const selected = signals.createSignal(/** @type {any} */ (undefined));
@@ -4183,6 +4188,15 @@ export function initOptions({
}, /** @type {Record<Unit, AnyFetchedSeriesBlueprint[]>} */ ({}));
}
/**
* @param {Option} option
*/
function selectOption(option) {
utils.url.pushHistory(option.path);
utils.url.resetParams(option);
selected.set(option);
}
/**
* @param {Object} args
* @param {Option} args.option
@@ -4217,7 +4231,7 @@ export function initOptions({
title,
text: name || option.name,
onClick: () => {
selected.set(() => option);
selectOption(option);
},
});
}
@@ -4343,52 +4357,66 @@ export function initOptions({
}
createRenderLiEffect();
} else {
/** @type {Option} */
let option;
const option = /** @type {Option} */ (anyPartial);
const name = anyPartial.name;
const path = [...parentPath, utils.stringToId(anyPartial.name)];
const name = option.name;
const path = [...parentPath, utils.stringToId(option.name)];
if ("kind" in anyPartial && anyPartial.kind === "explorer") {
option = /** @satisfies {ExplorerOption} */ ({
kind: anyPartial.kind,
name,
path,
title: anyPartial.title,
});
Object.assign(
option,
/** @satisfies {ExplorerOption} */ ({
kind: anyPartial.kind,
path,
name,
title: option.title,
}),
);
} else if ("kind" in anyPartial && anyPartial.kind === "table") {
option = /** @satisfies {TableOption} */ ({
kind: anyPartial.kind,
name,
path,
title: anyPartial.title,
});
Object.assign(
option,
/** @satisfies {TableOption} */ ({
kind: anyPartial.kind,
path,
name,
title: option.title,
}),
);
} else if ("kind" in anyPartial && anyPartial.kind === "simulation") {
option = /** @satisfies {SimulationOption} */ ({
kind: anyPartial.kind,
name,
path,
title: anyPartial.title,
});
Object.assign(
option,
/** @satisfies {SimulationOption} */ ({
kind: anyPartial.kind,
path,
name,
title: anyPartial.title,
}),
);
} else if ("url" in anyPartial) {
option = /** @satisfies {UrlOption} */ ({
kind: "url",
name,
path,
title: name,
qrcode: !!anyPartial.qrcode,
url: anyPartial.url,
});
Object.assign(
option,
/** @satisfies {UrlOption} */ ({
kind: "url",
path,
name,
title: name,
qrcode: !!anyPartial.qrcode,
url: anyPartial.url,
}),
);
} else {
const title = anyPartial.title || anyPartial.name;
option = /** @satisfies {ChartOption} */ ({
kind: "chart",
name,
title,
path,
top: arrayToRecord(anyPartial.top),
bottom: arrayToRecord(anyPartial.bottom),
});
const title = option.title || option.name;
Object.assign(
option,
/** @satisfies {ChartOption} */ ({
kind: "chart",
name,
title,
path,
top: arrayToRecord(anyPartial.top),
bottom: arrayToRecord(anyPartial.bottom),
}),
);
}
list.push(option);
@@ -4455,6 +4483,7 @@ export function initOptions({
tree: /** @type {OptionsTree} */ (partialOptions),
parent,
createOptionElement,
selectOption,
};
}
/** @typedef {ReturnType<typeof initOptions>} Options */