monorepo/visions/ui/src/components/StateProvider.tsx

65 lines
1.9 KiB
TypeScript

import React, { createContext, PropsWithChildren, useCallback, useEffect, useReducer } from "react";
import { Status, Tabletop } from "visions-types";
import { Client } from "../client";
import { assertNever } from "../plugins/Candela";
type AuthState = { type: "NoAdmin" } | { type: "Unauthed" } | { type: "Authed", username: string };
type TabletopState = {
auth: AuthState;
tabletop: Tabletop;
}
type StateAction = { type: "SetAuthState", state: AuthState }
| { type: "HandleMessage" };
const initialState = (): TabletopState => (
{
auth: { type: "Unauthed" },
tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined }
}
);
export const AppContext = createContext<TabletopState>(initialState());
interface StateProviderProps { client: Client; }
export const StateProvider = ({ client, children }: PropsWithChildren<StateProviderProps>) => {
console.log("StateProvider");
const [state, dispatch] = useReducer(stateReducer, initialState());
useEffect(() => {
console.log("useCallback");
client.status().then((status: Status) => {
console.log("status: ", status);
if (status.admin_enabled) {
dispatch({ type: "SetAuthState", state: { type: "Unauthed" } });
} else {
dispatch({ type: "SetAuthState", state: { type: "NoAdmin" } });
}
})
},
[client]
);
return <AppContext.Provider value={state}>
{children}
</AppContext.Provider>;
}
const stateReducer = (state: TabletopState, action: StateAction): TabletopState => {
switch (action.type) {
case "SetAuthState": {
return { ...state, auth: action.state };
}
case "HandleMessage": {
return state;
}
default: {
assertNever(action);
return state;
}
}
}