/** * AppShell — 应用壳 * * 窗口拖拽约定(Tauri overlay title bar): * - 仅使用 data-tauri-drag-region 处理拖拽和双击缩放 * - 不要再叠加 startDragging() 或 CSS app-region: drag,两者会抢鼠标导致窗口拖不动 * - 标签栏空白区也由 Tauri 原生拖拽区处理 * * RDP/VNC 全屏时只隐藏 chrome,保持 TabContent 挂载,避免会话 remount 立刻退出全屏。 */ import type { ReactNode } from 'react' import { useTranslation } from 'react-i18next' import { ChevronsRight } from 'lucide-react' import Sidebar from '../components/layout/Sidebar' import TabBar from '../components/layout/TabBar' import TabContent from '../components/layout/TabContent' import StatusBar from '../components/layout/StatusBar' import type { Session } from '../stores' import { useDesktopFullscreenStore } from '../stores/desktopFullscreenStore' import { getDesktopPlatform } from '../platform/runtime' export interface AppShellProps { activeTabId: string | null isMobile: boolean sidebarCollapsed: boolean mobileSidebarOpen: boolean onToggleSidebar: () => void onToggleMobileSidebar: () => void onCloseMobileSidebar: () => void onNewSession: (group?: string) => void onQuickConnect: () => void onRdpConnect?: () => void onVncConnect?: () => void onImportSessions?: () => void onOpenLauncher: () => void onEditSession: (session: Session) => void children?: ReactNode } function TitleBar() { const platform = getDesktopPlatform() // Overlay title bar is macOS-only; Win/Linux keep the native chrome. if (platform !== 'macos') return null return (
) } function MobileMenuButton({ onClick }: { onClick: () => void }) { const { t } = useTranslation('common') return ( ) } function ExpandSidebarButton({ onClick }: { onClick: () => void }) { const { t } = useTranslation('common') return ( ) } export default function AppShell({ activeTabId, isMobile, sidebarCollapsed, mobileSidebarOpen, onToggleSidebar, onToggleMobileSidebar, onCloseMobileSidebar, onNewSession, onQuickConnect, onRdpConnect, onVncConnect, onImportSessions, onOpenLauncher, onEditSession, children, }: AppShellProps) { const handleSidebarNewSession = (group?: string) => { onNewSession(group) if (isMobile) onCloseMobileSidebar() } const handleSidebarQuickConnect = () => { onQuickConnect() if (isMobile) onCloseMobileSidebar() } const handleSidebarEditSession = (session: Session) => { onEditSession(session) if (isMobile) onCloseMobileSidebar() } const desktopSidebarHidden = !isMobile && sidebarCollapsed const desktopFullscreen = useDesktopFullscreenStore((state) => state.active) return (
{!desktopFullscreen && }
{!desktopFullscreen && isMobile && mobileSidebarOpen && (
)} {!desktopFullscreen && ( )}
{!desktopFullscreen && (
{isMobile && } {desktopSidebarHidden && }
)}
{!desktopFullscreen && (
)}
{children}
) }