commit 8b608a527a049fa4f21244edcbf6d6b608119da3
parent f2e599412f1a2143b99571336a83aa223792cea5
Author: tongong <tongong@gmx.net>
Date: Wed, 30 Mar 2022 11:47:28 +0200
fancy state management with zustand
Diffstat:
7 files changed, 88 insertions(+), 37 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -8,7 +8,8 @@
"mithril": "^2.0.4",
"y-textarea": "^0.2.2",
"y-webrtc": "^10.2.2",
- "yjs": "^13.5.32"
+ "yjs": "^13.5.32",
+ "zustand": "^3.7.1"
},
"devDependencies": {
"parcel": "^2.0.0-rc.0",
@@ -2628,6 +2629,22 @@
"type": "GitHub Sponsors ❤",
"url": "https://github.com/sponsors/dmonad"
}
+ },
+ "node_modules/zustand": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.1.tgz",
+ "integrity": "sha512-wHBCZlKj+bg03/hP+Tzv24YhnqqP8MCeN9ECPDXoF01062SIbnfl3j9O0znkDw1lNTY0a8WN3F///a0UhhaEqg==",
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ }
+ }
}
},
"dependencies": {
@@ -4303,6 +4320,12 @@
"requires": {
"lib0": "^0.2.47"
}
+ },
+ "zustand": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.1.tgz",
+ "integrity": "sha512-wHBCZlKj+bg03/hP+Tzv24YhnqqP8MCeN9ECPDXoF01062SIbnfl3j9O0znkDw1lNTY0a8WN3F///a0UhhaEqg==",
+ "requires": {}
}
}
}
diff --git a/package.json b/package.json
@@ -3,7 +3,8 @@
"mithril": "^2.0.4",
"y-textarea": "^0.2.2",
"y-webrtc": "^10.2.2",
- "yjs": "^13.5.32"
+ "yjs": "^13.5.32",
+ "zustand": "^3.7.1"
},
"devDependencies": {
"parcel": "^2.0.0-rc.0",
diff --git a/src/components/qr-view.js b/src/components/qr-view.js
@@ -1,17 +1,21 @@
const m = require("mithril");
+const store = require("../modules/store.js");
const qr = require("../modules/qrcode.js");
module.exports = () => {
return {
view: () => m(".page.qrwrap", {
oncreate: (v) => {
- new qr(v.dom, {
- text: "https://wikipedia.org",
+ let qrcode = new qr(v.dom, {
+ text: window.location.href,
colorDark: "#212121",
colorLight: "#dcdcdc",
width: 512,
height: 512,
});
+ store.subscribe(s => s.id,
+ () => qrcode.makeCode(window.location.href)
+ );
}
})
}
diff --git a/src/main.js b/src/main.js
@@ -1,30 +1,14 @@
const m = require("mithril");
-const state = require("./modules/state.js");
+const store = require("./modules/store.js");
const editView = require("./components/edit-view.js");
const qrView = require("./components/qr-view.js");
-// ugly workaround to fix scrolling on route change
-// https://github.com/MithrilJS/mithril.js/issues/1655
-m.mount(
- // Don't attach to the document
- document.createDocumentFragment(),
- {
- // We need a valid view for Mithril to behave
- view : () => '',
- // Will execute on the DOM ready phase of every draw
- onupdate(){
- const route = m.route.get();
- if (route != this.route) scrollTo(0, 0);
- this.route = route;
- }
- }
-)
-
+store.subscribe(s => s, () => m.redraw());
const main = () => {
return {
view: () => m(".pagewrap", {
- class: state.qr? "": "scroll-down",
+ class: store().qr? "" : "scroll-down",
},
m(qrView),
m(editView),
@@ -32,8 +16,12 @@ const main = () => {
}
}
-document.body.onclick = state.closeQr;
+document.body.onclick = store().qrClose;
-m.route(document.body, "/", {
- "/": main,
+store.subscribe(s => s.id, id => m.route.set(id));
+m.route(document.body, "/-", {
+ "/:id": { onmatch: (args) => {
+ store().idSet(args.id);
+ return main;
+ }},
});
diff --git a/src/modules/navigation.js b/src/modules/navigation.js
@@ -0,0 +1,23 @@
+function generateId() {
+ let arr = new Uint8Array(32);
+ window.crypto.getRandomValues(arr);
+ return Array.from(arr)
+ .flatMap(e => [e % 16, e >> 4])
+ .map(e => "0123456789abcdef"[e])
+ .join("");
+}
+
+function isIdValid(id) {
+ if (id.length != 64) return false;
+ return id.split("").every(e => "0123456789abcdef".includes(e));
+}
+
+function splitId(id) {
+ return [id.substring(0,32), id.substring(32,64)];
+}
+
+module.exports = {
+ generateId,
+ isIdValid,
+ splitId,
+}
diff --git a/src/modules/state.js b/src/modules/state.js
@@ -1,11 +0,0 @@
-const m = require("mithril");
-
-const state = {
- qr: true,
- closeQr: function() {
- state.qr = false;
- m.redraw();
- }
-}
-
-module.exports = state;
diff --git a/src/modules/store.js b/src/modules/store.js
@@ -0,0 +1,23 @@
+const createStore = require("zustand/vanilla").default;
+const { subscribeWithSelector } = require("zustand/middleware");
+
+const navigation = require("./navigation.js");
+
+/* makes the store a function object from getState */
+function bindGetFn(store) {
+ let n = store.getState;
+ n.setState = store.setState;
+ n.subscribe = store.subscribe;
+ n.destroy = store.destroy;
+ return n;
+}
+
+module.exports = bindGetFn(createStore(subscribeWithSelector(set => ({
+ qr: true,
+ qrClose: () => set(() => ({ qr: false })),
+ id: "",
+ idSet: (n) => {
+ if (!navigation.isIdValid(n)) n = navigation.generateId();
+ return set(() => ({id: n}))
+ },
+}))));