refactor: move shell into its own component
This commit is contained in:
parent
839628dc75
commit
bf4b6b18d6
@ -1,42 +1,19 @@
|
|||||||
import {
|
import { useEffect, useState } from 'react'
|
||||||
forwardRef,
|
|
||||||
useCallback,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useState,
|
|
||||||
SyntheticEvent,
|
|
||||||
} from 'react'
|
|
||||||
import { Routes, Route } from 'react-router-dom'
|
import { Routes, Route } from 'react-router-dom'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
import localforage from 'localforage'
|
import localforage from 'localforage'
|
||||||
import AppBar from '@mui/material/AppBar'
|
|
||||||
import Toolbar from '@mui/material/Toolbar'
|
|
||||||
import Box from '@mui/material/Box'
|
|
||||||
import Typography from '@mui/material/Typography'
|
|
||||||
import StepIcon from '@mui/material/StepIcon'
|
|
||||||
import Tooltip from '@mui/material/Tooltip'
|
|
||||||
import Snackbar from '@mui/material/Snackbar'
|
|
||||||
import MuiAlert, { AlertProps, AlertColor } from '@mui/material/Alert'
|
|
||||||
|
|
||||||
import { ShellContext } from 'ShellContext'
|
|
||||||
import { Home } from 'pages/Home/'
|
import { Home } from 'pages/Home/'
|
||||||
import { PublicRoom } from 'pages/PublicRoom/'
|
import { PublicRoom } from 'pages/PublicRoom/'
|
||||||
import { UserSettings } from 'models/settings'
|
import { UserSettings } from 'models/settings'
|
||||||
import { PersistedStorageKeys } from 'models/storage'
|
import { PersistedStorageKeys } from 'models/storage'
|
||||||
import { AlertOptions } from 'models/shell'
|
import { Shell } from 'components/Shell'
|
||||||
|
|
||||||
export interface BootstrapProps {
|
export interface BootstrapProps {
|
||||||
persistedStorage?: typeof localforage
|
persistedStorage?: typeof localforage
|
||||||
getUuid?: typeof uuid
|
getUuid?: typeof uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
|
||||||
props,
|
|
||||||
ref
|
|
||||||
) {
|
|
||||||
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
|
|
||||||
})
|
|
||||||
|
|
||||||
function Bootstrap({
|
function Bootstrap({
|
||||||
persistedStorage = localforage.createInstance({
|
persistedStorage = localforage.createInstance({
|
||||||
name: 'chitchatter',
|
name: 'chitchatter',
|
||||||
@ -45,37 +22,8 @@ function Bootstrap({
|
|||||||
getUuid = uuid,
|
getUuid = uuid,
|
||||||
}: BootstrapProps) {
|
}: BootstrapProps) {
|
||||||
const [hasLoadedSettings, setHasLoadedSettings] = useState(false)
|
const [hasLoadedSettings, setHasLoadedSettings] = useState(false)
|
||||||
const [isAlertShowing, setIsAlertShowing] = useState(false)
|
|
||||||
const [alertSeverity, setAlertSeverity] = useState<AlertColor>('info')
|
|
||||||
const [settings, setSettings] = useState({ userId: getUuid() })
|
const [settings, setSettings] = useState({ userId: getUuid() })
|
||||||
const { userId } = settings
|
const { userId } = settings
|
||||||
const [title, setTitle] = useState('')
|
|
||||||
const [alertText, setAlertText] = useState('')
|
|
||||||
const [numberOfPeers, setNumberOfPeers] = useState(1)
|
|
||||||
|
|
||||||
const showAlert = useCallback<
|
|
||||||
(message: string, options?: AlertOptions) => void
|
|
||||||
>((message, options) => {
|
|
||||||
setAlertText(message)
|
|
||||||
setAlertSeverity(options?.severity ?? 'info')
|
|
||||||
setIsAlertShowing(true)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const shellContextValue = useMemo(
|
|
||||||
() => ({ numberOfPeers, setNumberOfPeers, setTitle, showAlert }),
|
|
||||||
[numberOfPeers, setNumberOfPeers, setTitle, showAlert]
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleAlertClose = (
|
|
||||||
_event?: SyntheticEvent | Event,
|
|
||||||
reason?: string
|
|
||||||
) => {
|
|
||||||
if (reason === 'clickaway') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsAlertShowing(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
@ -99,63 +47,22 @@ function Bootstrap({
|
|||||||
})()
|
})()
|
||||||
}, [hasLoadedSettings, persistedStorage, settings, userId])
|
}, [hasLoadedSettings, persistedStorage, settings, userId])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.title = title
|
|
||||||
}, [title])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShellContext.Provider value={shellContextValue}>
|
<Shell>
|
||||||
<Box
|
{hasLoadedSettings ? (
|
||||||
className="Chitchatter"
|
<Routes>
|
||||||
sx={{
|
{['/', '/index.html'].map(path => (
|
||||||
height: '100vh',
|
<Route key={path} path={path} element={<Home />} />
|
||||||
display: 'flex',
|
))}
|
||||||
flexDirection: 'column',
|
<Route
|
||||||
paddingTop: 8,
|
path="/public/:roomId"
|
||||||
}}
|
element={<PublicRoom userId={userId} />}
|
||||||
>
|
/>
|
||||||
<Snackbar
|
</Routes>
|
||||||
open={isAlertShowing}
|
) : (
|
||||||
autoHideDuration={6000}
|
<></>
|
||||||
onClose={handleAlertClose}
|
)}
|
||||||
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
</Shell>
|
||||||
>
|
|
||||||
<Alert
|
|
||||||
onClose={handleAlertClose}
|
|
||||||
severity={alertSeverity}
|
|
||||||
variant="standard"
|
|
||||||
>
|
|
||||||
{alertText}
|
|
||||||
</Alert>
|
|
||||||
</Snackbar>
|
|
||||||
<AppBar position="fixed">
|
|
||||||
<Toolbar
|
|
||||||
variant="regular"
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="h6">{title}</Typography>
|
|
||||||
<Tooltip title="Number of peers in the room">
|
|
||||||
<StepIcon icon={numberOfPeers} sx={{ marginLeft: 'auto' }} />
|
|
||||||
</Tooltip>
|
|
||||||
</Toolbar>
|
|
||||||
</AppBar>
|
|
||||||
{hasLoadedSettings ? (
|
|
||||||
<Routes>
|
|
||||||
{['/', '/index.html'].map(path => (
|
|
||||||
<Route key={path} path={path} element={<Home />} />
|
|
||||||
))}
|
|
||||||
<Route
|
|
||||||
path="/public/:roomId"
|
|
||||||
element={<PublicRoom userId={userId} />}
|
|
||||||
/>
|
|
||||||
</Routes>
|
|
||||||
) : null}
|
|
||||||
</Box>
|
|
||||||
</ShellContext.Provider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
110
src/components/Shell/Shell.tsx
Normal file
110
src/components/Shell/Shell.tsx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import {
|
||||||
|
forwardRef,
|
||||||
|
PropsWithChildren,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
SyntheticEvent,
|
||||||
|
} from 'react'
|
||||||
|
import AppBar from '@mui/material/AppBar'
|
||||||
|
import Toolbar from '@mui/material/Toolbar'
|
||||||
|
import Box from '@mui/material/Box'
|
||||||
|
import Typography from '@mui/material/Typography'
|
||||||
|
import StepIcon from '@mui/material/StepIcon'
|
||||||
|
import Tooltip from '@mui/material/Tooltip'
|
||||||
|
import Snackbar from '@mui/material/Snackbar'
|
||||||
|
import MuiAlert, { AlertProps, AlertColor } from '@mui/material/Alert'
|
||||||
|
|
||||||
|
import { ShellContext } from 'ShellContext'
|
||||||
|
import { AlertOptions } from 'models/shell'
|
||||||
|
|
||||||
|
interface ShellProps extends PropsWithChildren {}
|
||||||
|
|
||||||
|
const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(
|
||||||
|
props,
|
||||||
|
ref
|
||||||
|
) {
|
||||||
|
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />
|
||||||
|
})
|
||||||
|
|
||||||
|
export const Shell = ({ children }: ShellProps) => {
|
||||||
|
const [isAlertShowing, setIsAlertShowing] = useState(false)
|
||||||
|
const [alertSeverity, setAlertSeverity] = useState<AlertColor>('info')
|
||||||
|
const [title, setTitle] = useState('')
|
||||||
|
const [alertText, setAlertText] = useState('')
|
||||||
|
const [numberOfPeers, setNumberOfPeers] = useState(1)
|
||||||
|
|
||||||
|
const showAlert = useCallback<
|
||||||
|
(message: string, options?: AlertOptions) => void
|
||||||
|
>((message, options) => {
|
||||||
|
setAlertText(message)
|
||||||
|
setAlertSeverity(options?.severity ?? 'info')
|
||||||
|
setIsAlertShowing(true)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const shellContextValue = useMemo(
|
||||||
|
() => ({ numberOfPeers, setNumberOfPeers, setTitle, showAlert }),
|
||||||
|
[numberOfPeers, setNumberOfPeers, setTitle, showAlert]
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleAlertClose = (
|
||||||
|
_event?: SyntheticEvent | Event,
|
||||||
|
reason?: string
|
||||||
|
) => {
|
||||||
|
if (reason === 'clickaway') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsAlertShowing(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.title = title
|
||||||
|
}, [title])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ShellContext.Provider value={shellContextValue}>
|
||||||
|
<Box
|
||||||
|
className="Chitchatter"
|
||||||
|
sx={{
|
||||||
|
height: '100vh',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
paddingTop: 8,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Snackbar
|
||||||
|
open={isAlertShowing}
|
||||||
|
autoHideDuration={6000}
|
||||||
|
onClose={handleAlertClose}
|
||||||
|
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
||||||
|
>
|
||||||
|
<Alert
|
||||||
|
onClose={handleAlertClose}
|
||||||
|
severity={alertSeverity}
|
||||||
|
variant="standard"
|
||||||
|
>
|
||||||
|
{alertText}
|
||||||
|
</Alert>
|
||||||
|
</Snackbar>
|
||||||
|
<AppBar position="fixed">
|
||||||
|
<Toolbar
|
||||||
|
variant="regular"
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6">{title}</Typography>
|
||||||
|
<Tooltip title="Number of peers in the room">
|
||||||
|
<StepIcon icon={numberOfPeers} sx={{ marginLeft: 'auto' }} />
|
||||||
|
</Tooltip>
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
{children}
|
||||||
|
</Box>
|
||||||
|
</ShellContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
1
src/components/Shell/index.ts
Normal file
1
src/components/Shell/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './Shell'
|
Loading…
x
Reference in New Issue
Block a user