From 8ebc24a5ba1c87cb5cb14fbaff3bee329e30fc15 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sun, 21 Aug 2022 00:33:01 +0200 Subject: feat(frontend): overlay window controls Might need manual intervention in browsers, e.g. https://docs.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/window-controls-overlay#enable-the-window-controls-overlay-api-in-microsoft-edge --- subprojects/frontend/package.json | 2 + subprojects/frontend/src/TopBar.tsx | 58 +++++++++++++++++++++- .../frontend/src/WindowControlsOverlayColor.tsx | 21 ++++++++ subprojects/frontend/src/index.tsx | 2 + .../frontend/types/windowControlsOverlay.d.ts | 32 ++++++++++++ subprojects/frontend/vite.config.ts | 2 + 6 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 subprojects/frontend/src/WindowControlsOverlayColor.tsx create mode 100644 subprojects/frontend/types/windowControlsOverlay.d.ts (limited to 'subprojects/frontend') diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json index aa453cd0..448b9710 100644 --- a/subprojects/frontend/package.json +++ b/subprojects/frontend/package.json @@ -40,8 +40,10 @@ "@material-icons/svg": "^1.0.32", "@mui/icons-material": "5.8.4", "@mui/material": "5.10.1", + "@types/lodash-es": "^4.17.6", "ansi-styles": "^6.1.0", "escape-string-regexp": "^5.0.0", + "lodash-es": "^4.17.21", "loglevel": "^1.8.0", "loglevel-plugin-prefix": "^0.8.4", "mobx": "^6.6.1", 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 @@ import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; -import React from 'react'; +import { throttle } from 'lodash-es'; +import React, { useEffect, useMemo, useState } from 'react'; import ToggleDarkModeButton from './ToggleDarkModeButton'; +function useWindowControlsOverlayVisible(): boolean { + const [windowControlsOverlayVisible, setWindowControlsOverlayVisible] = + useState(false); + const updateWindowControlsOverlayVisible = useMemo( + () => + throttle( + ({ visible }: WindowControlsOverlayGeometryChangeEvent) => + setWindowControlsOverlayVisible(visible), + 250, + ), + [], + ); + useEffect(() => { + if ('windowControlsOverlay' in navigator) { + const { windowControlsOverlay } = navigator; + setWindowControlsOverlayVisible(windowControlsOverlay.visible); + windowControlsOverlay.addEventListener( + 'geometrychange', + updateWindowControlsOverlayVisible, + ); + return () => { + windowControlsOverlay.removeEventListener( + 'geometrychange', + updateWindowControlsOverlayVisible, + ); + }; + } + // Nothing to clean up if `windowControlsOverlay` is unsupported. + return () => {}; + }, [updateWindowControlsOverlayVisible]); + return windowControlsOverlayVisible; +} + export default function TopBar(): JSX.Element { + const overlayVisible = useWindowControlsOverlayVisible(); + return ( ({ background: theme.palette.outer.background, borderBottom: `1px solid ${theme.palette.outer.border}`, + appRegion: 'drag', + '.MuiButtonBase-root': { + appRegion: 'no-drag', + }, })} > - + Refinery 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 @@ +import { useTheme } from '@mui/material/styles'; +import { useEffect } from 'react'; + +export default function WindowControlsOverlayColor(): null { + const { + palette: { + outer: { background }, + }, + } = useTheme(); + useEffect(() => { + document.head + .querySelectorAll('meta[name="theme-color"]') + .forEach((meta) => meta.remove()); + const meta = document.createElement('meta'); + meta.name = 'theme-color'; + meta.content = background; + document.head.appendChild(meta); + }, [background]); + + return null; +} 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'; import Loading from './Loading'; import RegisterServiceWorker from './RegisterServiceWorker'; import RootStore, { RootStoreProvider } from './RootStore'; +import WindowControlsOverlayColor from './WindowControlsOverlayColor'; import ThemeProvider from './theme/ThemeProvider'; import getLogger from './utils/getLogger'; @@ -67,6 +68,7 @@ const app = ( + }> diff --git a/subprojects/frontend/types/windowControlsOverlay.d.ts b/subprojects/frontend/types/windowControlsOverlay.d.ts new file mode 100644 index 00000000..d8f3182f --- /dev/null +++ b/subprojects/frontend/types/windowControlsOverlay.d.ts @@ -0,0 +1,32 @@ +interface WindowControlsOverlayGeometryChangeEvent extends Event { + titlebarAreaRect: DOMRect; + + visible: boolean; +} + +interface WindowControlsOverlay { + readonly visible: boolean; + + getTitlebarAreaRect(): DOMRect; + + addEventListener( + type: 'geometrychange', + listener: ( + this: WindowControlsOverlay, + event: WindowControlsOverlayGeometryChangeEvent, + ) => unknown, + options?: boolean | AddEventListenerOptions, + ); + + removeEventListener( + type: 'geometrychange', + listener: ( + this: WindowControlsOverlay, + event: WindowControlsOverlayGeometryChangeEvent, + ) => unknown, + ); +} + +interface Navigator { + windowControlsOverlay?: WindowControlsOverlay; +} diff --git a/subprojects/frontend/vite.config.ts b/subprojects/frontend/vite.config.ts index 6ec2d513..f2e0f15c 100644 --- a/subprojects/frontend/vite.config.ts +++ b/subprojects/frontend/vite.config.ts @@ -111,6 +111,8 @@ export default defineConfig({ description: 'An efficient graph sovler for generating well-formed models', theme_color: '#21252b', + display_override: ['window-controls-overlay'], + display: 'standalone', background_color: '#21252b', icons: [ { -- cgit v1.2.3-54-g00ecf