diff options
Diffstat (limited to 'subprojects/frontend/src')
-rw-r--r-- | subprojects/frontend/src/TopBar.tsx | 58 | ||||
-rw-r--r-- | subprojects/frontend/src/WindowControlsOverlayColor.tsx | 21 | ||||
-rw-r--r-- | subprojects/frontend/src/index.tsx | 2 |
3 files changed, 79 insertions, 2 deletions
diff --git a/subprojects/frontend/src/TopBar.tsx b/subprojects/frontend/src/TopBar.tsx index 5ad80d40..4424e6b3 100644 --- a/subprojects/frontend/src/TopBar.tsx +++ b/subprojects/frontend/src/TopBar.tsx | |||
@@ -1,11 +1,47 @@ | |||
1 | import AppBar from '@mui/material/AppBar'; | 1 | import AppBar from '@mui/material/AppBar'; |
2 | import Toolbar from '@mui/material/Toolbar'; | 2 | import Toolbar from '@mui/material/Toolbar'; |
3 | import Typography from '@mui/material/Typography'; | 3 | import Typography from '@mui/material/Typography'; |
4 | import React from 'react'; | 4 | import { throttle } from 'lodash-es'; |
5 | import React, { useEffect, useMemo, useState } from 'react'; | ||
5 | 6 | ||
6 | import ToggleDarkModeButton from './ToggleDarkModeButton'; | 7 | import ToggleDarkModeButton from './ToggleDarkModeButton'; |
7 | 8 | ||
9 | function useWindowControlsOverlayVisible(): boolean { | ||
10 | const [windowControlsOverlayVisible, setWindowControlsOverlayVisible] = | ||
11 | useState(false); | ||
12 | const updateWindowControlsOverlayVisible = useMemo( | ||
13 | () => | ||
14 | throttle( | ||
15 | ({ visible }: WindowControlsOverlayGeometryChangeEvent) => | ||
16 | setWindowControlsOverlayVisible(visible), | ||
17 | 250, | ||
18 | ), | ||
19 | [], | ||
20 | ); | ||
21 | useEffect(() => { | ||
22 | if ('windowControlsOverlay' in navigator) { | ||
23 | const { windowControlsOverlay } = navigator; | ||
24 | setWindowControlsOverlayVisible(windowControlsOverlay.visible); | ||
25 | windowControlsOverlay.addEventListener( | ||
26 | 'geometrychange', | ||
27 | updateWindowControlsOverlayVisible, | ||
28 | ); | ||
29 | return () => { | ||
30 | windowControlsOverlay.removeEventListener( | ||
31 | 'geometrychange', | ||
32 | updateWindowControlsOverlayVisible, | ||
33 | ); | ||
34 | }; | ||
35 | } | ||
36 | // Nothing to clean up if `windowControlsOverlay` is unsupported. | ||
37 | return () => {}; | ||
38 | }, [updateWindowControlsOverlayVisible]); | ||
39 | return windowControlsOverlayVisible; | ||
40 | } | ||
41 | |||
8 | export default function TopBar(): JSX.Element { | 42 | export default function TopBar(): JSX.Element { |
43 | const overlayVisible = useWindowControlsOverlayVisible(); | ||
44 | |||
9 | return ( | 45 | return ( |
10 | <AppBar | 46 | <AppBar |
11 | position="static" | 47 | position="static" |
@@ -14,9 +50,27 @@ export default function TopBar(): JSX.Element { | |||
14 | sx={(theme) => ({ | 50 | sx={(theme) => ({ |
15 | background: theme.palette.outer.background, | 51 | background: theme.palette.outer.background, |
16 | borderBottom: `1px solid ${theme.palette.outer.border}`, | 52 | borderBottom: `1px solid ${theme.palette.outer.border}`, |
53 | appRegion: 'drag', | ||
54 | '.MuiButtonBase-root': { | ||
55 | appRegion: 'no-drag', | ||
56 | }, | ||
17 | })} | 57 | })} |
18 | > | 58 | > |
19 | <Toolbar> | 59 | <Toolbar |
60 | sx={{ | ||
61 | ...(overlayVisible | ||
62 | ? { | ||
63 | marginLeft: 'env(titlebar-area-x, 0)', | ||
64 | marginTop: 'env(titlebar-area-y, 0)', | ||
65 | width: 'env(titlebar-area-width, 100%)', | ||
66 | minHeight: 'env(titlebar-area-height, auto)', | ||
67 | } | ||
68 | : { | ||
69 | minHeight: 'auto', | ||
70 | }), | ||
71 | py: 0.5, | ||
72 | }} | ||
73 | > | ||
20 | <Typography variant="h6" component="h1" flexGrow={1}> | 74 | <Typography variant="h6" component="h1" flexGrow={1}> |
21 | Refinery | 75 | Refinery |
22 | </Typography> | 76 | </Typography> |
diff --git a/subprojects/frontend/src/WindowControlsOverlayColor.tsx b/subprojects/frontend/src/WindowControlsOverlayColor.tsx new file mode 100644 index 00000000..14eda566 --- /dev/null +++ b/subprojects/frontend/src/WindowControlsOverlayColor.tsx | |||
@@ -0,0 +1,21 @@ | |||
1 | import { useTheme } from '@mui/material/styles'; | ||
2 | import { useEffect } from 'react'; | ||
3 | |||
4 | export default function WindowControlsOverlayColor(): null { | ||
5 | const { | ||
6 | palette: { | ||
7 | outer: { background }, | ||
8 | }, | ||
9 | } = useTheme(); | ||
10 | useEffect(() => { | ||
11 | document.head | ||
12 | .querySelectorAll('meta[name="theme-color"]') | ||
13 | .forEach((meta) => meta.remove()); | ||
14 | const meta = document.createElement('meta'); | ||
15 | meta.name = 'theme-color'; | ||
16 | meta.content = background; | ||
17 | document.head.appendChild(meta); | ||
18 | }, [background]); | ||
19 | |||
20 | return null; | ||
21 | } | ||
diff --git a/subprojects/frontend/src/index.tsx b/subprojects/frontend/src/index.tsx index a65821ef..460f6f77 100644 --- a/subprojects/frontend/src/index.tsx +++ b/subprojects/frontend/src/index.tsx | |||
@@ -6,6 +6,7 @@ import { createRoot } from 'react-dom/client'; | |||
6 | import Loading from './Loading'; | 6 | import Loading from './Loading'; |
7 | import RegisterServiceWorker from './RegisterServiceWorker'; | 7 | import RegisterServiceWorker from './RegisterServiceWorker'; |
8 | import RootStore, { RootStoreProvider } from './RootStore'; | 8 | import RootStore, { RootStoreProvider } from './RootStore'; |
9 | import WindowControlsOverlayColor from './WindowControlsOverlayColor'; | ||
9 | import ThemeProvider from './theme/ThemeProvider'; | 10 | import ThemeProvider from './theme/ThemeProvider'; |
10 | import getLogger from './utils/getLogger'; | 11 | import getLogger from './utils/getLogger'; |
11 | 12 | ||
@@ -67,6 +68,7 @@ const app = ( | |||
67 | <RootStoreProvider rootStore={rootStore}> | 68 | <RootStoreProvider rootStore={rootStore}> |
68 | <ThemeProvider> | 69 | <ThemeProvider> |
69 | <CssBaseline enableColorScheme /> | 70 | <CssBaseline enableColorScheme /> |
71 | <WindowControlsOverlayColor /> | ||
70 | <SnackbarProvider> | 72 | <SnackbarProvider> |
71 | <RegisterServiceWorker /> | 73 | <RegisterServiceWorker /> |
72 | <Suspense fallback={<Loading />}> | 74 | <Suspense fallback={<Loading />}> |