import { useCallback, useMemo } from 'react'; import { normalizeToolbarItemLayout, reorderToolbarItems, type ToolbarItemLayout, type ToolbarItemLayoutDefaults, type ToolbarItemPlacement, } from '../../domain/toolbarItemLayout'; import { STORAGE_KEY_TERMINAL_SIDE_PANEL_TAB_LAYOUT, STORAGE_KEY_TERMINAL_SIDE_PANEL_TAB_ORDER, } from '../../infrastructure/config/storageKeys'; import { localStorageAdapter } from '../../infrastructure/persistence/localStorageAdapter'; import { useToolbarItemLayout } from './useToolbarItemLayout'; import type { SidePanelTool } from '../../domain/sidePanelLayout'; export type TerminalSidePanelTabId = SidePanelTool; export const TERMINAL_SIDE_PANEL_TAB_DEFAULT_ORDER: TerminalSidePanelTabId[] = [ 'sftp', 'scripts', 'history', 'theme', 'system', 'notes', 'ai', 'system-monitor', ]; export const TERMINAL_SIDE_PANEL_TAB_IDS = new Set( TERMINAL_SIDE_PANEL_TAB_DEFAULT_ORDER, ); export const TERMINAL_SIDE_PANEL_TAB_LAYOUT_DEFAULTS: ToolbarItemLayoutDefaults = { order: [...TERMINAL_SIDE_PANEL_TAB_DEFAULT_ORDER], placement: Object.fromEntries( TERMINAL_SIDE_PANEL_TAB_DEFAULT_ORDER.map((id) => [id, 'show' as const]), ), }; /** Order-only normalizer (legacy + tests). */ export function normalizeTerminalSidePanelTabOrder(value: unknown): TerminalSidePanelTabId[] { return normalizeToolbarItemLayout(value, TERMINAL_SIDE_PANEL_TAB_LAYOUT_DEFAULTS) .order as TerminalSidePanelTabId[]; } export function reorderTerminalSidePanelTab( order: TerminalSidePanelTabId[], draggedTab: TerminalSidePanelTabId, targetTab: TerminalSidePanelTabId, placement: 'before' | 'after' = 'before', ): TerminalSidePanelTabId[] { const layout: ToolbarItemLayout = { order, placement: Object.fromEntries(order.map((id) => [id, 'show' as ToolbarItemPlacement])), }; return reorderToolbarItems(layout, draggedTab, targetTab, placement) .order as TerminalSidePanelTabId[]; } export function fitTerminalSidePanelTabs(params: { shown: TerminalSidePanelTabId[]; collapsed: TerminalSidePanelTabId[]; active: TerminalSidePanelTabId | null; maxShown: number; }): { shown: TerminalSidePanelTabId[]; collapsed: TerminalSidePanelTabId[] } { if (params.shown.length <= params.maxShown) { return { shown: params.shown, collapsed: params.collapsed }; } const kept = new Set(params.shown.slice(0, Math.max(1, params.maxShown))); if (params.active && params.shown.includes(params.active) && !kept.has(params.active)) { const lastKept = [...kept].at(-1); if (lastKept) kept.delete(lastKept); kept.add(params.active); } const shown = params.shown.filter((id) => kept.has(id)); const autoCollapsed = params.shown.filter((id) => !kept.has(id)); return { shown, collapsed: [...autoCollapsed, ...params.collapsed.filter((id) => !autoCollapsed.includes(id))], }; } /** * Seed the modern layout storage from the legacy order-only key when needed. */ function migrateSidePanelTabLayoutIfNeeded(): void { try { const modern = localStorageAdapter.read(STORAGE_KEY_TERMINAL_SIDE_PANEL_TAB_LAYOUT); if (modern != null) return; const legacy = localStorageAdapter.read(STORAGE_KEY_TERMINAL_SIDE_PANEL_TAB_ORDER); if (legacy == null) return; const layout = normalizeToolbarItemLayout(legacy, TERMINAL_SIDE_PANEL_TAB_LAYOUT_DEFAULTS); localStorageAdapter.write(STORAGE_KEY_TERMINAL_SIDE_PANEL_TAB_LAYOUT, layout); } catch { // Best effort. } } migrateSidePanelTabLayoutIfNeeded(); export function useTerminalSidePanelTabOrder(): { sidePanelTabOrder: TerminalSidePanelTabId[]; setSidePanelTabOrder: (order: TerminalSidePanelTabId[]) => void; layout: ToolbarItemLayout; setPlacement: ReturnType['setPlacement']; move: ReturnType['move']; reorder: (draggedId: string, targetId: string, placement?: 'before' | 'after') => void; resetLayout: () => void; partition: ReturnType['partition']; } { const { layout, setPlacement, setOrder, move, reorder, reset, partition, } = useToolbarItemLayout( STORAGE_KEY_TERMINAL_SIDE_PANEL_TAB_LAYOUT, TERMINAL_SIDE_PANEL_TAB_LAYOUT_DEFAULTS, ); const sidePanelTabOrder = layout.order as TerminalSidePanelTabId[]; const setSidePanelTabOrder = useCallback( (order: TerminalSidePanelTabId[]) => { setOrder(order); }, [setOrder], ); return useMemo( () => ({ sidePanelTabOrder, setSidePanelTabOrder, layout, setPlacement, move, reorder, resetLayout: reset, partition, }), [layout, move, partition, reorder, reset, setPlacement, setSidePanelTabOrder, sidePanelTabOrder], ); }