import { Plus, LogIn, Clock, Server, ChevronRight, Laptop, Terminal, Monitor, Cast } from 'lucide-react' import { useTranslation } from 'react-i18next' import HostDistroIcon from '../common/HostDistroIcon' import { useEffect, useRef, useState, useCallback, useMemo } from 'react' import { useSessionStore } from '../../stores' import { useTabStore } from '../../stores/tabStore' import { useEntitlementStore } from '../../stores/entitlementStore' import EmptyState from '../common/EmptyState' import { openLocalShellTab, type ShellOption } from '../layout/sidebar/LocalShellMenu' import appIconUrl from '../../assets/opsxshell-app-icon.png' import { shellDisplayFromPath } from '../../utils/shellName' import { fallbackLocalShells, modKeyLabel } from '../../utils/platformShells' import { buildOpenTabPayload, defaultPortForProtocol, sessionProtocol } from '../../utils/sessionProtocol' interface WelcomeViewProps { onNewSession?: () => void onQuickConnect?: () => void onRdpConnect?: () => void onVncConnect?: () => void onImportSessions?: () => void } function Kbd({ children }: { children: string }) { return ( {children} ) } export default function WelcomeView({ onNewSession, onQuickConnect, onRdpConnect, onVncConnect, onImportSessions, }: WelcomeViewProps) { const { t } = useTranslation('sessions') const { addTab } = useTabStore() const requirePro = useEntitlementStore((s) => s.requirePro) const sessions = useSessionStore((s) => s.sessions) const recentSessions = sessions.slice(-8).reverse() const modKey = useMemo(() => modKeyLabel(), []) const [shells, setShells] = useState([]) const [shellMenuOpen, setShellMenuOpen] = useState(false) const shellMenuRef = useRef(null) useEffect(() => { const fallback = () => setShells(fallbackLocalShells() as ShellOption[]) void window.opsxApi ?.localListShells?.() .then((res) => { if (res?.success && res.shells?.length) setShells(res.shells) else fallback() }) .catch(fallback) }, []) useEffect(() => { if (!shellMenuOpen) return const onDoc = (e: MouseEvent) => { if (shellMenuRef.current && !shellMenuRef.current.contains(e.target as Node)) { setShellMenuOpen(false) } } document.addEventListener('mousedown', onDoc) return () => document.removeEventListener('mousedown', onDoc) }, [shellMenuOpen]) const defaultShell = shells.find((s) => s.isDefault) || shells[0] const defaultShellLabel = defaultShell ? shellDisplayFromPath(defaultShell.path || defaultShell.name).title : 'Shell' const openDefaultLocal = useCallback(() => { openLocalShellTab( defaultShell ? { path: defaultShell.path, kind: defaultShell.kind, name: defaultShell.name } : undefined ) }, [defaultShell]) const handleSessionClick = (session: (typeof sessions)[number]) => { const protocol = session.protocol ?? 'ssh' if ((protocol === 'rdp' || protocol === 'vnc') && !requirePro(protocol)) return addTab(buildOpenTabPayload(session)) } return (

OpsXShell

{t('welcome.tagline')}

{shellMenuOpen && shells.length > 0 && (
{shells.map((s) => ( ))}
)}

{t('welcome.sectionDesktop')}

{t('welcome.sectionRecent')}

{recentSessions.length > 0 && {recentSessions.length}}
{recentSessions.length === 0 ? (
) : (
    {recentSessions.map((session) => (
  • ))}
)}
) }