import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; import { useI18n } from '../../application/i18n/I18nProvider'; import type { Snippet } from '../../types'; import { SnippetCommandPicker } from '../snippets/SnippetCommandPicker'; import { SnippetScriptEditor } from '../snippets/SnippetScriptEditor'; import { Button } from '../ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../ui/dialog'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '../ui/tabs'; type CommandTab = 'custom' | 'snippet'; interface TmuxNewSessionModalProps { open: boolean; onOpenChange: (open: boolean) => void; onCreate: (name: string, command: string) => Promise; snippets: Snippet[]; creating?: boolean; error?: string | null; } export const TmuxNewSessionModal = memo(function TmuxNewSessionModal({ open, onOpenChange, onCreate, snippets, creating = false, error, }: TmuxNewSessionModalProps) { const { t } = useI18n(); const [commandTab, setCommandTab] = useState('custom'); const [name, setName] = useState(''); const [command, setCommand] = useState(''); const [selectedSnippetId, setSelectedSnippetId] = useState(null); const [localError, setLocalError] = useState(null); const nameInputRef = useRef(null); useEffect(() => { if (open) { setCommandTab('custom'); setName(''); setCommand(''); setSelectedSnippetId(null); setLocalError(null); } }, [open]); useEffect(() => { if (!open) return; const id = window.setTimeout(() => nameInputRef.current?.focus(), 50); return () => window.clearTimeout(id); }, [open]); const handleSnippetSelect = useCallback((snippet: Snippet) => { setSelectedSnippetId(snippet.id); setCommand(snippet.command); if (!name.trim() && snippet.label.trim()) { setName(snippet.label.trim().slice(0, 64)); } }, [name]); const handleCreate = useCallback(async () => { const trimmedName = name.trim(); if (!trimmedName) { setLocalError(t('systemManager.tmux.newSessionRequired')); return; } setLocalError(null); await onCreate(trimmedName, command); }, [command, name, onCreate, t]); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.defaultPrevented) return; if ((e.metaKey || e.ctrlKey) && e.key === 'Enter' && !creating && name.trim()) { e.preventDefault(); void handleCreate(); } }, [creating, handleCreate, name]); const handleSubmitShortcut = useCallback(() => { if (!creating && name.trim()) void handleCreate(); }, [creating, handleCreate, name]); const handleCommandChange = useCallback((value: string) => { setCommand(value); if (selectedSnippetId) { const linked = snippets.find((snippet) => snippet.id === selectedSnippetId); if (linked && value !== linked.command) { setSelectedSnippetId(null); } } }, [selectedSnippetId, snippets]); const displayError = localError || error; const selectedSnippet = snippets.find((snippet) => snippet.id === selectedSnippetId) ?? null; return ( {t('systemManager.tmux.newSessionTitle')} {t('systemManager.tmux.newSessionDesc')}
setName(e.target.value)} placeholder={t('systemManager.tmux.newSessionPlaceholder')} className="h-9" spellCheck={false} disabled={creating} />
setCommandTab(value as CommandTab)} className="flex min-h-0 flex-col" > {t('systemManager.tmux.newSessionTabCustom')} {t('systemManager.tmux.newSessionTabSnippet')}

{t('systemManager.tmux.newSessionCommandHint')}

{selectedSnippet && (

{t('systemManager.tmux.selectedSnippet', { label: selectedSnippet.label })}

)}
{displayError && (

{displayError}

)}
); });