Set up the user interface state model and set up the admin user onboarding #283
|
@ -0,0 +1,48 @@
|
|||
import React, { createContext, PropsWithChildren, useEffect, useReducer } from "react";
|
||||
import { Tabletop } from "visions-types";
|
||||
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 { }
|
||||
|
||||
export const StateProvider = ({ children }: PropsWithChildren<StateProviderProps>) => {
|
||||
const [state, dispatch] = useReducer(stateReducer, initialState());
|
||||
|
||||
return <AppContext.Provider value={initialState()}>
|
||||
{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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,19 +2,17 @@ import React, { createContext, PropsWithChildren, useEffect, useReducer } from "
|
|||
import useWebSocket from "react-use-websocket";
|
||||
import { Message, Tabletop } from "visions-types";
|
||||
|
||||
type TabletopState = {
|
||||
tabletop: Tabletop;
|
||||
}
|
||||
type WebsocketState = { }
|
||||
|
||||
const initialState = (): TabletopState => ({ tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined } });
|
||||
|
||||
export const WebsocketContext = createContext<TabletopState>(initialState());
|
||||
export const WebsocketContext = createContext<WebsocketState>({});
|
||||
|
||||
interface WebsocketProviderProps {
|
||||
websocketUrl: string;
|
||||
}
|
||||
|
||||
export const WebsocketProvider = ({ websocketUrl, children }: PropsWithChildren<WebsocketProviderProps>) => {
|
||||
return <div> {children} </div>;
|
||||
/*
|
||||
const { lastMessage } = useWebSocket(websocketUrl);
|
||||
|
||||
const [state, dispatch] = useReducer(handleMessage, initialState());
|
||||
|
@ -29,8 +27,10 @@ export const WebsocketProvider = ({ websocketUrl, children }: PropsWithChildren<
|
|||
return (<WebsocketContext.Provider value={state}>
|
||||
{children}
|
||||
</WebsocketContext.Provider>);
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
const handleMessage = (state: TabletopState, message: Message): TabletopState => {
|
||||
console.log(message);
|
||||
switch (message.type) {
|
||||
|
@ -42,3 +42,4 @@ const handleMessage = (state: TabletopState, message: Message): TabletopState =>
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -8,12 +8,6 @@
|
|||
height: 100vh;
|
||||
}
|
||||
|
||||
.auth > div {
|
||||
border: var(--border-standard);
|
||||
border-radius: var(--border-radius-standard);
|
||||
padding: var(--padding-m);
|
||||
}
|
||||
|
||||
.auth__input-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { PropsWithChildren, ReactNode, useContext, useEffect, useState } from 'react';
|
||||
import { Client } from '../../client';
|
||||
import { AppContext } from '../../components/StateProvider';
|
||||
import { assertNever } from '../../plugins/Candela';
|
||||
import './Authentication.css';
|
||||
|
||||
|
@ -7,16 +8,14 @@ interface AuthenticationProps {
|
|||
client: Client;
|
||||
}
|
||||
|
||||
type AuthState = "NoAdmin" | "Unauthed" | "Authed";
|
||||
|
||||
export const Authentication = ({ client, children }: PropsWithChildren<AuthenticationProps>) => {
|
||||
// No admin password set: prompt for the admin password
|
||||
// Password set, nobody logged in: prompt for login
|
||||
// User logged in: show the children
|
||||
|
||||
let [state, setState] = useState<AuthState>("Unauthed");
|
||||
let { auth } = useContext(AppContext);
|
||||
|
||||
switch (state) {
|
||||
switch (auth.type) {
|
||||
case "NoAdmin": {
|
||||
return <div className="auth">
|
||||
<div className="card">
|
||||
|
@ -43,7 +42,7 @@ export const Authentication = ({ client, children }: PropsWithChildren<Authentic
|
|||
return <div> {children} </div>;
|
||||
}
|
||||
default: {
|
||||
assertNever(state);
|
||||
assertNever(auth);
|
||||
return <div></div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Client, PlayingField } from '../../client';
|
||||
import { AppContext } from '../../components/StateProvider';
|
||||
import { TabletopElement } from '../../components/Tabletop/Tabletop';
|
||||
import { ThumbnailElement } from '../../components/Thumbnail/Thumbnail';
|
||||
import { WebsocketContext } from '../../components/WebsocketProvider';
|
||||
|
@ -10,7 +11,7 @@ interface GmViewProps {
|
|||
}
|
||||
|
||||
export const GmView = ({ client }: GmViewProps) => {
|
||||
const { tabletop } = useContext(WebsocketContext);
|
||||
const { tabletop } = useContext(AppContext);
|
||||
|
||||
const [images, setImages] = useState<string[]>([]);
|
||||
useEffect(() => {
|
||||
|
|
|
@ -4,6 +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';
|
||||
|
||||
const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803";
|
||||
|
||||
|
@ -12,7 +13,7 @@ interface PlayerViewProps {
|
|||
}
|
||||
|
||||
export const PlayerView = ({ client }: PlayerViewProps) => {
|
||||
const { tabletop } = useContext(WebsocketContext);
|
||||
const { tabletop } = useContext(AppContext);
|
||||
|
||||
const [charsheet, setCharsheet] = useState(undefined);
|
||||
|
||||
|
|
Loading…
Reference in New Issue