diff --git a/web/package-lock.json b/web/package-lock.json index ab6144ec1..1ba3fac94 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1721,6 +1721,11 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.9.tgz", "integrity": "sha512-X4m+4VMVINl/JFQKALOCwa3p8vhMAhBvle0hJ/W44w/WWfNb2TA7RNicDV3K2dNVs57f61GviEnVLiwN+fxiIg==" }, + "preact-async-route": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/preact-async-route/-/preact-async-route-2.2.1.tgz", + "integrity": "sha512-8bg1007akXs3YDmzYT4McaTe6ji2FIzcc0/NTlu+vjJaKPNQ8lNG/HQ6LP+FoIxQ4m/KH5vvJCHJN5ADp2iNGA==" + }, "preact-router": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-3.2.1.tgz", diff --git a/web/package.json b/web/package.json index cf5569bcd..9bc642727 100644 --- a/web/package.json +++ b/web/package.json @@ -16,6 +16,7 @@ "postcss": "^8.2.2", "postcss-cli": "^8.3.1", "preact": "^10.5.9", + "preact-async-route": "^2.2.1", "preact-router": "^3.2.1", "rimraf": "^3.0.2", "snowpack": "^3.0.11", diff --git a/web/src/App.jsx b/web/src/App.jsx index 198bc7411..3f943181b 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -1,15 +1,11 @@ +import * as Routes from './routes'; import { h } from 'preact'; import ActivityIndicator from './components/ActivityIndicator'; +import AsyncRoute from 'preact-async-route'; import AppBar from './components/AppBar'; -import Camera from './Camera'; -import CameraMap from './CameraMap'; -import Cameras from './Cameras'; -import Debug from './Debug'; -import Event from './Event'; -import Events from './Events'; +import Cameras from './routes/Cameras'; import { Router } from 'preact-router'; import Sidebar from './Sidebar'; -import StyleGuide from './StyleGuide'; import Api, { FetchStatus, useConfig } from './api'; import { DarkModeProvider, DrawerProvider } from './context'; @@ -29,12 +25,12 @@ export default function App() {
- - - - - - {import.meta.env.NODE_ENV !== 'development' ? : null} + + + + + +
diff --git a/web/src/Settings.jsx b/web/src/Settings.jsx deleted file mode 100644 index ef47a55aa..000000000 --- a/web/src/Settings.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import { h } from 'preact'; -import { useDarkMode } from './context'; -import { useCallback } from 'preact/hooks'; - -export default function Settings() { - const { currentMode, persistedMode, setDarkMode } = useDarkMode(); - - const handleSelect = useCallback( - (event) => { - const mode = event.target.value; - setDarkMode(mode); - }, - [setDarkMode] - ); - - return ( -
- -
- ); -} diff --git a/web/src/Sidebar.jsx b/web/src/Sidebar.jsx index a1d58385d..decc709ff 100644 --- a/web/src/Sidebar.jsx +++ b/web/src/Sidebar.jsx @@ -30,6 +30,12 @@ export default function Sidebar() {
+ {import.meta.env.MODE !== 'production' ? ( + + + + + ) : null} diff --git a/web/src/components/CameraImage.jsx b/web/src/components/CameraImage.jsx index b1634c95d..d5cf6a65d 100644 --- a/web/src/components/CameraImage.jsx +++ b/web/src/components/CameraImage.jsx @@ -50,7 +50,7 @@ export default function CameraImage({ camera, onload, searchParams = '' }) { ); useEffect(() => { - if (!scaledHeight) { + if (!scaledHeight || !canvasRef.current) { return; } img.src = `${apiHost}/api/${name}/latest.jpg?h=${scaledHeight}${searchParams ? `&${searchParams}` : ''}`; diff --git a/web/src/Camera.jsx b/web/src/routes/Camera.jsx similarity index 89% rename from web/src/Camera.jsx rename to web/src/routes/Camera.jsx index a586e8a21..42429d670 100644 --- a/web/src/Camera.jsx +++ b/web/src/routes/Camera.jsx @@ -1,15 +1,15 @@ import { h } from 'preact'; -import AutoUpdatingCameraImage from './components/AutoUpdatingCameraImage'; -import Button from './components/Button'; -import Card from './components/Card'; -import Heading from './components/Heading'; -import Link from './components/Link'; -import SettingsIcon from './icons/Settings'; -import Switch from './components/Switch'; +import AutoUpdatingCameraImage from '../components/AutoUpdatingCameraImage'; +import Button from '../components/Button'; +import Card from '../components/Card'; +import Heading from '../components/Heading'; +import Link from '../components/Link'; +import SettingsIcon from '../icons/Settings'; +import Switch from '../components/Switch'; import { route } from 'preact-router'; -import { usePersistence } from './context'; +import { usePersistence } from '../context'; import { useCallback, useContext, useMemo, useState } from 'preact/hooks'; -import { useApiHost, useConfig } from './api'; +import { useApiHost, useConfig } from '../api'; export default function Camera({ camera }) { const { data: config } = useConfig(); diff --git a/web/src/CameraMap.jsx b/web/src/routes/CameraMap.jsx similarity index 99% rename from web/src/CameraMap.jsx rename to web/src/routes/CameraMap.jsx index c267a6c57..344606a59 100644 --- a/web/src/CameraMap.jsx +++ b/web/src/routes/CameraMap.jsx @@ -1,8 +1,8 @@ import { h } from 'preact'; -import Card from './components/Card'; -import Button from './components/Button'; -import Heading from './components/Heading'; -import Switch from './components/Switch'; +import Card from '../components/Card'; +import Button from '../components/Button'; +import Heading from '../components/Heading'; +import Switch from '../components/Switch'; import { route } from 'preact-router'; import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'preact/hooks'; import { useApiHost, useConfig } from './api'; diff --git a/web/src/Cameras.jsx b/web/src/routes/Cameras.jsx similarity index 72% rename from web/src/Cameras.jsx rename to web/src/routes/Cameras.jsx index 91f7e4d70..70ca74a8f 100644 --- a/web/src/Cameras.jsx +++ b/web/src/routes/Cameras.jsx @@ -1,11 +1,10 @@ import { h } from 'preact'; -import ActivityIndicator from './components/ActivityIndicator'; -import Card from './components/Card'; -import CameraImage from './components/CameraImage'; -import Events from './Events'; -import Heading from './components/Heading'; +import ActivityIndicator from '../components/ActivityIndicator'; +import Card from '../components/Card'; +import CameraImage from '../components/CameraImage'; +import Heading from '../components/Heading'; import { route } from 'preact-router'; -import { useConfig } from './api'; +import { useConfig } from '../api'; import { useMemo } from 'preact/hooks'; export default function Cameras() { diff --git a/web/src/Debug.jsx b/web/src/routes/Debug.jsx similarity index 90% rename from web/src/Debug.jsx rename to web/src/routes/Debug.jsx index 6d164f3fb..5eaa0b544 100644 --- a/web/src/Debug.jsx +++ b/web/src/routes/Debug.jsx @@ -1,10 +1,10 @@ import { h } from 'preact'; -import ActivityIndicator from './components/ActivityIndicator'; -import Button from './components/Button'; -import Heading from './components/Heading'; -import Link from './components/Link'; -import { FetchStatus, useConfig, useStats } from './api'; -import { Table, Tbody, Thead, Tr, Th, Td } from './components/Table'; +import ActivityIndicator from '../components/ActivityIndicator'; +import Button from '../components/Button'; +import Heading from '../components/Heading'; +import Link from '../components/Link'; +import { FetchStatus, useConfig, useStats } from '../api'; +import { Table, Tbody, Thead, Tr, Th, Td } from '../components/Table'; import { useCallback, useEffect, useState } from 'preact/hooks'; export default function Debug() { diff --git a/web/src/Event.jsx b/web/src/routes/Event.jsx similarity index 86% rename from web/src/Event.jsx rename to web/src/routes/Event.jsx index 142284d6f..704ba20a6 100644 --- a/web/src/Event.jsx +++ b/web/src/routes/Event.jsx @@ -1,9 +1,9 @@ import { h, Fragment } from 'preact'; -import ActivityIndicator from './components/ActivityIndicator'; -import Heading from './components/Heading'; -import Link from './components/Link'; -import { FetchStatus, useApiHost, useEvent } from './api'; -import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from './components/Table'; +import ActivityIndicator from '../components/ActivityIndicator'; +import Heading from '../components/Heading'; +import Link from '../components/Link'; +import { FetchStatus, useApiHost, useEvent } from '../api'; +import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from '../components/Table'; export default function Event({ eventId }) { const apiHost = useApiHost(); diff --git a/web/src/Events.jsx b/web/src/routes/Events.jsx similarity index 96% rename from web/src/Events.jsx rename to web/src/routes/Events.jsx index e145889c5..29f258ad0 100644 --- a/web/src/Events.jsx +++ b/web/src/routes/Events.jsx @@ -1,13 +1,13 @@ import { h } from 'preact'; -import ActivityIndicator from './components/ActivityIndicator'; -import Card from './components/Card'; -import Heading from './components/Heading'; -import Link from './components/Link'; -import Select from './components/Select'; +import ActivityIndicator from '../components/ActivityIndicator'; +import Card from '../components/Card'; +import Heading from '../components/Heading'; +import Link from '../components/Link'; +import Select from '../components/Select'; import produce from 'immer'; import { route } from 'preact-router'; -import { FetchStatus, useApiHost, useConfig, useEvents } from './api'; -import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from './components/Table'; +import { FetchStatus, useApiHost, useConfig, useEvents } from '../api'; +import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from '../components/Table'; import { useCallback, useContext, useEffect, useMemo, useRef, useReducer, useState } from 'preact/hooks'; const API_LIMIT = 25; diff --git a/web/src/StyleGuide.jsx b/web/src/routes/StyleGuide.jsx similarity index 87% rename from web/src/StyleGuide.jsx rename to web/src/routes/StyleGuide.jsx index 8f2235ef4..32f51a2fa 100644 --- a/web/src/StyleGuide.jsx +++ b/web/src/routes/StyleGuide.jsx @@ -1,12 +1,12 @@ import { h } from 'preact'; -import ArrowDropdown from './icons/ArrowDropdown'; -import ArrowDropup from './icons/ArrowDropup'; -import Card from './components/Card'; -import Button from './components/Button'; -import Heading from './components/Heading'; -import Select from './components/Select'; -import Switch from './components/Switch'; -import TextField from './components/TextField'; +import ArrowDropdown from '../icons/ArrowDropdown'; +import ArrowDropup from '../icons/ArrowDropup'; +import Card from '../components/Card'; +import Button from '../components/Button'; +import Heading from '../components/Heading'; +import Select from '../components/Select'; +import Switch from '../components/Switch'; +import TextField from '../components/TextField'; import { useCallback, useState } from 'preact/hooks'; export default function StyleGuide() { diff --git a/web/src/routes/index.js b/web/src/routes/index.js new file mode 100644 index 000000000..1fdabe1ac --- /dev/null +++ b/web/src/routes/index.js @@ -0,0 +1,29 @@ +export async function getCameraMap(url, cb, props) { + const module = await import('./CameraMap.jsx'); + return module.default; +} + +export async function getCamera(url, cb, props) { + const module = await import('./Camera.jsx'); + return module.default; +} + +export async function getEvent(url, cb, props) { + const module = await import('./Event.jsx'); + return module.default; +} + +export async function getEvents(url, cb, props) { + const module = await import('./Events.jsx'); + return module.default; +} + +export async function getDebug(url, cb, props) { + const module = await import('./Debug.jsx'); + return module.default; +} + +export async function getStyleGuide(url, cb, props) { + const module = await import('./StyleGuide.jsx'); + return module.default; +}