Update TerminalSettings.tsx

This commit is contained in:
pobb 2026-05-14 15:01:46 +08:00 committed by GitHub
parent 2a505917e6
commit e4a487dd4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -37,6 +37,7 @@ export function TerminalSettings({
docked = false,
}: TerminalSettingsProps = {}) {
const t = useTranslation()
const isWindows = typeof navigator !== 'undefined' && navigator.platform.toLowerCase().includes('win')
const hostRef = useRef<HTMLDivElement | null>(null)
const terminalRef = useRef<XTermTerminal | null>(null)
const fitRef = useRef<XTermFitAddon | null>(null)
@ -289,6 +290,10 @@ export function TerminalSettings({
</div>
)}
{isWindows && (
<BashPathSettings isTauri={terminalApi.isAvailable()} />
)}
{status === 'unavailable' ? (
<div className="flex flex-1 items-center justify-center rounded-[var(--radius-lg)] border border-dashed border-[var(--color-border)] bg-[var(--color-surface-container-low)] p-8 text-center">
<div>
@ -341,3 +346,120 @@ function StatusPill({ status, label }: { status: TerminalStatus; label: string }
</span>
)
}
function BashPathSettings({ isTauri }: { isTauri: boolean }) {
const t = useTranslation()
const [bashPath, setBashPath] = useState<string | null>(null)
const [saving, setSaving] = useState(false)
const [saved, setSaved] = useState(false)
const [invalid, setInvalid] = useState(false)
useEffect(() => {
if (!isTauri) return
void terminalApi.getBashPath().then((path) => setBashPath(path)).catch(() => {})
}, [isTauri])
const handleSave = async () => {
const trimmed = bashPath?.trim() || null
setSaving(true)
setInvalid(false)
setSaved(false)
try {
await terminalApi.setBashPath(trimmed)
setBashPath(trimmed)
setSaved(true)
setTimeout(() => setSaved(false), 2000)
} catch {
setInvalid(true)
} finally {
setSaving(false)
}
}
const handleReset = async () => {
setSaving(true)
setSaved(false)
setInvalid(false)
try {
await terminalApi.setBashPath(null)
setBashPath(null)
setSaved(true)
setTimeout(() => setSaved(false), 2000)
} catch {
// ignore
} finally {
setSaving(false)
}
}
const handleBrowse = async () => {
if (!isTauri) return
try {
const { open } = await import('@tauri-apps/plugin-dialog')
const selected = await open({
title: t('settings.terminal.bashPathLabel'),
multiple: false,
filters: [{
name: 'Bash Executable',
extensions: ['exe', '', 'bat', 'cmd', 'ps1'],
}],
})
if (selected && typeof selected === 'string') {
setBashPath(selected)
setInvalid(false)
}
} catch {
// user cancelled
}
}
if (!isTauri) return null
return (
<div className="mb-3 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface-container-low)] px-4 py-3">
<label className="mb-1.5 block text-sm font-medium text-[var(--color-text-primary)]">
{t('settings.terminal.bashPathLabel')}
</label>
<p className="mb-2 text-xs text-[var(--color-text-tertiary)]">
{t('settings.terminal.bashPathDescription')}
</p>
<div className="flex gap-2">
<input
type="text"
value={bashPath || ''}
onChange={(e) => { setBashPath(e.target.value); setInvalid(false); setSaved(false) }}
placeholder={t('settings.terminal.bashPathLabel')}
className="flex-1 rounded-[var(--radius-sm)] border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-1.5 text-sm font-mono text-[var(--color-text-primary)] outline-none placeholder:text-[var(--color-text-tertiary)] focus:border-[var(--color-border-focus)]"
/>
<button
type="button"
onClick={handleBrowse}
className="inline-flex h-8 items-center gap-1 rounded-[var(--radius-sm)] border border-[var(--color-border)] px-3 text-xs font-medium text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-hover)]"
>
<span className="material-symbols-outlined text-[16px]">folder_open</span>
</button>
<button
type="button"
onClick={handleSave}
disabled={saving}
className="inline-flex h-8 items-center gap-1 rounded-[var(--radius-sm)] bg-[var(--color-text-primary)] px-3 text-xs font-medium text-[var(--color-surface)] transition-colors hover:opacity-90 disabled:opacity-50"
>
{saved ? t('settings.terminal.bashPathSaved') : t('settings.terminal.bashPathSave')}
</button>
<button
type="button"
onClick={handleReset}
disabled={saving || bashPath === null}
className="inline-flex h-8 items-center gap-1 rounded-[var(--radius-sm)] border border-[var(--color-border)] px-3 text-xs font-medium text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-hover)] disabled:opacity-50"
>
{t('settings.terminal.bashPathReset')}
</button>
</div>
{invalid && (
<p className="mt-1.5 text-xs text-[var(--color-error)]">
{t('settings.terminal.bashPathInvalid')}
</p>
)}
</div>
)
}