import { PropsWithChildren, SyntheticEvent, forwardRef, useCallback, useContext, useEffect, useMemo, useState, } from 'react' import { Link } from 'react-router-dom' import CssBaseline from '@mui/material/CssBaseline' import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar' import { ThemeProvider, createTheme, styled } from '@mui/material/styles' import Drawer from '@mui/material/Drawer' import Toolbar from '@mui/material/Toolbar' import Box from '@mui/material/Box' import List from '@mui/material/List' import Typography from '@mui/material/Typography' import Divider from '@mui/material/Divider' 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 IconButton from '@mui/material/IconButton' import Button from '@mui/material/Button' import Dialog from '@mui/material/Dialog' import DialogActions from '@mui/material/DialogActions' import DialogContent from '@mui/material/DialogContent' import DialogContentText from '@mui/material/DialogContentText' import DialogTitle from '@mui/material/DialogTitle' import MenuIcon from '@mui/icons-material/Menu' import WarningIcon from '@mui/icons-material/Warning' import ChevronLeftIcon from '@mui/icons-material/ChevronLeft' import ChevronRightIcon from '@mui/icons-material/ChevronRight' import ListItem from '@mui/material/ListItem' import ListItemButton from '@mui/material/ListItemButton' import ListItemIcon from '@mui/material/ListItemIcon' import ListItemText from '@mui/material/ListItemText' import Home from '@mui/icons-material/Home' import Brightness4Icon from '@mui/icons-material/Brightness4' import Brightness7Icon from '@mui/icons-material/Brightness7' import LinkIcon from '@mui/icons-material/Link' import { ShellContext } from 'contexts/ShellContext' import { SettingsContext } from 'contexts/SettingsContext' import { AlertOptions } from 'models/shell' import { PeerNameDisplay } from 'components/PeerNameDisplay' const drawerWidth = 240 const Alert = forwardRef(function Alert( props, ref ) { return }) const Main = styled('main', { shouldForwardProp: prop => prop !== 'open' })<{ open?: boolean }>(({ theme, open }) => ({ transition: theme.transitions.create('margin', { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, }), marginLeft: `-${drawerWidth}px`, ...(open && { transition: theme.transitions.create('margin', { easing: theme.transitions.easing.easeOut, duration: theme.transitions.duration.enteringScreen, }), marginLeft: 0, }), })) interface AppBarProps extends MuiAppBarProps { open?: boolean } const AppBar = styled(MuiAppBar, { shouldForwardProp: prop => prop !== 'open', })(({ theme, open }) => ({ transition: theme.transitions.create(['margin', 'width'], { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.leavingScreen, }), ...(open && { width: `calc(100% - ${drawerWidth}px)`, marginLeft: `${drawerWidth}px`, transition: theme.transitions.create(['margin', 'width'], { easing: theme.transitions.easing.easeOut, duration: theme.transitions.duration.enteringScreen, }), }), })) const DrawerHeader = styled('div')(({ theme }) => ({ display: 'flex', alignItems: 'center', padding: theme.spacing(0, 1), // necessary for content to be below app bar ...theme.mixins.toolbar, justifyContent: 'flex-end', })) export interface ShellProps extends PropsWithChildren { userPeerId: string appNeedsUpdate: boolean } export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => { const settingsContext = useContext(SettingsContext) const [isAlertShowing, setIsAlertShowing] = useState(false) const [isDrawerOpen, setIsDrawerOpen] = useState(false) const [doShowPeers, setDoShowPeers] = useState(false) const [alertSeverity, setAlertSeverity] = useState('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, setDoShowPeers, setNumberOfPeers, setTitle, showAlert, }), [numberOfPeers, setDoShowPeers, setNumberOfPeers, setTitle, showAlert] ) const colorMode = settingsContext.getUserSettings().colorMode const handleColorModeToggleClick = () => { const newMode = colorMode === 'light' ? 'dark' : 'light' settingsContext.updateUserSettings({ colorMode: newMode }) } const theme = useMemo( () => createTheme({ palette: { mode: colorMode, }, }), [colorMode] ) const handleAlertClose = ( _event?: SyntheticEvent | Event, reason?: string ) => { if (reason === 'clickaway') { return } setIsAlertShowing(false) } useEffect(() => { document.title = title }, [title]) const handleDrawerOpen = () => { setIsDrawerOpen(true) } const handleDrawerClose = () => { setIsDrawerOpen(false) } const handleHomeLinkClick = () => { setIsDrawerOpen(false) } const handleLinkButtonClick = async () => { await navigator.clipboard.writeText(window.location.href) shellContextValue.showAlert('Current URL copied to clipboard', { severity: 'success', }) } const handleRestartClick = () => { window.location.reload() } return ( ({ color: theme.palette.warning.main, mr: theme.spacing(1), })} /> Update needed In order to function properly, Chitchatter needs to be updated. The update has already been installed in the background. All you need to do is reload the page or click "Refresh" below. {alertText} {title} {doShowPeers ? ( ) : null} {theme.direction === 'ltr' ? ( ) : ( )} Your user name:{' '} {userPeerId} } /> {theme.palette.mode === 'dark' ? ( ) : ( )}
{children}
) }