import { Info, Trash as Trash2 } from '@phosphor-icons/react' import { type KeyboardEvent, useState } from 'react' import { Button } from './ui/button' import { Input } from './ui/input' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './ui/tooltip' import { ConfirmDeleteDialog } from './ConfirmDeleteDialog' import { SettingsGroup, SettingsGroupItem, SettingsSwitchRow } from './SettingsControls' import { createTranslator, type AppLocale } from '../lib/i18n' import { trackEvent } from '../lib/telemetry' import type { VaultOption } from './status-bar/types' import { workspaceIdentityFromVault } from '../utils/workspaces' import { AccentColorPicker } from './AccentColorPicker' interface WorkspaceSettingsSectionProps { defaultWorkspacePath?: string | null enabled: boolean locale: AppLocale onEnabledChange: (enabled: boolean) => void onRemoveVault?: (path: string) => void onSetDefaultWorkspace?: (path: string) => void onUpdateWorkspaceIdentity?: (path: string, patch: Partial) => void vaults: VaultOption[] } function workspaceInputId(alias: string, field: 'name' | 'label' | 'slug'): string { return `settings-workspace-${alias}-${field}` } function sanitizeWorkspaceShortLabel(value: string): string { return value.trim().toUpperCase().slice(0, 3) } function WorkspaceFieldLabel({ htmlFor, label, tooltip, }: { htmlFor: string label: string tooltip: string }) { return (
{tooltip}
) } function WorkspaceIdentityInputs({ canEdit, locale, onUpdateWorkspaceIdentity, vault, }: Pick & { canEdit: boolean vault: VaultOption }) { const t = createTranslator(locale) const workspace = workspaceIdentityFromVault(vault) const nameId = workspaceInputId(workspace.alias, 'name') const labelId = workspaceInputId(workspace.alias, 'label') const slugId = workspaceInputId(workspace.alias, 'slug') const savedNameDraft = vault.label ?? '' const savedShortLabelDraft = sanitizeWorkspaceShortLabel(vault.shortLabel || workspace.shortLabel) const [nameDraft, setNameDraft] = useState(savedNameDraft) const [shortLabelDraft, setShortLabelDraft] = useState(savedShortLabelDraft) const commitNameDraft = () => { if (!canEdit || nameDraft === savedNameDraft) return onUpdateWorkspaceIdentity?.(vault.path, { label: nameDraft }) } const commitShortLabelDraft = () => { const normalizedShortLabel = sanitizeWorkspaceShortLabel(shortLabelDraft) if (!canEdit || normalizedShortLabel === savedShortLabelDraft) return onUpdateWorkspaceIdentity?.(vault.path, { shortLabel: normalizedShortLabel }) } const blurOnEnter = (event: KeyboardEvent) => { if (event.key === 'Enter') { event.currentTarget.blur() } } return (
setNameDraft(event.target.value)} onBlur={commitNameDraft} onKeyDown={blurOnEnter} aria-label={t('settings.workspaces.nameAria', { label: workspace.label })} disabled={!canEdit} className="h-8 bg-transparent" />
setShortLabelDraft(sanitizeWorkspaceShortLabel(event.target.value))} onBlur={commitShortLabelDraft} onKeyDown={blurOnEnter} aria-label={t('settings.workspaces.labelAria', { label: workspace.label })} disabled={!canEdit} className="h-8 bg-transparent uppercase" />
) } function WorkspaceRowActions({ canEdit, locale, onSetDefaultWorkspace, onUpdateWorkspaceIdentity, onRemoveVault, workspace, vault, }: Pick & { canEdit: boolean workspace: ReturnType vault: VaultOption }) { const t = createTranslator(locale) const removeLabel = t('settings.workspaces.removeAria', { label: workspace.label }) return (
onUpdateWorkspaceIdentity?.(vault.path, { color })} size={18} /> {onRemoveVault && ( )}
) } function WorkspaceSettingsRow({ defaultWorkspacePath, locale, onSetDefaultWorkspace, onUpdateWorkspaceIdentity, onRemoveVault, vault, }: Pick & { vault: VaultOption }) { const workspace = workspaceIdentityFromVault(vault, { defaultWorkspacePath }) const canEdit = !!onUpdateWorkspaceIdentity && vault.path !== '' && !vault.managedDefault return (
{workspace.label}
{workspace.path}
) } export function WorkspaceSettingsSection({ defaultWorkspacePath, enabled, locale, onEnabledChange, onRemoveVault, onSetDefaultWorkspace, onUpdateWorkspaceIdentity, vaults, }: WorkspaceSettingsSectionProps) { const t = createTranslator(locale) const [vaultPendingRemoval, setVaultPendingRemoval] = useState(null) const pendingRemovalIdentity = vaultPendingRemoval ? workspaceIdentityFromVault(vaultPendingRemoval, { defaultWorkspacePath }) : null return ( {enabled && (
{vaults.map((vault) => ( setVaultPendingRemoval(vault) : undefined} vault={vault} /> ))}
)}
setVaultPendingRemoval(null)} onConfirm={() => { if (vaultPendingRemoval) { onRemoveVault?.(vaultPendingRemoval.path) } setVaultPendingRemoval(null) }} />
) }