reverseqr

qr codes working in both directions
git clone https://tongong.net/git/reverseqr.git
Log | Files | Refs | README

commit 8b608a527a049fa4f21244edcbf6d6b608119da3
parent f2e599412f1a2143b99571336a83aa223792cea5
Author: tongong <tongong@gmx.net>
Date:   Wed, 30 Mar 2022 11:47:28 +0200

fancy state management with zustand

Diffstat:
Mpackage-lock.json | 25++++++++++++++++++++++++-
Mpackage.json | 3++-
Msrc/components/qr-view.js | 8++++++--
Msrc/main.js | 32++++++++++----------------------
Asrc/modules/navigation.js | 23+++++++++++++++++++++++
Dsrc/modules/state.js | 11-----------
Asrc/modules/store.js | 23+++++++++++++++++++++++
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})) + }, +}))));