import React, { lazy, Suspense } from "react"; import type { Host, SftpFileEntry } from "../../types"; import type { FileOpenerType, SystemAppInfo } from "../../lib/sftpFileUtils"; import type { useSftpState } from "../../application/state/useSftpState"; import type { HotkeyScheme, KeyBinding } from "../../domain/models"; import type { TransferTask } from "../../types"; import FileOpenerDialog from "../FileOpenerDialog"; import type { TextEditorModalSnapshot } from "../TextEditorModal"; import { TerminalHostKeyVerification } from "../terminal/TerminalHostKeyVerification"; import { Dialog, DialogContent, DialogTitle } from "../ui/dialog"; import { LazyLoadBoundary } from "../ui/lazy-load-boundary"; import { SftpConflictDialog } from "./SftpConflictDialog"; import { SftpHostPicker } from "./SftpHostPicker"; import { SftpPermissionsDialog } from "./SftpPermissionsDialog"; import { SftpTransferQueue } from "./SftpTransferQueue"; const LazyTextEditorModal = lazy(() => import("../TextEditorModal")); type SftpState = ReturnType; const TextEditorModalLoading: React.FC<{ open: boolean; fileName: string; onClose: () => void; }> = ({ open, fileName, onClose }) => ( !isOpen && onClose()}> {fileName || "Text editor"} ); const TextEditorModalUnavailable: React.FC<{ open: boolean; fileName: string; onClose: () => void; }> = ({ open, fileName, onClose }) => ( !isOpen && onClose()}> Text editor could not load.
{fileName ? `${fileName} cannot be opened until the editor reloads.` : "The editor needs to reload before it can open this file."}
); interface SftpOverlaysProps { hosts: Host[]; connectedHosts?: import("../../domain/sftpConnectedHosts").SftpConnectedHostEntry[]; sftp: SftpState; visibleTransfers: SftpState["transfers"]; showTransferQueue?: boolean; canRevealTransferTarget?: (task: TransferTask) => boolean; onRevealTransferTarget?: (task: TransferTask) => void | Promise; canCopyTransferTargetPath?: (task: TransferTask) => boolean; onCopyTransferTargetPath?: (task: TransferTask) => void | Promise; showHostPickerLeft: boolean; showHostPickerRight: boolean; hostSearchLeft: string; hostSearchRight: string; setShowHostPickerLeft: (open: boolean) => void; setShowHostPickerRight: (open: boolean) => void; setHostSearchLeft: (value: string) => void; setHostSearchRight: (value: string) => void; handleHostSelectLeft: (host: Host | "local", options?: { sourceSessionId?: string }) => void; handleHostSelectRight: (host: Host | "local", options?: { sourceSessionId?: string }) => void; permissionsState: { file: SftpFileEntry; side: "left" | "right"; fullPath: string } | null; setPermissionsState: (state: { file: SftpFileEntry; side: "left" | "right"; fullPath: string } | null) => void; showTextEditor: boolean; setShowTextEditor: (open: boolean) => void; textEditorTarget: { file: SftpFileEntry; side: "left" | "right"; fullPath: string } | null; setTextEditorTarget: (target: { file: SftpFileEntry; side: "left" | "right"; fullPath: string } | null) => void; textEditorContent: string; setTextEditorContent: (content: string) => void; handleSaveTextFile: (content: string) => Promise; editorWordWrap: boolean; setEditorWordWrap: (enabled: boolean) => void; hotkeyScheme: HotkeyScheme; keyBindings: KeyBinding[]; showFileOpenerDialog: boolean; setShowFileOpenerDialog: (open: boolean) => void; fileOpenerTarget: { file: SftpFileEntry; side: "left" | "right"; fullPath: string } | null; setFileOpenerTarget: (target: { file: SftpFileEntry; side: "left" | "right"; fullPath: string } | null) => void; handleFileOpenerSelect: (openerType: FileOpenerType, setAsDefault: boolean, systemApp?: SystemAppInfo) => void; handleSelectSystemApp: (systemApp: { path: string; name: string }) => void; onPromoteToTab?: (snapshot: TextEditorModalSnapshot) => void; onRequestTerminalFocus?: () => void; } export const SftpOverlays: React.FC = React.memo(({ hosts, connectedHosts = [], sftp, visibleTransfers, showTransferQueue = true, canRevealTransferTarget, onRevealTransferTarget, canCopyTransferTargetPath, onCopyTransferTargetPath, showHostPickerLeft, showHostPickerRight, hostSearchLeft, hostSearchRight, setShowHostPickerLeft, setShowHostPickerRight, setHostSearchLeft, setHostSearchRight, handleHostSelectLeft, handleHostSelectRight, permissionsState, setPermissionsState, showTextEditor, setShowTextEditor, textEditorTarget, setTextEditorTarget, textEditorContent, setTextEditorContent, handleSaveTextFile, editorWordWrap, setEditorWordWrap, hotkeyScheme, keyBindings, showFileOpenerDialog, setShowFileOpenerDialog, fileOpenerTarget, setFileOpenerTarget, handleFileOpenerSelect, handleSelectSystemApp, onPromoteToTab, onRequestTerminalFocus, }) => { const textEditorFileName = textEditorTarget?.file.name || ""; const closeTextEditor = () => { setShowTextEditor(false); setTextEditorTarget(null); setTextEditorContent(""); onRequestTerminalFocus?.(); }; return ( <> {/* Host pickers for adding new tabs */} handleHostSelectLeft("local")} onSelectHost={handleHostSelectLeft} /> handleHostSelectRight("local")} onSelectHost={handleHostSelectRight} /> {showTransferQueue && ( )} { if (!open) sftp.rejectHostKeyVerification(); }} > Confirm host key {sftp.hostKeyVerification && ( 0} progressLogs={sftp.hostKeyVerification.progressLogs} onClose={sftp.rejectHostKeyVerification} onContinue={sftp.acceptHostKeyVerification} onAddAndContinue={sftp.acceptAndSaveHostKeyVerification} /> )} !open && setPermissionsState(null)} file={permissionsState?.file ?? null} onSave={(_file, permissions) => { if (permissionsState) { sftp.changePermissions( permissionsState.side, permissionsState.fullPath, permissions, ); } setPermissionsState(null); }} /> {/* Text Editor Modal */} {showTextEditor && ( } > } > setEditorWordWrap(!editorWordWrap)} hotkeyScheme={hotkeyScheme} keyBindings={keyBindings} onPromoteToTab={onPromoteToTab} /> )} {/* File Opener Dialog */} { setShowFileOpenerDialog(false); setFileOpenerTarget(null); }} fileName={fileOpenerTarget?.file.name || ""} onSelect={handleFileOpenerSelect} onSelectSystemApp={handleSelectSystemApp} /> ); });