diff --git a/index.html b/index.html
index aefc83c..922954b 100644
--- a/index.html
+++ b/index.html
@@ -7,16 +7,13 @@
Watterblock
-
+
+
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..7e6cead
--- /dev/null
+++ b/index.js
@@ -0,0 +1,13 @@
+"use strict";
+
+import Layout from "/ui/layout.js";
+import BaseView from "/ui/base_view.js";
+
+m.route.prefix = "";
+m.route(document.body, "/", {
+ "/": {
+ render: function() {
+ return m(Layout, m(BaseView));
+ },
+ },
+});
diff --git a/ui/app.js b/ui/app.js
deleted file mode 100644
index 51f7fa9..0000000
--- a/ui/app.js
+++ /dev/null
@@ -1,43 +0,0 @@
-"use strict";
-
-import WbDb from "/data/db.js";
-import Shell from "/ui/shell.js";
-
-export default class App {
- #needsHandler = true;
-
- constructor() {
- WbDb.get().addEventListener(WbDb.EVENT_CHANGE, () => {
- if (this.#needsHandler) {
- WbDb.get().db.addEventListener("error", e => console.log(e));
- this.#needsHandler = false;
- }
- m.redraw();
- });
- }
-
- view() {
- let db = WbDb.get();
-
- if (db.failed)
- return m.fragment([
- m("h1", "Watterblock kann nicht geöffnet werden"),
- m("p", "Die IndexedDB-Verbindung funktioniert gerade nicht"),
- ]);
-
- if (db.blocked)
- return m.fragment([
- 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/shell.js b/ui/base_view.js
similarity index 97%
rename from ui/shell.js
rename to ui/base_view.js
index e19df09..9554462 100644
--- a/ui/shell.js
+++ b/ui/base_view.js
@@ -5,7 +5,7 @@ import SessionRepo from "/data/session_repo.js";
import SessionList from "/ui/session_list.js";
import SessionView from "/ui/session.js";
-export default class Shell {
+export default class BaseView {
/** @type(?Session[]) */
#sessions = null;
/** @type(?Session) */
diff --git a/ui/layout.js b/ui/layout.js
new file mode 100644
index 0000000..7b49490
--- /dev/null
+++ b/ui/layout.js
@@ -0,0 +1,50 @@
+"use strict";
+
+import WbDb from "/data/db.js";
+
+export default class Layout {
+ #db = WbDb.get();
+ #dbErrorsHandled = false;
+
+ constructor() {
+ this.#db.addEventListener(WbDb.EVENT_CHANGE, () => {
+ if (!this.#dbErrorsHandled) {
+ this.#db.addEventListener("error", this.#handleDbError.bind(this));
+ this.#dbErrorsHandled = true;
+ }
+ m.redraw();
+ });
+
+ if (this.#db.open && !this.#dbErrorsHandled) {
+ this.#db.addEventListener("error", this.#handleDbError.bind(this));
+ this.#dbErrorsHandled = true;
+ }
+ }
+
+ #handleDbError(error) {
+ console.error("database error", error);
+ }
+
+ view(vnode) {
+ if (this.#db.failed)
+ return m.fragment([
+ m("h1", "Watterblock kann nicht geöffnet werden"),
+ m("p", "Die IndexedDB-Verbindung funktioniert gerade nicht"),
+ ]);
+
+ if (this.#db.blocked)
+ return m.fragment([
+ 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 (!this.#db.open)
+ return m("p", "Öffne Datenbank, bitte warten…");
+
+ return m("main", vnode.children);
+ }
+}