remnantchat/src/Bootstrap.tsx

125 lines
3.6 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from 'react'
2022-09-01 03:05:24 +00:00
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
2022-08-20 19:20:51 +00:00
import { v4 as uuid } from 'uuid'
2022-08-20 21:52:31 +00:00
import localforage from 'localforage'
2022-08-10 02:28:46 +00:00
2022-09-11 18:44:23 +00:00
import * as serviceWorkerRegistration from 'serviceWorkerRegistration'
import { StorageContext } from 'contexts/StorageContext'
2022-09-05 22:35:40 +00:00
import { SettingsContext } from 'contexts/SettingsContext'
2022-09-20 19:22:39 +00:00
import { routes } from 'config/routes'
2022-09-17 17:39:16 +00:00
import { Home } from 'pages/Home'
import { About } from 'pages/About'
import { Settings } from 'pages/Settings'
2022-09-17 17:39:16 +00:00
import { PublicRoom } from 'pages/PublicRoom'
2022-08-20 21:52:31 +00:00
import { UserSettings } from 'models/settings'
import { PersistedStorageKeys } from 'models/storage'
import { Shell } from 'components/Shell'
2022-08-09 14:35:49 +00:00
2022-08-20 21:52:31 +00:00
export interface BootstrapProps {
persistedStorage?: typeof localforage
getUuid?: typeof uuid
}
function Bootstrap({
persistedStorage: persistedStorageProp = localforage.createInstance({
2022-08-20 21:52:31 +00:00
name: 'chitchatter',
description: 'Persisted settings data for chitchatter',
}),
getUuid = uuid,
}: BootstrapProps) {
const [persistedStorage] = useState(persistedStorageProp)
2022-09-11 18:44:23 +00:00
const [appNeedsUpdate, setAppNeedsUpdate] = useState(false)
2022-08-20 21:52:31 +00:00
const [hasLoadedSettings, setHasLoadedSettings] = useState(false)
2022-09-05 22:35:40 +00:00
const [userSettings, setUserSettings] = useState<UserSettings>({
userId: getUuid(),
colorMode: 'dark',
})
const { userId } = userSettings
2022-09-11 18:44:23 +00:00
const handleServiceWorkerUpdate = () => {
setAppNeedsUpdate(true)
}
useEffect(() => {
serviceWorkerRegistration.register({ onUpdate: handleServiceWorkerUpdate })
}, [])
2022-08-20 21:52:31 +00:00
useEffect(() => {
;(async () => {
if (hasLoadedSettings) return
const persistedUserSettings =
await persistedStorageProp.getItem<UserSettings>(
2022-08-20 21:52:31 +00:00
PersistedStorageKeys.USER_SETTINGS
)
if (persistedUserSettings) {
2022-09-05 22:35:40 +00:00
setUserSettings(persistedUserSettings)
2022-08-20 21:52:31 +00:00
} else {
await persistedStorageProp.setItem(
2022-08-20 21:52:31 +00:00
PersistedStorageKeys.USER_SETTINGS,
2022-09-05 22:35:40 +00:00
userSettings
2022-08-20 21:52:31 +00:00
)
}
setHasLoadedSettings(true)
})()
}, [hasLoadedSettings, persistedStorageProp, userSettings, userId])
2022-09-05 22:35:40 +00:00
const settingsContextValue = {
updateUserSettings: async (changedSettings: Partial<UserSettings>) => {
const newSettings = {
...userSettings,
...changedSettings,
}
await persistedStorageProp.setItem(
2022-09-05 22:35:40 +00:00
PersistedStorageKeys.USER_SETTINGS,
newSettings
)
setUserSettings(newSettings)
},
getUserSettings: () => ({ ...userSettings }),
}
2022-08-20 19:20:51 +00:00
const storageContextValue = {
getPersistedStorage: () => persistedStorage,
}
2022-08-10 02:28:46 +00:00
return (
2022-09-01 03:05:24 +00:00
<Router>
<StorageContext.Provider value={storageContextValue}>
<SettingsContext.Provider value={settingsContextValue}>
<Shell appNeedsUpdate={appNeedsUpdate} userPeerId={userId}>
{hasLoadedSettings ? (
<Routes>
{[routes.ROOT, routes.INDEX_HTML].map(path => (
<Route
key={path}
path={path}
element={<Home userId={userId} />}
/>
))}
<Route path={routes.ABOUT} element={<About />} />
<Route
path={routes.SETTINGS}
element={<Settings userId={userId} />}
/>
2022-09-05 23:59:59 +00:00
<Route
path={routes.PUBLIC_ROOM}
element={<PublicRoom userId={userId} />}
2022-09-05 23:59:59 +00:00
/>
</Routes>
) : (
<></>
)}
</Shell>
</SettingsContext.Provider>
</StorageContext.Provider>
2022-09-01 03:05:24 +00:00
</Router>
2022-08-10 02:28:46 +00:00
)
2022-08-09 14:35:49 +00:00
}
export default Bootstrap