1
0
Fork 0

add vertical layout

This commit is contained in:
Sean Sube 2024-05-18 19:46:56 -05:00
parent 95c17c65d9
commit ea5ac0cd10
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
5 changed files with 52 additions and 11 deletions

View File

@ -31,6 +31,7 @@ export interface AppProps {
export function appStateSelector(s: StoreState) { export function appStateSelector(s: StoreState) {
return { return {
layoutMode: s.layoutMode,
themeMode: s.themeMode, themeMode: s.themeMode,
setReadyState: s.setReadyState, setReadyState: s.setReadyState,
}; };
@ -38,12 +39,11 @@ export function appStateSelector(s: StoreState) {
export function App(props: AppProps) { export function App(props: AppProps) {
const state = useStore(store, appStateSelector); const state = useStore(store, appStateSelector);
const { themeMode, setReadyState } = state; const { layoutMode, themeMode, setReadyState } = state;
// socket stuff // socket stuff
const { lastMessage, readyState, sendMessage } = useWebSocket(props.socketUrl); const { lastMessage, readyState, sendMessage } = useWebSocket(props.socketUrl);
// socket senders
function renderEntity(type: string, entity: string) { function renderEntity(type: string, entity: string) {
sendMessage(JSON.stringify({ type: 'render', [type]: entity })); sendMessage(JSON.stringify({ type: 'render', [type]: entity }));
} }
@ -120,6 +120,24 @@ export function App(props: AppProps) {
setReadyState(readyState); setReadyState(readyState);
}, [readyState]); }, [readyState]);
function innerLayout(a: React.JSX.Element, b: React.JSX.Element) {
switch (layoutMode) {
case 'horizontal':
return <Allotment className='body-allotment'>{a}{b}</Allotment>;
case 'vertical':
default:
return <Stack direction='column'>{a}{b}</Stack>;
}
}
const layoutWidths = {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
horizontal: [400, 600],
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
vertical: [1000, 1000],
};
const [leftWidth, rightWidth] = layoutWidths[layoutMode];
return <ThemeProvider theme={theme}> return <ThemeProvider theme={theme}>
<CssBaseline /> <CssBaseline />
<DetailDialog renderEntity={renderEntity} /> <DetailDialog renderEntity={renderEntity} />
@ -127,15 +145,15 @@ export function App(props: AppProps) {
<Stack direction="column"> <Stack direction="column">
<Statusbar setName={setName} /> <Statusbar setName={setName} />
<Stack direction="row" spacing={2}> <Stack direction="row" spacing={2}>
<Allotment className='body-allotment'> {innerLayout(
<Stack direction="column" spacing={2} sx={{ minWidth: 400 }} className="scroll-history"> <Stack direction="column" spacing={2} sx={{ minWidth: leftWidth }} className="scroll-history">
<PlayerPanel sendInput={sendInput} /> <PlayerPanel sendInput={sendInput} />
<WorldPanel setPlayer={setPlayer} /> <WorldPanel setPlayer={setPlayer} />
</Stack> </Stack>,
<Stack direction="column" sx={{ minWidth: 600 }} className="scroll-history"> <Stack direction="column" sx={{ minWidth: rightWidth }} className="scroll-history">
<HistoryPanel renderEntity={renderEntity} renderEvent={renderEvent} /> <HistoryPanel renderEntity={renderEntity} renderEvent={renderEvent} />
</Stack> </Stack>
</Allotment> )}
</Stack> </Stack>
</Stack> </Stack>
</Container> </Container>

View File

@ -105,7 +105,7 @@ export function worldGraph(world: World): string {
} }
export function roomGraph(room: Room): Array<string> { export function roomGraph(room: Room): Array<string> {
return Object.entries(room.portals).map(([direction, destination]) => return room.portals.map((portal) =>
`"${room.name}" -> "${destination}" [label="${direction}"]` `"${room.name}" -> "${portal.destination}" [label="${portal.name}"]`
); );
} }

View File

@ -12,13 +12,20 @@ export interface Actor {
items: Array<Item>; items: Array<Item>;
} }
export interface Portal {
type: 'portal';
name: string;
description: string;
destination: string;
}
export interface Room { export interface Room {
type: 'room'; type: 'room';
name: string; name: string;
description: string; description: string;
portals: Record<string, string>;
actors: Array<Actor>; actors: Array<Actor>;
items: Array<Item>; items: Array<Item>;
portals: Array<Portal>;
} }
export interface World { export interface World {

View File

@ -38,10 +38,12 @@ export function statusbarStateSelector(s: StoreState) {
return { return {
autoScroll: s.autoScroll, autoScroll: s.autoScroll,
clientName: s.clientName, clientName: s.clientName,
layoutMode: s.layoutMode,
readyState: s.readyState, readyState: s.readyState,
themeMode: s.themeMode, themeMode: s.themeMode,
setAutoScroll: s.setAutoScroll, setAutoScroll: s.setAutoScroll,
setClientName: s.setClientName, setClientName: s.setClientName,
setLayoutMode: s.setLayoutMode,
setThemeMode: s.setThemeMode, setThemeMode: s.setThemeMode,
eventHistory: s.eventHistory, eventHistory: s.eventHistory,
}; };
@ -54,7 +56,7 @@ export interface StatusbarProps {
export function Statusbar(props: StatusbarProps) { export function Statusbar(props: StatusbarProps) {
const { setName } = props; const { setName } = props;
const state = useStore(store, statusbarStateSelector); const state = useStore(store, statusbarStateSelector);
const { autoScroll, clientName, readyState, themeMode, setAutoScroll, setClientName, setThemeMode, eventHistory } = state; const { autoScroll, clientName, layoutMode, readyState, themeMode, setAutoScroll, setClientName, setLayoutMode, setThemeMode, eventHistory } = state;
const connectionStatus = statusStrings[readyState as ReadyState]; const connectionStatus = statusStrings[readyState as ReadyState];
@ -76,6 +78,12 @@ export function Statusbar(props: StatusbarProps) {
inputProps={{ 'aria-label': 'controlled' }} inputProps={{ 'aria-label': 'controlled' }}
sx={{ marginLeft: 'auto' }} sx={{ marginLeft: 'auto' }}
/>} label="Auto Scroll" /> />} label="Auto Scroll" />
<FormControlLabel control={<Switch
checked={layoutMode === 'vertical'}
onChange={() => setLayoutMode(layoutMode === 'vertical' ? 'horizontal' : 'vertical')}
inputProps={{ 'aria-label': 'controlled' }}
sx={{ marginLeft: 'auto' }}
/>} label="Vertical Layout" />
</FormGroup> </FormGroup>
<FormGroup row> <FormGroup row>
<TextField <TextField

View File

@ -6,12 +6,15 @@ import { PaletteMode } from '@mui/material';
import { ReadyState } from 'react-use-websocket'; import { ReadyState } from 'react-use-websocket';
import { Actor, GameEvent, Item, Room, World } from './models'; import { Actor, GameEvent, Item, Room, World } from './models';
export type LayoutMode = 'horizontal' | 'vertical';
export interface ClientState { export interface ClientState {
autoScroll: boolean; autoScroll: boolean;
clientId: string; clientId: string;
clientName: string; clientName: string;
detailEntity: Maybe<Item | Actor | Room | World>; detailEntity: Maybe<Item | Actor | Room | World>;
eventHistory: Array<GameEvent>; eventHistory: Array<GameEvent>;
layoutMode: LayoutMode;
readyState: ReadyState; readyState: ReadyState;
themeMode: PaletteMode; themeMode: PaletteMode;
@ -20,6 +23,7 @@ export interface ClientState {
setClientId: (clientId: string) => void; setClientId: (clientId: string) => void;
setClientName: (name: string) => void; setClientName: (name: string) => void;
setDetailEntity: (entity: Maybe<Item | Actor | Room | World>) => void; setDetailEntity: (entity: Maybe<Item | Actor | Room | World>) => void;
setLayoutMode: (mode: LayoutMode) => void;
setReadyState: (state: ReadyState) => void; setReadyState: (state: ReadyState) => void;
setThemeMode: (mode: PaletteMode) => void; setThemeMode: (mode: PaletteMode) => void;
@ -59,6 +63,7 @@ export function createClientStore(): StateCreator<ClientState> {
clientName: '', clientName: '',
detailEntity: undefined, detailEntity: undefined,
eventHistory: [], eventHistory: [],
layoutMode: 'horizontal',
readyState: ReadyState.UNINSTANTIATED, readyState: ReadyState.UNINSTANTIATED,
themeMode: 'light', themeMode: 'light',
setAutoScroll(autoScroll) { setAutoScroll(autoScroll) {
@ -73,6 +78,9 @@ export function createClientStore(): StateCreator<ClientState> {
setDetailEntity(detailEntity) { setDetailEntity(detailEntity) {
set({ detailEntity }); set({ detailEntity });
}, },
setLayoutMode(mode) {
set({ layoutMode: mode });
},
setReadyState(state) { setReadyState(state) {
set({ readyState: state }); set({ readyState: state });
}, },