import React, { Suspense, lazy, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useActiveTabId, useIsSftpActive, useIsVaultActive } from '../state/activeTabStore'; import { useTerminalHostTreeLayoutWidth } from '../state/terminalHostTreeStore'; import { isTerminalContentTabSurface } from './workTabSurface'; import { cn } from '../../lib/utils'; import { ConnectionLog, TerminalTheme } from '../../types'; import { LazyLoadBoundary } from '../../components/ui/lazy-load-boundary'; import type { LogView as LogViewType } from '../state/logViewState'; import type { SftpView as SftpViewComponent } from '../../components/SftpView'; import type { TerminalLayer as TerminalLayerComponent } from '../../components/TerminalLayer'; // Visibility container for VaultView - isolates isActive subscription export const VaultViewContainer: React.FC<{ children: React.ReactNode; appThemeStyle?: React.CSSProperties; }> = ({ children, appThemeStyle }) => { const isActive = useIsVaultActive(); const wasActiveRef = useRef(isActive); const [suppressActiveTransition, setSuppressActiveTransition] = useState(false); const isActivating = isActive && !wasActiveRef.current; const shouldSuppressTransition = isActivating || suppressActiveTransition; const containerStyle: React.CSSProperties = isActive ? {} : { visibility: 'hidden', pointerEvents: 'none', position: 'absolute', zIndex: -1 }; useLayoutEffect(() => { const wasActive = wasActiveRef.current; wasActiveRef.current = isActive; if (!isActive || wasActive) return; setSuppressActiveTransition(true); const view = window; let firstFrame = 0; let secondFrame = 0; firstFrame = view.requestAnimationFrame(() => { secondFrame = view.requestAnimationFrame(() => { setSuppressActiveTransition(false); }); }); return () => { view.cancelAnimationFrame(firstFrame); view.cancelAnimationFrame(secondFrame); }; }, [isActive]); return (
{children}
); }; // LogView wrapper - manages visibility based on active tab interface LogViewWrapperProps { logView: LogViewType; defaultTerminalTheme: TerminalTheme; defaultFontSize: number; onClose: () => void; onUpdateLog: (logId: string, updates: Partial) => void; } export function getLogViewWrapperStyle( isVisible: boolean, hostTreeLayoutWidth: number, ): React.CSSProperties { const baseStyle = { left: hostTreeLayoutWidth, }; return isVisible ? baseStyle : { visibility: 'hidden', pointerEvents: 'none', position: 'absolute', zIndex: -1, ...baseStyle }; } export const LogViewWrapper: React.FC = ({ logView, defaultTerminalTheme, defaultFontSize, onClose, onUpdateLog }) => { const activeTabId = useActiveTabId(); const isVisible = activeTabId === logView.id; const hostTreeLayoutWidth = useTerminalHostTreeLayoutWidth(); const containerStyle = getLogViewWrapperStyle(isVisible, hostTreeLayoutWidth); return (
}>
); }; const LazyLogView = lazy(() => import('../../components/LogView')); const LazySftpView = lazy(() => import('../../components/SftpView').then((m) => ({ default: m.SftpView })), ); const LazyTerminalLayer = lazy(() => import('../../components/TerminalLayer').then((m) => ({ default: m.TerminalLayer })), ); type SftpViewProps = React.ComponentProps; type TerminalLayerProps = React.ComponentProps; const LogViewFallback = () => (