diff --git a/visions/ui/package-lock.json b/visions/ui/package-lock.json index 337109c..807f246 100644 --- a/visions/ui/package-lock.json +++ b/visions/ui/package-lock.json @@ -20,7 +20,6 @@ "classnames": "^2.5.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-redux": "^9.2.0", "react-router": "^6.28.0", "react-router-dom": "^6.28.0", "react-scripts": "5.0.1", @@ -3748,11 +3747,6 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" - }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -12926,28 +12920,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "node_modules/react-redux": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", - "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "dependencies": { - "@types/use-sync-external-store": "^0.0.6", - "use-sync-external-store": "^1.4.0" - }, - "peerDependencies": { - "@types/react": "^18.2.25 || ^19", - "react": "^18.0 || ^19", - "redux": "^5.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "redux": { - "optional": true - } - } - }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -15285,14 +15257,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/use-sync-external-store": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz", - "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/visions/ui/package.json b/visions/ui/package.json index f95789d..65707a6 100644 --- a/visions/ui/package.json +++ b/visions/ui/package.json @@ -15,7 +15,6 @@ "classnames": "^2.5.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-redux": "^9.2.0", "react-router": "^6.28.0", "react-router-dom": "^6.28.0", "react-scripts": "5.0.1", diff --git a/visions/ui/src/App.tsx b/visions/ui/src/App.tsx index a607bbb..373750c 100644 --- a/visions/ui/src/App.tsx +++ b/visions/ui/src/App.tsx @@ -1,4 +1,4 @@ -import React, { PropsWithChildren, useEffect, useState } from 'react'; +import React, { PropsWithChildren, useContext, useEffect, useState } from 'react'; import './App.css'; import { Client } from './client'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; @@ -9,8 +9,7 @@ import { PlayerView } from './views/PlayerView/PlayerView'; import { Admin } from './views/Admin/Admin'; import Candela from './plugins/Candela'; import { Authentication } from './views/Authentication/Authentication'; -import { StateProvider } from './components/StateProvider'; -import { AuthProvider } from './providers/AuthProvider/AuthProvider'; +import { StateContext, StateProvider } from './providers/StateProvider/StateProvider'; const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803"; @@ -33,13 +32,14 @@ interface AuthedViewProps { } const AuthedView = ({ client, children }: PropsWithChildren) => { - return ( - - console.log(password)} onAuth={(username, password) => console.log(username, password)}> - {children} - - - ); + const [state, dispatch] = useContext(StateContext); + return ( + { + dispatch({type: "SetAdminPassword", password }); + }} onAuth={(username, password) => console.log(username, password)}> + {children} + + ); } const App = ({ client }: AppProps) => { @@ -54,8 +54,7 @@ const App = ({ client }: AppProps) => { createBrowserRouter([ { path: "/", - element: - + element: }, { path: "/gm", diff --git a/visions/ui/src/components/StateProvider.tsx b/visions/ui/src/components/StateProvider.tsx deleted file mode 100644 index 79b504a..0000000 --- a/visions/ui/src/components/StateProvider.tsx +++ /dev/null @@ -1,32 +0,0 @@ -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 TabletopState = { - tabletop: Tabletop; -} - -type Action = {}; - -const initialState = (): TabletopState => ( - { - tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined } - } -); - -export const AppContext = createContext(initialState()); - -interface StateProviderProps { client: Client; } - -export const StateProvider = ({ client, children }: PropsWithChildren) => { - console.log("StateProvider"); - const [state, dispatch] = useReducer(stateReducer, initialState()); - - return - {children} - ; -} - -const stateReducer = (state: TabletopState, _action: Action): TabletopState => state; - diff --git a/visions/ui/src/providers/AuthProvider/AuthProvider.tsx b/visions/ui/src/providers/AuthProvider/AuthProvider.tsx deleted file mode 100644 index e32743d..0000000 --- a/visions/ui/src/providers/AuthProvider/AuthProvider.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { createContext, PropsWithChildren, useEffect, useReducer } from "react"; -import { Status } from "visions-types"; -import { Client } from "../../client"; - -type AuthState = { type: "NoAdmin" } | { type: "Unauthed" } | { type: "Authed", username: string }; - -type Action = { type: "SetAuthState", state: AuthState }; - -export const AuthContext = createContext({ type: "NoAdmin" }); - -interface AuthProviderProps { - client: Client; -} - -export const AuthProvider = ({ client, children }: PropsWithChildren) => { - const [authState, dispatch] = useReducer(stateReducer, { type: "NoAdmin" }); - - useEffect(() => { - client.status().then((status: Status) => { - if (status.admin_enabled) { - dispatch({ type: "SetAuthState", state: { type: "Unauthed" } }); - } else { - dispatch({ type: "SetAuthState", state: { type: "NoAdmin" } }); - } - }) - }, - [client] - ); - - return ( - {children} - ); -} - -const stateReducer = (_state: AuthState, action: Action) => action.state; diff --git a/visions/ui/src/providers/StateProvider/StateProvider.tsx b/visions/ui/src/providers/StateProvider/StateProvider.tsx new file mode 100644 index 0000000..9968cdd --- /dev/null +++ b/visions/ui/src/providers/StateProvider/StateProvider.tsx @@ -0,0 +1,37 @@ +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 AppState = { + auth: AuthState; + tabletop: Tabletop; +} + +type Action = { type: "SetAdminPassword", password: string } | { type: "Auth", username: string, password: string }; + +const initialState = (): AppState => ( + { + auth: { type: "NoAdmin" }, + tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined } + } +); + +const stateReducer = (state: AppState, action: Action): AppState => { + console.log("reducer: ", state, action); + return state; +} + +export const StateContext = createContext<[AppState, React.Dispatch]>([initialState(), () => { }]); + +interface StateProviderProps { client: Client; } + +export const StateProvider = ({ client, children }: PropsWithChildren) => { + const [state, dispatch] = useReducer(stateReducer, initialState()); + + return + {children} + ; +} diff --git a/visions/ui/src/views/Authentication/Authentication.tsx b/visions/ui/src/views/Authentication/Authentication.tsx index 39496ab..7b0e322 100644 --- a/visions/ui/src/views/Authentication/Authentication.tsx +++ b/visions/ui/src/views/Authentication/Authentication.tsx @@ -1,7 +1,6 @@ -import React, { PropsWithChildren, useContext, useState } from 'react'; -import { AppContext } from '../../components/StateProvider'; +import { PropsWithChildren, useContext, useState } from 'react'; +import { StateContext } from '../../providers/StateProvider/StateProvider'; import { assertNever } from '../../plugins/Candela'; -import { AuthContext } from '../../providers/AuthProvider/AuthProvider'; import './Authentication.css'; interface AuthenticationProps { @@ -16,9 +15,9 @@ export const Authentication = ({ onAdminPassword, onAuth, children }: PropsWithC let [userField, setUserField] = useState(""); let [pwField, setPwField] = useState(""); - let auth = useContext(AuthContext); + let [state, _] = useContext(StateContext); - switch (auth.type) { + switch (state.auth.type) { case "NoAdmin": { return
@@ -45,7 +44,7 @@ export const Authentication = ({ onAdminPassword, onAuth, children }: PropsWithC return
{children}
; } default: { - assertNever(auth); + assertNever(state.auth); return
; } } diff --git a/visions/ui/src/views/GmView/GmView.tsx b/visions/ui/src/views/GmView/GmView.tsx index 5d43745..948906e 100644 --- a/visions/ui/src/views/GmView/GmView.tsx +++ b/visions/ui/src/views/GmView/GmView.tsx @@ -1,6 +1,6 @@ -import React, { useContext, useEffect, useState } from 'react'; -import { Client, PlayingField } from '../../client'; -import { AppContext } from '../../components/StateProvider'; +import { useContext, useEffect, useState } from 'react'; +import { Client } from '../../client'; +import { StateContext } from '../../providers/StateProvider/StateProvider'; import { TabletopElement } from '../../components/Tabletop/Tabletop'; import { ThumbnailElement } from '../../components/Thumbnail/Thumbnail'; import { WebsocketContext } from '../../components/WebsocketProvider'; @@ -11,19 +11,19 @@ interface GmViewProps { } export const GmView = ({ client }: GmViewProps) => { - const { tabletop } = useContext(AppContext); + const [state, dispatch] = useContext(StateContext); const [images, setImages] = useState([]); useEffect(() => { client.availableImages().then((images) => setImages(images)); }, [client]); - const backgroundUrl = tabletop.backgroundImage ? client.imageUrl(tabletop.backgroundImage) : undefined; + const backgroundUrl = state.tabletop.backgroundImage ? client.imageUrl(state.tabletop.backgroundImage) : undefined; return (
{images.map((imageName) => { client.setBackgroundImage(imageName); }} />)}
- +
) } diff --git a/visions/ui/src/views/PlayerView/PlayerView.tsx b/visions/ui/src/views/PlayerView/PlayerView.tsx index 5ead8d2..3d3304c 100644 --- a/visions/ui/src/views/PlayerView/PlayerView.tsx +++ b/visions/ui/src/views/PlayerView/PlayerView.tsx @@ -4,7 +4,7 @@ import { WebsocketContext } from '../../components/WebsocketProvider'; import { Client } from '../../client'; import { TabletopElement } from '../../components/Tabletop/Tabletop'; import Candela from '../../plugins/Candela'; -import { AppContext } from '../../components/StateProvider'; +import { StateContext } from '../../providers/StateProvider/StateProvider'; const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803"; @@ -13,7 +13,7 @@ interface PlayerViewProps { } export const PlayerView = ({ client }: PlayerViewProps) => { - const { tabletop } = useContext(AppContext); + const [state, dispatch] = useContext(StateContext); const [charsheet, setCharsheet] = useState(undefined); @@ -26,9 +26,9 @@ export const PlayerView = ({ client }: PlayerViewProps) => { [client, setCharsheet] ); - const backgroundColor = tabletop.backgroundColor; + const backgroundColor = state.tabletop.backgroundColor; const tabletopColorStyle = `rgb(${backgroundColor.red}, ${backgroundColor.green}, ${backgroundColor.blue})`; - const backgroundUrl = tabletop.backgroundImage ? client.imageUrl(tabletop.backgroundImage) : undefined; + const backgroundUrl = state.tabletop.backgroundImage ? client.imageUrl(state.tabletop.backgroundImage) : undefined; return (