prettify code

This commit is contained in:
michioxd 2024-04-14 10:04:54 +07:00 committed by Scott Lamb
parent a787703a31
commit 8036aa40b7
14 changed files with 4539 additions and 2313 deletions

6294
ui/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -76,12 +76,14 @@ function MoonfireMenu(props: Props) {
</Box>
)}
<Tooltip title="Toggle theme">
<IconButton
onClick={changeTheme}
color="inherit"
size="small"
>
{choosenTheme === CurrentMode.Light ? <Brightness7 /> : choosenTheme === CurrentMode.Dark ? <Brightness2 /> : <BrightnessAuto />}
<IconButton onClick={changeTheme} color="inherit" size="small">
{choosenTheme === CurrentMode.Light ? (
<Brightness7 />
) : choosenTheme === CurrentMode.Dark ? (
<Brightness2 />
) : (
<BrightnessAuto />
)}
</IconButton>
</Tooltip>
{props.loginState !== "unknown" && props.loginState !== "logged-in" && (

View File

@ -76,7 +76,9 @@ const DisplaySelector = (props: Props) => {
<Checkbox
checked={props.trimStartAndEnd}
size="small"
onChange={(event) => props.setTrimStartAndEnd(event.target.checked)}
onChange={(event) =>
props.setTrimStartAndEnd(event.target.checked)
}
name="trim-start-and-end"
color="secondary"
/>
@ -90,7 +92,9 @@ const DisplaySelector = (props: Props) => {
<Checkbox
checked={props.timestampTrack}
size="small"
onChange={(event) => props.setTimestampTrack(event.target.checked)}
onChange={(event) =>
props.setTimestampTrack(event.target.checked)
}
name="timestamp-track"
color="secondary"
/>

View File

@ -90,8 +90,7 @@ const StreamMultiSelector = ({ toplevel, selected, setSelected }: Props) => {
);
});
return (
<Card
>
<Card>
<CardContent>
<Box
component="table"

View File

@ -400,7 +400,9 @@ const TimerangeSelector = ({
/>
</Box>
<Box>
<FormLabel sx={{ mt: 1 }} component="legend">To</FormLabel>
<FormLabel sx={{ mt: 1 }} component="legend">
To
</FormLabel>
<RadioGroup
row
value={days.endType}

View File

@ -15,7 +15,7 @@ import Fullscreen from "@mui/icons-material/Fullscreen";
export interface Layout {
className: string;
cameras: number;
name: string
name: string;
}
// These class names must match useStyles rules (below).
@ -24,7 +24,7 @@ const LAYOUTS: Layout[] = [
{ className: "dual", cameras: 2, name: "2" },
{ className: "main-plus-five", cameras: 6, name: "Main + 5" },
{ className: "two-by-two", cameras: 4, name: "2x2" },
{ className: "three-by-three", cameras: 9, name: "3x3" }
{ className: "three-by-three", cameras: 9, name: "3x3" },
];
const MAX_CAMERAS = 9;
@ -114,9 +114,9 @@ const Multiview = (props: MultiviewProps) => {
const [selected, updateSelected] = useReducer(
selectedReducer,
searchParams.has("cams")
? JSON.parse(searchParams.get("cams") || "") :
localStorage.getItem("camsSelected") !== null ?
JSON.parse(localStorage.getItem("camsSelected") || "")
? JSON.parse(searchParams.get("cams") || "")
: localStorage.getItem("camsSelected") !== null
? JSON.parse(localStorage.getItem("camsSelected") || "")
: Array(MAX_CAMERAS).fill(null)
);
@ -124,7 +124,8 @@ const Multiview = (props: MultiviewProps) => {
* Save previously selected cameras to local storage.
*/
useEffect(() => {
if (searchParams.has("cams")) localStorage.setItem("camsSelected", (searchParams.get("cams") || ""));
if (searchParams.has("cams"))
localStorage.setItem("camsSelected", searchParams.get("cams") || "");
}, [searchParams]);
const outerRef = React.useRef<HTMLDivElement>(null);
@ -148,7 +149,6 @@ const Multiview = (props: MultiviewProps) => {
}
}, [outerRef]);
const monoviews = selected.slice(0, layout.cameras).map((e, i) => {
// When a camera is selected, use the camera's index as the key.
// This allows swapping cameras' positions without tearing down their
@ -196,11 +196,23 @@ const Multiview = (props: MultiviewProps) => {
}}
>
<Tooltip title="Toggle full screen">
<IconButton size="small" sx={{
position: 'fixed', background: 'rgba(50,50,50,0.4) !important', transition: '0.2s', opacity: '0.4', bottom: 10, right: 10, zIndex: 9, color: "#fff", ":hover": {
opacity: '1'
}
}} onClick={handleFullScreen}>
<IconButton
size="small"
sx={{
position: "fixed",
background: "rgba(50,50,50,0.4) !important",
transition: "0.2s",
opacity: "0.4",
bottom: 10,
right: 10,
zIndex: 9,
color: "#fff",
":hover": {
opacity: "1",
},
}}
onClick={handleFullScreen}
>
<Fullscreen />
</IconButton>
</Tooltip>
@ -227,12 +239,12 @@ const Multiview = (props: MultiviewProps) => {
gridTemplateColumns: {
xs: "100%",
sm: "100%",
md: "repeat(2, calc(100% / 2))"
md: "repeat(2, calc(100% / 2))",
},
gridTemplateRows: {
xs: "50%",
sm: "50%",
md: "repeat(1, calc(100% / 1))"
md: "repeat(1, calc(100% / 1))",
},
},
"&.two-by-two": {

View File

@ -19,15 +19,21 @@ export interface LiveProps {
const Live = ({ cameras, Frame }: LiveProps) => {
const [searchParams, setSearchParams] = useSearchParams();
const [multiviewLayoutIndex, setMultiviewLayoutIndex] = useState(
Number.parseInt(searchParams.get("layout") || localStorage.getItem("multiviewLayoutIndex") || "0", 10)
Number.parseInt(
searchParams.get("layout") ||
localStorage.getItem("multiviewLayoutIndex") ||
"0",
10
)
);
useEffect(() => {
if (searchParams.has("layout"))
localStorage.setItem("multiviewLayoutIndex", (searchParams.get("layout") || "0"));
localStorage.setItem(
"multiviewLayoutIndex",
searchParams.get("layout") || "0"
);
}, [searchParams]);
if ("MediaSource" in window === false) {

View File

@ -118,7 +118,7 @@ const Login = ({ open, onSuccess, handleClose }: Props) => {
</DialogTitle>
<form onSubmit={onSubmit}>
<DialogContent>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
<TextField
id="username"
label="Username"

View File

@ -18,14 +18,20 @@ import { useReducer } from "react";
import { LoginState } from "../App";
import { Link } from "react-router-dom";
export default function Header({ loginState, logout, setChangePasswordOpen, activityMenuPart, setLoginState, toplevel }:
{
loginState: LoginState,
logout: () => void,
setChangePasswordOpen: React.Dispatch<React.SetStateAction<boolean>>,
activityMenuPart?: JSX.Element,
setLoginState: React.Dispatch<React.SetStateAction<LoginState>>,
toplevel: api.ToplevelResponse | null
export default function Header({
loginState,
logout,
setChangePasswordOpen,
activityMenuPart,
setLoginState,
toplevel,
}: {
loginState: LoginState;
logout: () => void;
setChangePasswordOpen: React.Dispatch<React.SetStateAction<boolean>>;
activityMenuPart?: JSX.Element;
setLoginState: React.Dispatch<React.SetStateAction<LoginState>>;
toplevel: api.ToplevelResponse | null;
}) {
const [showMenu, toggleShowMenu] = useReducer((m: boolean) => !m, false);
@ -90,5 +96,5 @@ export default function Header({ loginState, logout, setChangePasswordOpen, acti
</List>
</Drawer>
</>
)
);
}

View File

@ -9,19 +9,21 @@ import React, { createContext } from "react";
export enum CurrentMode {
Auto = 0,
Light = 1,
Dark = 2
Dark = 2,
}
interface ThemeProps {
changeTheme: () => void,
currentTheme: 'dark' | 'light',
choosenTheme: CurrentMode
changeTheme: () => void;
currentTheme: "dark" | "light";
choosenTheme: CurrentMode;
}
export const ThemeContext = createContext<ThemeProps>({
currentTheme: window.matchMedia("(prefers-color-scheme: dark)").matches ? 'dark' : 'light',
currentTheme: window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light",
changeTheme: () => {},
choosenTheme: CurrentMode.Auto
choosenTheme: CurrentMode.Auto,
});
const ThemeMode = ({ children }: { children: JSX.Element }): JSX.Element => {
@ -40,21 +42,33 @@ const ThemeMode = ({ children }: { children: JSX.Element }): JSX.Element => {
return matches;
};
const detectedSystemColorScheme = useMediaQuery("(prefers-color-scheme: dark)") ? "dark" : "light";
const detectedSystemColorScheme = useMediaQuery(
"(prefers-color-scheme: dark)"
)
? "dark"
: "light";
const changeTheme = React.useCallback(() => {
setMode(mode === 'dark' ? 'light' : mode === 'light' ? 'system' : 'dark')
setMode(mode === "dark" ? "light" : mode === "light" ? "system" : "dark");
}, [mode, setMode]);
const currentTheme = mode === 'system' ? detectedSystemColorScheme : (mode ?? detectedSystemColorScheme);
const choosenTheme = mode === 'dark' ? CurrentMode.Dark : mode === 'light' ? CurrentMode.Light : CurrentMode.Auto;
const currentTheme =
mode === "system"
? detectedSystemColorScheme
: mode ?? detectedSystemColorScheme;
const choosenTheme =
mode === "dark"
? CurrentMode.Dark
: mode === "light"
? CurrentMode.Light
: CurrentMode.Auto;
return (
<ThemeContext.Provider value={{ changeTheme, currentTheme, choosenTheme }}>
{children}
</ThemeContext.Provider>
)
}
);
};
export default ThemeMode;

View File

@ -3,7 +3,10 @@
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception
import CssBaseline from "@mui/material/CssBaseline";
import { Experimental_CssVarsProvider, experimental_extendTheme } from "@mui/material/styles";
import {
Experimental_CssVarsProvider,
experimental_extendTheme,
} from "@mui/material/styles";
import StyledEngineProvider from "@mui/material/StyledEngineProvider";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import "@fontsource/roboto";
@ -22,15 +25,15 @@ const themeExtended = experimental_extendTheme({
dark: {
palette: {
primary: {
main: "#000000"
main: "#000000",
},
secondary: {
main: "#e65100"
}
}
main: "#e65100",
},
}
})
},
},
},
});
const container = document.getElementById("root");
const root = createRoot(container!);
root.render(

View File

@ -7,11 +7,11 @@
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";
import { vi } from 'vitest'
import { vi } from "vitest";
Object.defineProperty(window, 'matchMedia', {
Object.defineProperty(window, "matchMedia", {
writable: true,
value: vi.fn().mockImplementation(query => ({
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
@ -21,4 +21,4 @@ Object.defineProperty(window, 'matchMedia', {
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
})
});

View File

@ -11,9 +11,13 @@ const target = process.env.PROXY_TARGET ?? "http://localhost:8080/";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), viteCompression(), viteLegacyPlugin({
targets: ['defaults', 'fully supports es6-module'],
})],
plugins: [
react(),
viteCompression(),
viteLegacyPlugin({
targets: ["defaults", "fully supports es6-module"],
}),
],
server: {
proxy: {
"/api": {