1
0
watterblock/ui/base_view.js

170 lines
4.3 KiB
JavaScript

"use strict";
import Session from "/models/session.js";
import SessionRepo from "/data/session_repo.js";
import SessionList from "/ui/session_list.js";
import SessionView from "/ui/session.js";
export default class BaseView {
#model = new BaseViewModel();
oninit() {
this.#model.loadAllSessions();
}
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 });
if (this.#model.sessions !== null)
return m(SessionList, {
models: this.#model.sessions,
onSelect: (session) => this.#model.current = session,
onDelete: (id, index) => this.#model.deleteSession(id, index),
});
return m("p", "Wart kurz, i lad grad die Spiele…");
}
}
class BaseViewModel {
#current = null;
#currentLoading = null;
get current() {
return this.#current;
}
#setCurrent(value) {
if (this.#current !== null)
this.#current.removeEventListener(
Session.EVENT_CHANGE, this.#handleCurrentUpdate);
if (value !== null)
value.addEventListener(Session.EVENT_CHANGE, this.#handleCurrentUpdate);
this.#current = value;
}
set current(value) {
if (value instanceof Session) {
this.#setCurrent(value);
this.#currentLoading = null;
} else if (typeof value === "number") {
if (value === this.#current?.id || value === this.#currentLoading)
return;
this.#currentLoading = value;
SessionRepo
.get(value)
.then((s) => {
if (this.#currentLoading === s?.id)
this.#setCurrent(s);
})
.catch((e) => {
console.error("failed to load session: ", e);
})
.finally(() => {
m.redraw();
if (this.#currentLoading === value)
this.#currentLoading = null;
});
} else if (value === null) {
if (this.#current === null)
return;
this.#setCurrent(null);
this.#currentLoading = null;
} else {
throw new TypeError("current session must be session or id or null");
}
}
get currentLoading() {
return this.#currentLoading !== null;
}
static #newSessionMarker = Symbol("new session loading");
newSession() {
if (this.#currentLoading === BaseViewModel.#newSessionMarker)
return;
this.#currentLoading = BaseViewModel.#newSessionMarker;
let session = new Session();
SessionRepo
.put(session)
.then(() => {
if (this.#currentLoading === BaseViewModel.#newSessionMarker) {
this.#setCurrent(session);
this.#sessions.splice(0, 0, session);
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;
});
}
#sessions = null;
#sessionsLoading = false;
get sessions() {
return this.#sessions;
}
loadAllSessions() {
if (this.#sessionsLoading)
return;
this.#sessionsLoading = true;
SessionRepo
.getAllFromNewest()
.then(s => this.#sessions = s)
.finally(() => {
this.#sessionsLoading = false;
m.redraw();
});
}
#handleCurrentUpdate = (e) => {
if (this.#current !== e.target || this.#current === this.#sessions[0]) {
e.target.removeEventListener(
Session.EVENT_CHANGE, this.#handleCurrentUpdate);
return;
}
if (this.#current?.id === this.#sessions[0]?.id) {
e.target.removeEventListener(
Session.EVENT_CHANGE, this.#handleCurrentUpdate);
this.#sessions[0] = this.#current;
return;
}
this.loadAllSessions();
};
deleteSession(id, index) {
SessionRepo.delete(id);
if (this.#sessions[index] === undefined || this.#sessions[index].id !== id)
return;
this.#sessions.splice(index, 1);
}
}