diff --git a/src/App.tsx b/src/App.tsx index 6c8462e..2b46147 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,7 @@ function MainContent(): React.JSX.Element { const { currentTheme } = useTheme() const [messageApi, contextHolder] = message.useMessage() const { isIosDevice, isAndroidDevice, defaultPortraitMode } = useMemo(getMobileDeviceInfo, []) + const [immersiveMode, setImmersiveMode] = useState(false) useEffect(() => { const api = (window as any).api @@ -27,6 +28,11 @@ function MainContent(): React.JSX.Element { const currentPath = location.pathname === "/" ? "/home" : location.pathname const targetPath = route === "/" ? "/home" : route + if (immersiveMode && !targetPath.startsWith("/home")) { + navigate("/", { replace: true }) + return + } + if (currentPath !== targetPath) { navigate(route) } @@ -44,7 +50,7 @@ function MainContent(): React.JSX.Element { disposed = true if (unlisten) unlisten() } - }, [navigate, location.pathname]) + }, [navigate, location.pathname, immersiveMode]) const [wizardVisible, setWizardVisible] = useState(false) const [permission, setPermission] = useState<"admin" | "points" | "view">("view") @@ -302,6 +308,7 @@ function MainContent(): React.JSX.Element { const onMenuChange = (v: string) => { const key = String(v) + if (immersiveMode && key !== "home") return if (key === "home") navigate("/") if (key === "students") navigate("/students") if (key === "score") navigate("/score") @@ -315,6 +322,7 @@ function MainContent(): React.JSX.Element { } const toggleSidebar = () => { + if (immersiveMode) return if (isPortraitMode && sidebarCollapsed) { setFloatingSidebarExpanded((prev) => !prev) return @@ -322,6 +330,26 @@ function MainContent(): React.JSX.Element { setSidebarCollapsed((prev) => !prev) } + useEffect(() => { + if (!immersiveMode) return + if (location.pathname !== "/" && !location.pathname.startsWith("/home")) { + navigate("/", { replace: true }) + } + }, [immersiveMode, location.pathname, navigate]) + + const toggleImmersiveMode = () => { + setImmersiveMode((prev) => { + const next = !prev + if (next) { + setFloatingSidebarExpanded(false) + if (location.pathname !== "/" && !location.pathname.startsWith("/home")) { + navigate("/", { replace: true }) + } + } + return next + }) + } + const isDark = currentTheme?.mode === "dark" const brandColor = currentTheme?.config?.tdesign?.brandColor || "#0052D9" @@ -338,15 +366,17 @@ function MainContent(): React.JSX.Element { > {contextHolder} - + {!immersiveMode && ( + + )} setWizardVisible(false)} /> diff --git a/src/components/ContentArea.tsx b/src/components/ContentArea.tsx index 6b3af31..002eeac 100644 --- a/src/components/ContentArea.tsx +++ b/src/components/ContentArea.tsx @@ -1,6 +1,11 @@ import React, { Suspense, lazy, useEffect } from "react" import { Layout, Space, Button, Tag, Spin } from "antd" -import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons" +import { + MenuFoldOutlined, + MenuUnfoldOutlined, + FullscreenOutlined, + FullscreenExitOutlined, +} from "@ant-design/icons" import { Routes, Route, Navigate } from "react-router-dom" import { useTranslation } from "react-i18next" import { WindowControls } from "./WindowControls" @@ -58,6 +63,9 @@ interface ContentAreaProps { floatingExpand: boolean floatingExpanded: boolean onToggleSidebar: () => void + immersiveMode: boolean + isHomePage: boolean + onToggleImmersiveMode: () => void } export function ContentArea({ @@ -71,6 +79,9 @@ export function ContentArea({ floatingExpand, floatingExpanded, onToggleSidebar, + immersiveMode, + isHomePage, + onToggleImmersiveMode, }: ContentAreaProps): React.JSX.Element { const { t } = useTranslation() @@ -144,26 +155,28 @@ export function ContentArea({ } as React.CSSProperties } > -