From 979dfb9b08a48c2fd157293a012bec5075513c30 Mon Sep 17 00:00:00 2001 From: Adrian Wannenmacher Date: Wed, 18 Feb 2026 19:01:03 +0100 Subject: [PATCH] make basic UI fully functional --- ui/app.js | 50 +++++++++++++++++++++++++++++++------------------- ui/session.js | 3 ++- ui/shell.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 ui/shell.js diff --git a/ui/app.js b/ui/app.js index a399870..e3505a8 100644 --- a/ui/app.js +++ b/ui/app.js @@ -1,31 +1,43 @@ "use strict"; -import Session from "../models/session.js"; import WbDb from "../data/db.js"; -import SessionRepo from "../data/session_repo.js"; -import SessionList from "./session_list.js"; +import Shell from "./shell.js"; export default class App { - #sessions = []; + #needsHandler = true; constructor() { - let db = WbDb.get(); - if (db.open) - this.#dbReady(); - else - db.addEventListener(WbDb.EVENT_CHANGE, this.#dbReady.bind(this)); - } - - async #dbReady() { - this.#sessions = await SessionRepo.getAll(); - m.redraw(); + WbDb.get().addEventListener(WbDb.EVENT_CHANGE, () => { + if (this.#needsHandler) { + WbDb.get().db.addEventListener("error", e => console.log(e)); + this.#needsHandler = false; + } + m.redraw(); + }); } view() { - return m(SessionList, { - models: this.#sessions, - onSelect: (key) => console.log("selected", key), - onNew: () => console.log("new"), - }); + let db = WbDb.get(); + + if (db.failed) + return m("[", [ + m("h1", "Watterblock kann nicht geöffnet werden"), + m("p", "Die IndexedDB-Verbindung funktioniert gerade nicht"), + ]); + + if (db.blocked) + return m("[", [ + m("h1", "Watterblock muss warten"), + m("p", + "Bitte schließe alle anderen Tabs, in denen der Watterblock " + + "geöffnet ist" + ), + m("p", "Die Spieledatenbank muss aktualisiert werden."), + ]); + + if (!db.open) + return m("p", "Öffne Datenbank, bitte warten…"); + + return m(Shell); } } diff --git a/ui/session.js b/ui/session.js index a835973..1adaa29 100644 --- a/ui/session.js +++ b/ui/session.js @@ -5,8 +5,9 @@ import GameView from "./game.js"; export default class SessionView { /** @param {{ attrs: { model: Session } }} param The session model to use. */ - view({ attrs: { model } }) { + view({ attrs: { model, onDeselect } }) { return m("article", [ + m("button", { onclick: () => onDeselect() }, "Zruck"), model.games.map((g) => m(GameView, { model: g })), model.currentGame !== null ? m(GameView, { model: model.currentGame }) diff --git a/ui/shell.js b/ui/shell.js new file mode 100644 index 0000000..e69647b --- /dev/null +++ b/ui/shell.js @@ -0,0 +1,44 @@ +"use strict"; + +import Session from "../models/session.js"; +import SessionRepo from "../data/session_repo.js"; +import SessionList from "./session_list.js"; +import SessionView from "./session.js"; + +export default class Shell { + /** @type(?Session[]) */ + #sessions = null; + /** @type(?Session) */ + #currentSession = null; + + constructor() { + SessionRepo.getAll().then(ls => { + this.#sessions = ls; + m.redraw(); + }); + } + + view() { + if (this.#currentSession !== null) + return m(SessionView, { + model: this.#currentSession, + onDeselect: () => this.#currentSession = null; + }); + + if (this.#sessions !== null) + return m(SessionList, { + models: this.#sessions, + onSelect: async (key) => { + this.#currentSession = await SessionRepo.get(key) ?? null; + }, + onNew: async () => { + let session = new Session(); + await SessionRepo.put(session); + this.#currentSession = session; + this.#sessions.splice(0, 0, session); + } + }); + + return m("p", "Wart kurz, i lad grad die Spiele…"); + } +}