fix comms
This commit is contained in:
+4
-1
@@ -25,7 +25,10 @@ export function VersionCheck() {
|
||||
const [count, setCount] = useState<string | number>("...");
|
||||
const [debug, setDebug] = comms.var("debug");
|
||||
|
||||
useKey("f2", () => setDebug(!debug));
|
||||
useKey("F2", () => {
|
||||
setDebug((x) => !x);
|
||||
});
|
||||
// console.log(`Debug mode ${debug ? "enabled" : "disabled"}`);
|
||||
|
||||
useEffect(() => {
|
||||
const es = new ReconnectingEventSource(`/api/active`, {});
|
||||
|
||||
+1
-1
@@ -47,9 +47,9 @@ export default function RootLayout({
|
||||
/>
|
||||
<Providers>
|
||||
<AnimatePresence mode="wait">{children}</AnimatePresence>
|
||||
<VersionCheck />
|
||||
</Providers>
|
||||
<Toaster theme="dark" richColors closeButton />
|
||||
<VersionCheck />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
+61
-38
@@ -2,7 +2,7 @@
|
||||
|
||||
import { createContext, use, useEffect, useRef, useState } from "react";
|
||||
|
||||
type WebsiteComms = Partial<{ manual: boolean, debug: boolean }>;
|
||||
type WebsiteComms = Partial<{ manual: boolean; debug: boolean }>;
|
||||
|
||||
type WebsiteSignals = { beforeSubmit: undefined } & WebsiteComms;
|
||||
|
||||
@@ -18,14 +18,19 @@ type WebsiteCommsMutator = {
|
||||
listener: (value: WebsiteSignals[K]) => void,
|
||||
): void;
|
||||
emit<K extends keyof WebsiteSignals>(key: K, value: WebsiteSignals[K]): void;
|
||||
active: boolean;
|
||||
};
|
||||
|
||||
export const CommsContext = createContext<WebsiteCommsMutator>({
|
||||
get: () => undefined,
|
||||
get: () => {
|
||||
console.error("Inter-component communication used outside of provider.");
|
||||
return undefined;
|
||||
},
|
||||
set: () => undefined,
|
||||
on: () => () => undefined,
|
||||
off: () => undefined,
|
||||
emit: () => undefined,
|
||||
active: false,
|
||||
});
|
||||
|
||||
export default function CommsProvider({
|
||||
@@ -33,63 +38,81 @@ export default function CommsProvider({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const [store, setStore] = useState<WebsiteComms>({});
|
||||
const storeRef = useRef<WebsiteComms>({});
|
||||
const [, forceUpdate] = useState({});
|
||||
|
||||
const listeners = useRef<{
|
||||
[K in keyof WebsiteSignals]?: Array<(value: WebsiteSignals[K]) => void>;
|
||||
}>({});
|
||||
return (
|
||||
<CommsContext
|
||||
value={{
|
||||
get: (k) => store[k],
|
||||
set: (k, v) => {
|
||||
setStore((x) => ({ ...x, [k]: v }));
|
||||
(listeners.current[k] || []).map((l) => l(v));
|
||||
},
|
||||
on: (k, listener) => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = [...(listeners.current[k] || []), listener];
|
||||
|
||||
return () => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = listeners.current[k]?.filter(
|
||||
(l) => l !== listener,
|
||||
);
|
||||
};
|
||||
},
|
||||
off: (k, listener) => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = (listeners.current[k] || []).filter(
|
||||
(l) => l !== listener,
|
||||
);
|
||||
},
|
||||
emit: (k, value) => {
|
||||
(listeners.current[k] || []).map((l) => l(value));
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</CommsContext>
|
||||
);
|
||||
const contextValue = useRef<WebsiteCommsMutator>({
|
||||
get: (k) => storeRef.current[k],
|
||||
set: (k, v) => {
|
||||
storeRef.current = { ...storeRef.current, [k]: v };
|
||||
(listeners.current[k] || []).map((l) => l(v));
|
||||
forceUpdate({});
|
||||
},
|
||||
on: (k, listener) => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = [...(listeners.current[k] || []), listener];
|
||||
return () => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = listeners.current[k]?.filter(
|
||||
(l) => l !== listener,
|
||||
);
|
||||
};
|
||||
},
|
||||
off: (k, listener) => {
|
||||
// @ts-expect-error
|
||||
listeners.current[k] = (listeners.current[k] || []).filter(
|
||||
(l) => l !== listener,
|
||||
);
|
||||
},
|
||||
emit: (k, value) => {
|
||||
(listeners.current[k] || []).map((l) => l(value));
|
||||
},
|
||||
active: true,
|
||||
});
|
||||
|
||||
return <CommsContext value={contextValue.current}>{children}</CommsContext>;
|
||||
}
|
||||
|
||||
export const comms = {
|
||||
var(name: keyof WebsiteComms) {
|
||||
const comms = use(CommsContext);
|
||||
const [state, setState] = useState(comms.get(name));
|
||||
if(!comms.active) {
|
||||
console.warn("Inter-component communication used outside of provider. Using local state instead.");
|
||||
}
|
||||
const [state, setState] = useState(comms.active?comms.get(name): undefined);
|
||||
useEffect(() => {
|
||||
function listener(value: WebsiteComms[typeof name]) {
|
||||
setState(value);
|
||||
}
|
||||
return comms.on(name, listener);
|
||||
}, [comms, name]);
|
||||
}, [name]);
|
||||
|
||||
return [state, comms.set.bind(comms, name)] as const;
|
||||
function mutator(
|
||||
value:
|
||||
| WebsiteComms[typeof name]
|
||||
| ((prev: WebsiteComms[typeof name]) => WebsiteComms[typeof name]),
|
||||
) {
|
||||
const v = typeof value === "function" ? value(comms.get(name)) : value;
|
||||
if(comms.active) comms.set(name, v);
|
||||
else setState(v);
|
||||
}
|
||||
|
||||
return [state, mutator] as const;
|
||||
},
|
||||
event<K extends keyof WebsiteSignals>(
|
||||
key: K,
|
||||
listener: (ev: WebsiteSignals[K]) => void,
|
||||
) {
|
||||
const comms = use(CommsContext);
|
||||
if (!comms.active) {
|
||||
console.warn(
|
||||
"Inter-component communication used outside of provider. No events will be emitted.",
|
||||
);
|
||||
}
|
||||
useEffect(() => {
|
||||
return comms.on(key, listener);
|
||||
}, [comms, key, listener]);
|
||||
|
||||
+2
-1
@@ -79,7 +79,8 @@
|
||||
"uuidv7": "^1.0.2",
|
||||
"vaul": "^1.1.2",
|
||||
"yaml": "^2.8.1",
|
||||
"zod": "^4.1.12"
|
||||
"zod": "^4.1.12",
|
||||
"zustand": "^5.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@better-auth/cli": "^1.3.34",
|
||||
|
||||
Reference in New Issue
Block a user