import React, { useMemo, useState } from 'react'; import { parseSnippetVariables } from '../domain/snippetVariables'; import { Check, Clock, Keyboard, Loader2, Package, RotateCcw, Trash2 } from 'lucide-react'; import { cn } from '../lib/utils'; import SelectHostPanel from './SelectHostPanel'; import { SelectGroupDialog } from './SelectGroupDialog'; import { AsidePanel, AsidePanelContent, AsidePanelFooter } from './ui/aside-panel'; import { Button } from './ui/button'; import { Card } from './ui/card'; import { Input } from './ui/input'; import { SnippetScriptEditor } from './snippets/SnippetScriptEditor'; import { SnippetTargetsSection } from './snippets/SnippetTargetsSection'; import { ScriptEditorPanel } from './scripts/ScriptEditorPanel'; import { ScriptEditorModal } from './scripts/ScriptEditorModal'; import { isScriptSnippet } from '../domain/snippetScript.ts'; import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip'; import { Combobox } from './ui/combobox'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { HistoryItem } from './SnippetsHistoryItem'; import type { Snippet } from '@/domain/models'; import { getRunnableHostsForSnippet, resolveSnippetTargetGroupsForSave, } from '@/domain/snippetTargets.ts'; import { STORAGE_KEY_SNIPPETS_PANEL_WIDTH } from '@/infrastructure/config/storageKeys.ts'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type SnippetsRightPanelProps = Record; export const SnippetsRightPanel: React.FC = ({ rightPanelMode, hosts, customGroups, targetSelection, setTargetSelection, targetGroupSelection, setTargetGroupSelection, handleTargetSelect, handleTargetSelectionChange, handleTargetPickerBack, availableKeys, proxyProfiles, managedSources, onSaveHost, onCreateGroup, t, handleClosePanel, editingSnippet, onDelete, handleSave, handleSaveAndRun, setEditingSnippet, packageOptions, selectedPackage, packages, onPackagesChange, shortkeyError, setShortkeyError, isRecordingShortkey, setIsRecordingShortkey, openTargetPicker, targetHosts, shellHistory, handleHistoryScroll, historyScrollRef, visibleHistory, saveHistoryAsSnippet, handleCopy, copiedId, hasMoreHistory, isLoadingMore, loadMoreHistory, onRunSnippet, }) => { const detectedVariables = useMemo( () => parseSnippetVariables(editingSnippet?.command || ''), [editingSnippet?.command], ); const [scriptEditorModalOpen, setScriptEditorModalOpen] = useState(false); const [groupPickerOpen, setGroupPickerOpen] = useState(false); const isEditingScript = isScriptSnippet(editingSnippet as import('../types').Snippet); const snippetsPanelResizeProps = { resizable: true as const, persistWidthStorageKey: STORAGE_KEY_SNIPPETS_PANEL_WIDTH, resizeAriaLabel: t('snippets.panel.resizeWidth'), }; const runnableEditingSnippet = useMemo(() => ({ ...(editingSnippet as Snippet), targets: editingSnippet.targetsAllHosts ? [] : targetSelection, targetGroups: resolveSnippetTargetGroupsForSave( editingSnippet, targetGroupSelection, ), targetsAllHosts: editingSnippet.targetsAllHosts || undefined, }), [editingSnippet, targetGroupSelection, targetSelection]); const runTargets = useMemo( () => getRunnableHostsForSnippet(runnableEditingSnippet, hosts), [hosts, runnableEditingSnippet], ); const runEditingScript = () => { if (runTargets.length === 0) return; onRunSnippet?.(runnableEditingSnippet, runTargets); }; const canRunEditingScript = Boolean(editingSnippet.command?.trim()) && runTargets.length > 0; const handleTargetsAllHostsChange = (checked: boolean) => { if (checked) { setTargetSelection([]); setTargetGroupSelection([]); setEditingSnippet({ ...editingSnippet, targetsAllHosts: true, targets: [], targetGroups: undefined, }); return; } setEditingSnippet({ ...editingSnippet, targetsAllHosts: undefined, }); }; if (rightPanelMode === 'select-targets') { return ( ); } if (rightPanelMode === 'edit-snippet') { return ( <> {editingSnippet.id && ( {t('common.delete')} )} } > {!isEditingScript ? (

{t('snippets.field.description')}

setEditingSnippet({ ...editingSnippet, label: e.target.value })} className="h-10" spellCheck={false} />
) : null} {/* Package */}

{t('snippets.field.package')}

{ setEditingSnippet({ ...editingSnippet, package: val }); // If selecting an implicit parent path, persist it to packages if (val && !packages.includes(val)) { onPackagesChange([...packages, val]); } }} placeholder={t('snippets.field.packagePlaceholder')} allowCreate={true} onCreateNew={(val) => { if (!packages.includes(val)) { onPackagesChange([...packages, val]); } }} createText={t('snippets.field.createPackage')} icon={} triggerClassName="h-10" />
{/* Script / Snippet body */} {isEditingScript ? ( setScriptEditorModalOpen(true)} onRun={canRunEditingScript ? runEditingScript : undefined} /> ) : ( setEditingSnippet({ ...editingSnippet, command })} />

{t('snippets.field.variablesHelp')}

{detectedVariables.length > 0 && (
{t('snippets.field.variablesDetected')}: {detectedVariables.map((variable) => ( {variable.name} {variable.defaultValue !== undefined && ( ({t('snippets.field.variableDefault', { value: variable.defaultValue })}) )} ))}
)}
)} setGroupPickerOpen(true) : undefined} hint={isEditingScript ? (editingSnippet.trigger === 'onConnect' ? t('scripts.targets.connectOrderHint') : t('scripts.targets.hint')) : undefined} targetsAllHosts={Boolean(editingSnippet.targetsAllHosts)} onTargetsAllHostsChange={handleTargetsAllHostsChange} /> {!isEditingScript ? ( <>

{t('snippets.field.multiLineRunMode')}

{t('snippets.field.multiLineRunModeHint')}

{/* Shortkey */}

{t('snippets.field.shortkey')}

{editingSnippet.shortkey && ( {t('snippets.shortkey.clear')} )}
{shortkeyError && (

{shortkeyError}

)}

{t('snippets.shortkey.hint')}

) : null}
{/* Footer */} {isEditingScript ? ( setScriptEditorModalOpen(false)} snippet={editingSnippet as import('../types').Snippet} onChange={setEditingSnippet} onSave={handleSave} canRun={canRunEditingScript} onRun={canRunEditingScript ? runEditingScript : undefined} targetHosts={targetHosts} hosts={hosts} customGroups={customGroups} selectedHostIds={targetSelection} onSelectHost={handleTargetSelect} onSelectionChange={handleTargetSelectionChange} selectedGroupPaths={targetGroupSelection} onGroupSelectionChange={setTargetGroupSelection} targetsAllHosts={Boolean(editingSnippet.targetsAllHosts)} onTargetsAllHostsChange={handleTargetsAllHostsChange} /> ) : null}
{ setTargetGroupSelection(nextGroups); setEditingSnippet({ ...editingSnippet, targetGroups: nextGroups, targetsAllHosts: undefined, }); }} /> ); } if (rightPanelMode === 'history') { return ( {/* History List */}
{visibleHistory.length === 0 ? (

{t('snippets.history.emptyTitle')}

{t('snippets.history.emptyDesc')}

) : ( <> {visibleHistory.map((entry) => ( handleCopy(entry.id, entry.command)} isCopied={copiedId === entry.id} /> ))} {hasMoreHistory && (
{isLoadingMore ? ( ) : ( )}
)} )}
); } return null; };