1
0
silverbullet/web/navigator.ts

91 lines
2.1 KiB
TypeScript
Raw Normal View History

import { safeRun } from "../common/util.ts";
function encodePageUrl(name: string): string {
return name.replaceAll(" ", "_");
}
function decodePageUrl(url: string): string {
return url.replaceAll("_", " ");
}
2022-03-28 13:25:05 +00:00
export class PathPageNavigator {
navigationResolve?: () => void;
2022-08-02 10:43:39 +00:00
constructor(readonly indexPage: string, readonly root: string = "") {}
2022-07-22 11:44:28 +00:00
2022-08-30 08:44:20 +00:00
async navigate(page: string, pos?: number | string, replaceState = false) {
2022-08-02 10:43:39 +00:00
let encodedPage = encodePageUrl(page);
if (page === this.indexPage) {
encodedPage = "";
}
if (replaceState) {
window.history.replaceState(
{ page, pos },
page,
`${this.root}/${encodedPage}`,
);
} else {
window.history.pushState(
{ page, pos },
page,
`${this.root}/${encodedPage}`,
);
}
2022-04-01 13:02:35 +00:00
window.dispatchEvent(
new PopStateEvent("popstate", {
state: { page, pos },
}),
2022-03-28 13:25:05 +00:00
);
await new Promise<void>((resolve) => {
this.navigationResolve = resolve;
});
this.navigationResolve = undefined;
}
2022-03-28 13:25:05 +00:00
subscribe(
pageLoadCallback: (pageName: string, pos: number | string) => Promise<void>,
2022-03-28 13:25:05 +00:00
): void {
2022-04-01 13:03:12 +00:00
const cb = (event?: PopStateEvent) => {
const gotoPage = this.getCurrentPage();
if (!gotoPage) {
return;
}
safeRun(async () => {
2022-04-04 13:25:07 +00:00
await pageLoadCallback(
this.getCurrentPage(),
event?.state?.pos || this.getCurrentPos(),
2022-04-04 13:25:07 +00:00
);
2022-04-01 13:03:12 +00:00
if (this.navigationResolve) {
this.navigationResolve();
}
2022-04-01 13:03:12 +00:00
});
};
window.addEventListener("popstate", cb);
cb();
}
2022-08-30 08:44:20 +00:00
decodeURI(): [string, number | string] {
let [page, pos] = decodeURI(
location.pathname.substring(this.root.length + 1),
2022-07-22 11:44:28 +00:00
).split("@");
2022-08-30 08:44:20 +00:00
if (pos) {
if (pos.match(/^\d+$/)) {
return [page, +pos];
} else {
return [page, pos];
}
2022-04-24 16:06:34 +00:00
} else {
2022-08-30 08:44:20 +00:00
return [page, 0];
2022-04-24 16:06:34 +00:00
}
}
getCurrentPage(): string {
2022-08-02 10:43:39 +00:00
return decodePageUrl(this.decodeURI()[0]) || this.indexPage;
}
2022-08-30 08:44:20 +00:00
getCurrentPos(): number | string {
2022-07-22 11:44:28 +00:00
// console.log("Pos", this.decodeURI()[1]);
2022-04-24 16:06:34 +00:00
return this.decodeURI()[1];
}
}