1
0

enable history navigation

The previous implementation only looked at the URL (and state) during
initialization. This allowed users to open a specific session via URL
(e.g. when reloading the page).

History navigation, however, was completely ignored. I.e. if the user
pressed the back button the URL would change, but the content would
remain the same.

This has now been corrected.
This commit is contained in:
Adrian Wannenmacher 2026-03-01 02:14:21 +01:00
parent b5ead20f0b
commit de0fc8c917
Signed by: tfld
GPG Key ID: 19D986ECB1E492D5
4 changed files with 55 additions and 30 deletions

View File

@ -6,8 +6,12 @@ import BaseView from "/ui/base_view.js";
m.route.prefix = "";
m.route(document.body, "/", {
"/": {
render: function() {
return m(Layout, m(BaseView));
render: function(vnode) {
let newSession = vnode.attrs.newSession ?? false;
let session = newSession ? null : parseInt(vnode.attrs.session);
session = isNaN(session) ? null : session;
return m(Layout, m(BaseView, { newSession, session }));
},
},
});

View File

@ -9,27 +9,22 @@ export default class BaseView {
#model = new BaseViewModel();
oninit() {
let id = m.route.param("session");
id = parseInt(id);
if (Number.isNaN(id))
id = null;
this.#model.current = id;
this.#model.loadAllSessions();
}
view() {
view(vnode) {
if (vnode.attrs.newSession)
this.#model.newSession();
else
this.#model.current = vnode.attrs.session;
if (this.#model.current !== null)
return m(SessionView, {
model: this.#model.current,
onDeselect: () => this.#model.current = null,
});
return m(SessionView, { model: this.#model.current });
if (this.#model.sessions !== null)
return m(SessionList, {
models: this.#model.sessions,
onSelect: (session) => this.#model.current = session,
onNew: () => this.#model.newSession(),
});
return m("p", "Wart kurz, i lad grad die Spiele…");
@ -48,30 +43,32 @@ class BaseViewModel {
if (value instanceof Session) {
this.#current = value;
this.#currentLoading = null;
m.route.set("/", { session: value.id });
} else if (typeof value === "number") {
if (value === this.#current?.id || value === this.#currentLoading)
return;
this.#currentLoading = value;
m.route.set("/", { session: value });
SessionRepo
.get(value)
.then((s) => {
if (this.#currentLoading === s?.id)
this.#current = s;
})
.catch((e) => {
console.error("failed to load session: ", e);
})
.finally(() => {
m.redraw();
if (this.#currentLoading === value)
this.#currentLoading = null;
m.redraw();
});
} else if (value === null) {
if (this.#current === null)
return;
this.#current = null;
this.#currentLoading = null;
this.loadAllSessions();
m.route.set("/");
} else {
throw new TypeError("current session must be session or id or null");
@ -96,13 +93,22 @@ class BaseViewModel {
.then(() => {
if (this.#currentLoading === BaseViewModel.#newSessionMarker) {
this.#current = session;
m.route.set("/", { session: session.id });
m.route.set("/", { session: session.id }, { replace: true });
}
})
.catch((e) => {
console.error("failed to create new session: ", e);
if (this.#currentLoading === BaseViewModel.#newSessionMarker)
m.route.set(
"/",
{ session: this.#current?.id ?? undefined },
{ replace: true });
else
m.redraw();
})
.finally(() => {
if (this.#currentLoading === BaseViewModel.#newSessionMarker)
this.#currentLoading = null;
m.redraw();
});
}

View File

@ -6,12 +6,12 @@ import RoundView from "/ui/round.js";
export default class SessionView {
/** @param {{ attrs: { model: Session } }} param The session model to use. */
view({ attrs: { model, onDeselect } }) {
view({ attrs: { model } }) {
let res = model.result;
return m("article.session-view", [
m("button", { onclick: () => onDeselect() }, "Zruck"),
m(m.route.Link, { href: "/", selector: "button" }, "Zruck"),
m("table", [
m("thead", [
m("tr", [

View File

@ -4,17 +4,32 @@ import Session from "/models/session.js";
export default class SessionList {
/** @param {{ attrs: { models: Session[] } }} param The sessions to show. */
view({attrs: { models, onSelect, onNew } }) {
view({attrs: { models, onSelect } }) {
return m("section", [
m("button", { onclick: () => onNew() }, "Neie Session"),
m(m.route.Link, {
href: "/",
selector: "button",
options: {
state: { newSession: true },
},
}, "Neie Session"),
m("ol", [
models.map((s) => m("li", [
m("button", { onclick: () => onSelect(s) }, [
m("p", s.ourTeam !== "" ? s.ourTeam : "Unbnannts Team"),
m("p", s.theirTeam !== "" ? s.theirTeam : "Unbnannts Team"),
m("p", "•".repeat(s.result.ourPoints)),
m("p", "•".repeat(s.result.theirPoints)),
])
m(
m.route.Link,
{
href: "/",
selector: "button",
params: { session: s.id },
onclick: () => onSelect(s),
},
[
m("p", s.ourTeam !== "" ? s.ourTeam : "Unbnannts Team"),
m("p", s.theirTeam !== "" ? s.theirTeam : "Unbnannts Team"),
m("p", "•".repeat(s.result.ourPoints)),
m("p", "•".repeat(s.result.theirPoints)),
],
),
]))
])
]);