diff --git a/remote_frontend/package-lock.json b/remote_frontend/package-lock.json index 5ec1cd8..aa5da94 100644 --- a/remote_frontend/package-lock.json +++ b/remote_frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@fluentui/react-components": "^9.49.0", + "@fluentui/react-icons": "^2.0.238", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -1415,9 +1416,9 @@ } }, "node_modules/@fluentui/react-icons": { - "version": "2.0.237", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.237.tgz", - "integrity": "sha512-J+6XDB/Y3G3nfNWvKKI6xhUXDN6/xvhksnV+zfXiGb6tqtK7QiihAzvRRgPnKuS3BH/H1TM7k3KC19V0AJrTDg==", + "version": "2.0.238", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-2.0.238.tgz", + "integrity": "sha512-2T87k8lP4k2h98aDY2WlSACa2u0WBll1BQ/0+hsS0ir4uvRLRofLi5rtRUz3i1aOymeKvCoQzW6q1m03Z7JEOw==", "dependencies": { "@griffel/react": "^1.0.0", "tslib": "^2.1.0" diff --git a/remote_frontend/package.json b/remote_frontend/package.json index 5031631..9cd9ed7 100644 --- a/remote_frontend/package.json +++ b/remote_frontend/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@fluentui/react-components": "^9.49.0", + "@fluentui/react-icons": "^2.0.238", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/remote_frontend/src/App.tsx b/remote_frontend/src/App.tsx index 005b232..074c9a3 100644 --- a/remote_frontend/src/App.tsx +++ b/remote_frontend/src/App.tsx @@ -1,19 +1,8 @@ -import { - Menu, - MenuButton, - MenuItem, - MenuList, - MenuPopover, - MenuTrigger, - makeStyles, - typographyStyles, -} from "@fluentui/react-components"; +import { makeStyles, typographyStyles } from "@fluentui/react-components"; import { ServerApi } from "./api/ServerApi"; import { AuthRouteWidget } from "./routes/AuthRouteWidget"; import { AsyncWidget } from "./widgets/AsyncWidget"; -import { AuthApi } from "./api/AuthApi"; -import { useAlert } from "./hooks/providers/AlertDialogProvider"; -import { useConfirm } from "./hooks/providers/ConfirmDialogProvider"; +import { MainMenu } from "./widgets/MainMenu"; const useStyles = makeStyles({ title: typographyStyles.title2, @@ -32,20 +21,8 @@ export function App() { } function AppInner(): React.ReactElement { - const alert = useAlert(); - const confirm = useConfirm(); const styles = useStyles(); - const signOut = async () => { - try { - if (!(await confirm("Do you really want to sign out?"))) return; - await AuthApi.SignOut(); - } catch (e) { - console.error(e); - alert("Failed to perform sign out!"); - } - }; - if (!ServerApi.Config.authenticated && !ServerApi.Config.disable_auth) return ; @@ -59,17 +36,7 @@ function AppInner(): React.ReactElement { >
VirtWebRemote - - - Account - - - - - Sign out - - - +
); diff --git a/remote_frontend/src/hooks/providers/ThemeProvider.tsx b/remote_frontend/src/hooks/providers/ThemeProvider.tsx new file mode 100644 index 0000000..fd419f6 --- /dev/null +++ b/remote_frontend/src/hooks/providers/ThemeProvider.tsx @@ -0,0 +1,55 @@ +import { + FluentProvider, + teamsDarkTheme, + teamsHighContrastTheme, + teamsLightTheme, + webDarkTheme, + webLightTheme, +} from "@fluentui/react-components"; +import React from "react"; + +export type Theme = + | "highcontrast" + | "teamsdark" + | "teamslight" + | "webdark" + | "weblight"; + +type ThemeContext = { theme: Theme; set: (theme: Theme) => void }; + +const ThemeContextK = React.createContext(null); + +export function ThemeProvider(p: React.PropsWithChildren): React.ReactElement { + const [theme, setTheme] = React.useState("highcontrast"); + + let fluentTheme = teamsHighContrastTheme; + switch (theme) { + case "teamsdark": + fluentTheme = teamsDarkTheme; + break; + case "teamslight": + fluentTheme = teamsLightTheme; + break; + case "highcontrast": + fluentTheme = teamsHighContrastTheme; + break; + case "webdark": + fluentTheme = webDarkTheme; + break; + case "weblight": + fluentTheme = webLightTheme; + break; + } + + return ( + + + {p.children} + + + ); +} + +export function useTheme(): ThemeContext { + return React.useContext(ThemeContextK)!; +} diff --git a/remote_frontend/src/main.tsx b/remote_frontend/src/main.tsx index 2624abb..2ccddd9 100644 --- a/remote_frontend/src/main.tsx +++ b/remote_frontend/src/main.tsx @@ -1,25 +1,19 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import "./index.css"; import { App } from "./App"; -import { - FluentProvider, - teamsHighContrastTheme, -} from "@fluentui/react-components"; import { AlertDialogProvider } from "./hooks/providers/AlertDialogProvider"; import { ConfirmDialogProvider } from "./hooks/providers/ConfirmDialogProvider"; +import { ThemeProvider } from "./hooks/providers/ThemeProvider"; +import "./index.css"; ReactDOM.createRoot(document.getElementById("root")!).render( - + - + ); diff --git a/remote_frontend/src/widgets/MainMenu.tsx b/remote_frontend/src/widgets/MainMenu.tsx new file mode 100644 index 0000000..7f4c560 --- /dev/null +++ b/remote_frontend/src/widgets/MainMenu.tsx @@ -0,0 +1,69 @@ +import { + Menu, + MenuButton, + MenuItem, + MenuList, + MenuPopover, + MenuTrigger, +} from "@fluentui/react-components"; +import { Checkmark12Regular } from "@fluentui/react-icons"; +import { AuthApi } from "./../api/AuthApi"; +import { useAlert } from "./../hooks/providers/AlertDialogProvider"; +import { useConfirm } from "./../hooks/providers/ConfirmDialogProvider"; +import { Theme, useTheme } from "./../hooks/providers/ThemeProvider"; + +export function MainMenu(): React.ReactElement { + const alert = useAlert(); + const confirm = useConfirm(); + + const signOut = async () => { + try { + if (!(await confirm("Do you really want to sign out?"))) return; + await AuthApi.SignOut(); + } catch (e) { + console.error(e); + alert("Failed to perform sign out!"); + } + }; + return ( + + + Settings + + + + + + + Theme + + + + + + + + + + + + + Sign out + + + + ); +} + +function ThemeMenuItem(p: { label: string; value: Theme }): React.ReactElement { + const theme = useTheme(); + + return ( + : undefined} + onClick={() => theme.set(p.value)} + > + {p.label} + + ); +}