Erste Produktivversion
This commit is contained in:
51
web/html/js/store.js
Normal file
51
web/html/js/store.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// Ein einziger Zustandsspeicher. Ansichten lesen daraus und zeichnen sich
|
||||
// neu, wenn er sich ändert - niemand fasst fremde DOM-Knoten an.
|
||||
//
|
||||
// Das ist im Kern das, was ein Framework auch tut. Der Unterschied ist,
|
||||
// dass hier nichts passiert, was nicht in dieser Datei steht.
|
||||
"use strict";
|
||||
|
||||
const listeners = new Set();
|
||||
|
||||
export const state = {
|
||||
/** Aus /api/config, mit Rückfallwert für den ersten Start ohne Netz. */
|
||||
appName: "Einkaufsliste",
|
||||
user: null,
|
||||
lists: [],
|
||||
/** Ansicht der geöffneten Liste, so wie /view sie liefert. */
|
||||
view: null,
|
||||
markets: [],
|
||||
categories: [],
|
||||
online: navigator.onLine,
|
||||
/** "ok" | "offline" | "error" */
|
||||
syncState: navigator.onLine ? "ok" : "offline",
|
||||
/** Einmalige Meldung aus der Synchronisation, wird von der Ansicht
|
||||
* abgeholt und zurückgesetzt. */
|
||||
syncProblem: null,
|
||||
lastSync: null,
|
||||
};
|
||||
|
||||
export function subscribe(fn) {
|
||||
listeners.add(fn);
|
||||
return () => listeners.delete(fn);
|
||||
}
|
||||
|
||||
/** Nach jeder Zustandsänderung genau einmal aufrufen. Mehrere Aufrufe im
|
||||
* selben Tick werden zusammengefasst, damit nicht mehrfach gezeichnet wird. */
|
||||
let scheduled = false;
|
||||
export function notify() {
|
||||
if (scheduled) return;
|
||||
scheduled = true;
|
||||
queueMicrotask(() => {
|
||||
scheduled = false;
|
||||
for (const fn of listeners) fn(state);
|
||||
});
|
||||
}
|
||||
|
||||
export function set(patch) {
|
||||
Object.assign(state, patch);
|
||||
notify();
|
||||
}
|
||||
|
||||
window.addEventListener("online", () => set({ online: true }));
|
||||
window.addEventListener("offline", () => set({ online: false }));
|
||||
Reference in New Issue
Block a user