add vertical layout
This commit is contained in:
parent
95c17c65d9
commit
ea5ac0cd10
|
@ -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>
|
||||||
|
|
|
@ -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}"]`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 });
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue