Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
598 lines
27 KiB
TypeScript
598 lines
27 KiB
TypeScript
import { useEffect, useRef, type Dispatch, type SetStateAction } from 'react';
|
|
import type { CustomKeyBindings, HotkeyScheme, SessionLogFormat, TerminalSettings, UILanguage } from '../../domain/models';
|
|
import { parseCustomKeyBindingsStorageRecord } from '../../domain/customKeyBindings';
|
|
import { resolveSupportedLocale } from '../../infrastructure/config/i18n';
|
|
import {
|
|
STORAGE_KEY_AUTO_UPDATE_ENABLED,
|
|
STORAGE_KEY_CUSTOM_CSS,
|
|
STORAGE_KEY_CUSTOM_KEY_BINDINGS,
|
|
STORAGE_KEY_EDITOR_WORD_WRAP,
|
|
STORAGE_KEY_GLOBAL_HOTKEY_ENABLED,
|
|
STORAGE_KEY_HOTKEY_SCHEME,
|
|
STORAGE_KEY_SESSION_LOGS_DIR,
|
|
STORAGE_KEY_SESSION_LOGS_ENABLED,
|
|
STORAGE_KEY_SESSION_LOGS_FORMAT,
|
|
STORAGE_KEY_SESSION_LOGS_TIMESTAMPS_ENABLED,
|
|
STORAGE_KEY_SSH_DEBUG_LOGS_ENABLED,
|
|
STORAGE_KEY_SSH_DEEP_LINK_ENABLED,
|
|
STORAGE_KEY_JMS_DEEP_LINK_ENABLED,
|
|
STORAGE_KEY_EXPLORER_CONTEXT_MENU_ENABLED,
|
|
STORAGE_KEY_RESTORE_PREVIOUS_SESSION,
|
|
STORAGE_KEY_RESTORE_TERMINAL_CWD,
|
|
STORAGE_KEY_STARTUP_LANDING,
|
|
STORAGE_KEY_SFTP_AUTO_OPEN_SIDEBAR,
|
|
STORAGE_KEY_SFTP_FOLLOW_TERMINAL_CWD,
|
|
STORAGE_KEY_SFTP_AUTO_SYNC,
|
|
STORAGE_KEY_SFTP_DEFAULT_VIEW_MODE,
|
|
STORAGE_KEY_SFTP_DOUBLE_CLICK_BEHAVIOR,
|
|
STORAGE_KEY_SFTP_SHOW_HIDDEN_FILES,
|
|
STORAGE_KEY_SFTP_TRANSFER_CONCURRENCY,
|
|
STORAGE_KEY_SSH_TRANSPORT_IDLE_TTL_MS,
|
|
STORAGE_KEY_SFTP_USE_COMPRESSED_UPLOAD,
|
|
STORAGE_KEY_SFTP_SKIP_UNCHANGED,
|
|
STORAGE_KEY_SHOW_ONLY_UNGROUPED_HOSTS_IN_ROOT,
|
|
STORAGE_KEY_SHOW_RECENT_HOSTS,
|
|
STORAGE_KEY_HOST_CLICK_BEHAVIOR,
|
|
STORAGE_KEY_SHOW_SFTP_TAB,
|
|
STORAGE_KEY_SHOW_HOST_TREE_SIDEBAR,
|
|
STORAGE_KEY_TERMINAL_SIDE_PANEL_AUTO_OPEN,
|
|
STORAGE_KEY_TERMINAL_SIDE_PANEL_AUTO_OPEN_TAB,
|
|
STORAGE_KEY_SHELL_ONLY_TAB_NUMBER_SHORTCUTS,
|
|
STORAGE_KEY_SHOW_TAB_NUMBER_BADGES,
|
|
STORAGE_KEY_DISABLE_TERMINAL_FONT_ZOOM,
|
|
STORAGE_KEY_TERM_FOLLOW_APP_THEME,
|
|
STORAGE_KEY_TERM_FONT_FAMILY,
|
|
STORAGE_KEY_TERM_FONT_SIZE,
|
|
STORAGE_KEY_TERM_SETTINGS,
|
|
STORAGE_KEY_TERM_THEME,
|
|
STORAGE_KEY_TERM_THEME_DARK,
|
|
STORAGE_KEY_TERM_THEME_LIGHT,
|
|
STORAGE_KEY_UI_FONT_FAMILY,
|
|
STORAGE_KEY_UI_LANGUAGE,
|
|
STORAGE_KEY_WORKSPACE_FOCUS_STYLE,
|
|
STORAGE_KEY_WINDOW_OPACITY,
|
|
STORAGE_KEY_APP_ICON_VARIANT,
|
|
} from '../../infrastructure/config/storageKeys';
|
|
import { resolveAppIconVariant, type AppIconVariant } from '../../domain/appIconVariant';
|
|
import { resolveAppearanceStorageEvent } from './appearanceSync';
|
|
import {
|
|
isValidUiFontId,
|
|
migrateIncomingTerminalFontId,
|
|
} from './settingsStateDefaults';
|
|
import { isTerminalSidePanelAutoOpenTab, type TerminalSidePanelAutoOpenTab } from '../../domain/terminalSidePanelAutoOpen';
|
|
import { isHostClickBehavior, type HostClickBehavior } from '../../domain/hostClickBehavior';
|
|
import { isStartupLanding, type StartupLanding } from '../../domain/startupLanding';
|
|
|
|
interface UseSettingsStorageSyncParams {
|
|
enabled?: boolean;
|
|
theme: 'dark' | 'light' | 'system';
|
|
lightUiThemeId: string;
|
|
darkUiThemeId: string;
|
|
accentMode: 'theme' | 'custom';
|
|
customAccent: string;
|
|
customAccentVersion: number;
|
|
customCSS: string;
|
|
uiFontFamilyId: string;
|
|
hotkeyScheme: HotkeyScheme;
|
|
uiLanguage: UILanguage;
|
|
terminalThemeId: string;
|
|
followAppTerminalTheme: boolean;
|
|
terminalFontFamilyId: string;
|
|
terminalFontSize: number;
|
|
sftpDoubleClickBehavior: 'open' | 'transfer';
|
|
sftpAutoSync: boolean;
|
|
sftpShowHiddenFiles: boolean;
|
|
sftpUseCompressedUpload: boolean;
|
|
sftpSkipUnchanged: boolean;
|
|
sftpAutoOpenSidebar: boolean;
|
|
sftpFollowTerminalCwd: boolean;
|
|
sftpDefaultViewMode: 'list' | 'tree';
|
|
showRecentHosts: boolean;
|
|
hostClickBehavior: HostClickBehavior;
|
|
showOnlyUngroupedHostsInRoot: boolean;
|
|
showSftpTab: boolean;
|
|
showHostTreeSidebar: boolean;
|
|
terminalSidePanelAutoOpen: boolean;
|
|
terminalSidePanelAutoOpenTab: TerminalSidePanelAutoOpenTab;
|
|
shellOnlyTabNumberShortcuts: boolean;
|
|
showTabNumberBadges: boolean;
|
|
disableTerminalFontZoom: boolean;
|
|
restorePreviousSession: boolean;
|
|
restoreTerminalCwd: boolean;
|
|
startupLanding: StartupLanding;
|
|
editorWordWrap: boolean;
|
|
sessionLogsEnabled: boolean;
|
|
sessionLogsDir: string;
|
|
sessionLogsFormat: SessionLogFormat;
|
|
sessionLogsTimestampsEnabled: boolean;
|
|
sshDebugLogsEnabled: boolean;
|
|
sshDeepLinkEnabled: boolean;
|
|
jmsDeepLinkEnabled: boolean;
|
|
explorerContextMenuEnabled: boolean;
|
|
globalHotkeyEnabled: boolean;
|
|
autoUpdateEnabled: boolean;
|
|
windowOpacity: number;
|
|
appIconVariant: AppIconVariant;
|
|
setTheme: Dispatch<SetStateAction<'dark' | 'light' | 'system'>>;
|
|
setLightUiThemeId: Dispatch<SetStateAction<string>>;
|
|
setDarkUiThemeId: Dispatch<SetStateAction<string>>;
|
|
setAccentMode: Dispatch<SetStateAction<'theme' | 'custom'>>;
|
|
applyIncomingCustomAccent: (raw: unknown) => void;
|
|
setCustomCSS: Dispatch<SetStateAction<string>>;
|
|
setUiFontFamilyId: Dispatch<SetStateAction<string>>;
|
|
setHotkeyScheme: Dispatch<SetStateAction<HotkeyScheme>>;
|
|
setUiLanguage: Dispatch<SetStateAction<UILanguage>>;
|
|
setTerminalThemeId: Dispatch<SetStateAction<string>>;
|
|
setTerminalThemeDarkId: Dispatch<SetStateAction<string>>;
|
|
setTerminalThemeLightId: Dispatch<SetStateAction<string>>;
|
|
setFollowAppTerminalThemeState: Dispatch<SetStateAction<boolean>>;
|
|
setTerminalFontFamilyId: Dispatch<SetStateAction<string>>;
|
|
setTerminalFontSize: (raw: unknown) => void;
|
|
setSftpDoubleClickBehavior: Dispatch<SetStateAction<'open' | 'transfer'>>;
|
|
setSftpAutoSync: Dispatch<SetStateAction<boolean>>;
|
|
setSftpShowHiddenFiles: Dispatch<SetStateAction<boolean>>;
|
|
setSftpUseCompressedUpload: Dispatch<SetStateAction<boolean>>;
|
|
setSftpSkipUnchanged: Dispatch<SetStateAction<boolean>>;
|
|
setSftpAutoOpenSidebar: Dispatch<SetStateAction<boolean>>;
|
|
setSftpFollowTerminalCwd: Dispatch<SetStateAction<boolean>>;
|
|
setSftpDefaultViewMode: Dispatch<SetStateAction<'list' | 'tree'>>;
|
|
setShowRecentHostsState: Dispatch<SetStateAction<boolean>>;
|
|
setHostClickBehaviorState: Dispatch<SetStateAction<HostClickBehavior>>;
|
|
setShowOnlyUngroupedHostsInRootState: Dispatch<SetStateAction<boolean>>;
|
|
setShowSftpTabState: Dispatch<SetStateAction<boolean>>;
|
|
setShowHostTreeSidebarState: Dispatch<SetStateAction<boolean>>;
|
|
setTerminalSidePanelAutoOpenState: Dispatch<SetStateAction<boolean>>;
|
|
setTerminalSidePanelAutoOpenTabState: Dispatch<SetStateAction<TerminalSidePanelAutoOpenTab>>;
|
|
setShellOnlyTabNumberShortcutsState: Dispatch<SetStateAction<boolean>>;
|
|
setShowTabNumberBadgesState: Dispatch<SetStateAction<boolean>>;
|
|
setDisableTerminalFontZoomState: Dispatch<SetStateAction<boolean>>;
|
|
setRestorePreviousSessionState: Dispatch<SetStateAction<boolean>>;
|
|
setRestoreTerminalCwdState: Dispatch<SetStateAction<boolean>>;
|
|
setStartupLandingState: Dispatch<SetStateAction<StartupLanding>>;
|
|
setEditorWordWrapState: Dispatch<SetStateAction<boolean>>;
|
|
setSessionLogsEnabled: Dispatch<SetStateAction<boolean>>;
|
|
setSessionLogsDir: Dispatch<SetStateAction<string>>;
|
|
setSessionLogsFormat: Dispatch<SetStateAction<SessionLogFormat>>;
|
|
setSessionLogsTimestampsEnabled: Dispatch<SetStateAction<boolean>>;
|
|
setSshDebugLogsEnabled: Dispatch<SetStateAction<boolean>>;
|
|
setSshDeepLinkEnabledState: (enabled: boolean) => void;
|
|
setJmsDeepLinkEnabledState: (enabled: boolean) => void;
|
|
setExplorerContextMenuEnabledState: (enabled: boolean) => void;
|
|
setGlobalHotkeyEnabled: Dispatch<SetStateAction<boolean>>;
|
|
setWindowOpacity: (raw: unknown) => void;
|
|
setAppIconVariant: Dispatch<SetStateAction<AppIconVariant>>;
|
|
setAutoUpdateEnabled: Dispatch<SetStateAction<boolean>>;
|
|
setWorkspaceFocusStyleState: Dispatch<SetStateAction<'dim' | 'border'>>;
|
|
setSftpTransferConcurrencyState: Dispatch<SetStateAction<number>>;
|
|
setSshTransportIdleTtlMsState: Dispatch<SetStateAction<number>>;
|
|
applyIncomingCustomKeyBindings: (incoming: { bindings: CustomKeyBindings; version: number; origin: string }) => void;
|
|
mergeIncomingTerminalSettings: (incoming: Partial<TerminalSettings>) => void;
|
|
}
|
|
|
|
export function useSettingsStorageSync({
|
|
enabled = true,
|
|
theme, lightUiThemeId, darkUiThemeId, accentMode, customAccent, customAccentVersion,
|
|
customCSS, uiFontFamilyId, hotkeyScheme, uiLanguage,
|
|
terminalThemeId, followAppTerminalTheme, terminalFontFamilyId, terminalFontSize,
|
|
sftpDoubleClickBehavior, sftpAutoSync, sftpShowHiddenFiles,
|
|
sftpUseCompressedUpload, sftpSkipUnchanged, sftpAutoOpenSidebar, sftpFollowTerminalCwd, sftpDefaultViewMode,
|
|
showRecentHosts, hostClickBehavior, showOnlyUngroupedHostsInRoot, showSftpTab, showHostTreeSidebar, terminalSidePanelAutoOpen, terminalSidePanelAutoOpenTab, shellOnlyTabNumberShortcuts, showTabNumberBadges, disableTerminalFontZoom, restorePreviousSession, restoreTerminalCwd, startupLanding,
|
|
editorWordWrap, sessionLogsEnabled, sessionLogsDir, sessionLogsFormat, sessionLogsTimestampsEnabled, sshDebugLogsEnabled, sshDeepLinkEnabled, jmsDeepLinkEnabled, explorerContextMenuEnabled,
|
|
globalHotkeyEnabled, autoUpdateEnabled, windowOpacity, appIconVariant,
|
|
setTheme, setLightUiThemeId, setDarkUiThemeId, setAccentMode, applyIncomingCustomAccent,
|
|
setCustomCSS, setUiFontFamilyId, setHotkeyScheme, setUiLanguage,
|
|
setTerminalThemeId, setTerminalThemeDarkId, setTerminalThemeLightId,
|
|
setFollowAppTerminalThemeState, setTerminalFontFamilyId, setTerminalFontSize,
|
|
setSftpDoubleClickBehavior, setSftpAutoSync, setSftpShowHiddenFiles,
|
|
setSftpUseCompressedUpload, setSftpSkipUnchanged, setSftpAutoOpenSidebar, setSftpFollowTerminalCwd, setSftpDefaultViewMode,
|
|
setShowRecentHostsState, setHostClickBehaviorState, setShowOnlyUngroupedHostsInRootState, setShowSftpTabState, setShowHostTreeSidebarState, setTerminalSidePanelAutoOpenState, setTerminalSidePanelAutoOpenTabState, setShellOnlyTabNumberShortcutsState, setShowTabNumberBadgesState, setDisableTerminalFontZoomState, setRestorePreviousSessionState, setRestoreTerminalCwdState, setStartupLandingState,
|
|
setEditorWordWrapState, setSessionLogsEnabled, setSessionLogsDir, setSessionLogsFormat, setSessionLogsTimestampsEnabled, setSshDebugLogsEnabled, setSshDeepLinkEnabledState, setJmsDeepLinkEnabledState, setExplorerContextMenuEnabledState,
|
|
setGlobalHotkeyEnabled, setWindowOpacity, setAppIconVariant, setAutoUpdateEnabled, setWorkspaceFocusStyleState,
|
|
setSftpTransferConcurrencyState, setSshTransportIdleTtlMsState,
|
|
applyIncomingCustomKeyBindings, mergeIncomingTerminalSettings,
|
|
}: UseSettingsStorageSyncParams) {
|
|
// Fix 4: Keep a ref snapshot of current settings so the storage event handler
|
|
// can compare without capturing 25+ state variables in its closure / dep array.
|
|
// This avoids constant listener detach/reattach on every state change.
|
|
const settingsSnapshotRef = useRef({
|
|
theme, lightUiThemeId, darkUiThemeId, accentMode, customAccent, customAccentVersion,
|
|
customCSS, uiFontFamilyId, hotkeyScheme, uiLanguage,
|
|
terminalThemeId, followAppTerminalTheme, terminalFontFamilyId, terminalFontSize,
|
|
sftpDoubleClickBehavior, sftpAutoSync, sftpShowHiddenFiles,
|
|
sftpUseCompressedUpload, sftpSkipUnchanged, sftpAutoOpenSidebar, sftpFollowTerminalCwd, sftpDefaultViewMode,
|
|
showRecentHosts, hostClickBehavior, showOnlyUngroupedHostsInRoot, showSftpTab, showHostTreeSidebar, terminalSidePanelAutoOpen, terminalSidePanelAutoOpenTab, shellOnlyTabNumberShortcuts, showTabNumberBadges, disableTerminalFontZoom, restorePreviousSession, restoreTerminalCwd, startupLanding,
|
|
editorWordWrap, sessionLogsEnabled, sessionLogsDir, sessionLogsFormat, sessionLogsTimestampsEnabled, sshDebugLogsEnabled, sshDeepLinkEnabled, jmsDeepLinkEnabled, explorerContextMenuEnabled,
|
|
globalHotkeyEnabled, autoUpdateEnabled, windowOpacity, appIconVariant,
|
|
});
|
|
settingsSnapshotRef.current = {
|
|
theme, lightUiThemeId, darkUiThemeId, accentMode, customAccent, customAccentVersion,
|
|
customCSS, uiFontFamilyId, hotkeyScheme, uiLanguage,
|
|
terminalThemeId, followAppTerminalTheme, terminalFontFamilyId, terminalFontSize,
|
|
sftpDoubleClickBehavior, sftpAutoSync, sftpShowHiddenFiles,
|
|
sftpUseCompressedUpload, sftpSkipUnchanged, sftpAutoOpenSidebar, sftpFollowTerminalCwd, sftpDefaultViewMode,
|
|
showRecentHosts, hostClickBehavior, showOnlyUngroupedHostsInRoot, showSftpTab, showHostTreeSidebar, terminalSidePanelAutoOpen, terminalSidePanelAutoOpenTab, shellOnlyTabNumberShortcuts, showTabNumberBadges, disableTerminalFontZoom, restorePreviousSession, restoreTerminalCwd, startupLanding,
|
|
editorWordWrap, sessionLogsEnabled, sessionLogsDir, sessionLogsFormat, sessionLogsTimestampsEnabled, sshDebugLogsEnabled, sshDeepLinkEnabled, jmsDeepLinkEnabled, explorerContextMenuEnabled,
|
|
globalHotkeyEnabled, autoUpdateEnabled, windowOpacity, appIconVariant,
|
|
};
|
|
|
|
// Listen for storage changes from other windows (cross-window sync)
|
|
useEffect(() => {
|
|
if (!enabled) return;
|
|
const handleStorageChange = (e: StorageEvent) => {
|
|
const s = settingsSnapshotRef.current;
|
|
const appearance = resolveAppearanceStorageEvent(s, e.key, e.newValue);
|
|
if (appearance.handled) {
|
|
if (appearance.next.theme !== s.theme) setTheme(appearance.next.theme);
|
|
if (appearance.next.lightUiThemeId !== s.lightUiThemeId) setLightUiThemeId(appearance.next.lightUiThemeId);
|
|
if (appearance.next.darkUiThemeId !== s.darkUiThemeId) setDarkUiThemeId(appearance.next.darkUiThemeId);
|
|
if (appearance.next.accentMode !== s.accentMode) setAccentMode(appearance.next.accentMode);
|
|
if (
|
|
appearance.next.customAccent !== s.customAccent
|
|
|| appearance.next.customAccentVersion !== s.customAccentVersion
|
|
) {
|
|
applyIncomingCustomAccent({
|
|
color: appearance.next.customAccent,
|
|
version: appearance.next.customAccentVersion,
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
if (e.key === STORAGE_KEY_CUSTOM_CSS && e.newValue !== null) {
|
|
if (e.newValue !== s.customCSS) {
|
|
setCustomCSS(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_UI_FONT_FAMILY && e.newValue) {
|
|
if (isValidUiFontId(e.newValue) && e.newValue !== s.uiFontFamilyId) {
|
|
setUiFontFamilyId(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_HOTKEY_SCHEME && e.newValue) {
|
|
const newScheme = e.newValue as HotkeyScheme;
|
|
if (newScheme !== s.hotkeyScheme) {
|
|
setHotkeyScheme(newScheme);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_UI_LANGUAGE && e.newValue) {
|
|
const next = resolveSupportedLocale(e.newValue);
|
|
if (next !== s.uiLanguage) {
|
|
setUiLanguage(next as UILanguage);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_CUSTOM_KEY_BINDINGS && e.newValue) {
|
|
const parsed = parseCustomKeyBindingsStorageRecord(e.newValue);
|
|
if (parsed) {
|
|
applyIncomingCustomKeyBindings(parsed);
|
|
}
|
|
}
|
|
// Sync terminal settings from other windows
|
|
if (e.key === STORAGE_KEY_TERM_SETTINGS && e.newValue) {
|
|
try {
|
|
const newSettings = JSON.parse(e.newValue) as TerminalSettings;
|
|
mergeIncomingTerminalSettings(newSettings);
|
|
} catch {
|
|
// ignore parse errors
|
|
}
|
|
}
|
|
// Sync terminal theme from other windows
|
|
if (e.key === STORAGE_KEY_TERM_THEME && e.newValue) {
|
|
if (e.newValue !== s.terminalThemeId) {
|
|
setTerminalThemeId(e.newValue);
|
|
}
|
|
}
|
|
// Sync per-mode follow terminal themes from other windows
|
|
if (e.key === STORAGE_KEY_TERM_THEME_DARK && e.newValue) {
|
|
const next = e.newValue;
|
|
setTerminalThemeDarkId((prev) => (prev === next ? prev : next));
|
|
}
|
|
if (e.key === STORAGE_KEY_TERM_THEME_LIGHT && e.newValue) {
|
|
const next = e.newValue;
|
|
setTerminalThemeLightId((prev) => (prev === next ? prev : next));
|
|
}
|
|
// Sync follow-app-theme toggle from other windows
|
|
if (e.key === STORAGE_KEY_TERM_FOLLOW_APP_THEME && e.newValue) {
|
|
const next = e.newValue === 'true';
|
|
if (next !== s.followAppTerminalTheme) {
|
|
setFollowAppTerminalThemeState(next);
|
|
}
|
|
}
|
|
// Sync terminal font family from other windows
|
|
if (e.key === STORAGE_KEY_TERM_FONT_FAMILY && e.newValue) {
|
|
const migrated = migrateIncomingTerminalFontId(e.newValue);
|
|
if (migrated && migrated !== s.terminalFontFamilyId) {
|
|
setTerminalFontFamilyId(migrated);
|
|
}
|
|
}
|
|
// Sync terminal font size from other windows
|
|
if (e.key === STORAGE_KEY_TERM_FONT_SIZE && e.newValue) {
|
|
setTerminalFontSize(e.newValue);
|
|
}
|
|
// Sync SFTP double-click behavior from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_DOUBLE_CLICK_BEHAVIOR && e.newValue) {
|
|
if ((e.newValue === 'open' || e.newValue === 'transfer') && e.newValue !== s.sftpDoubleClickBehavior) {
|
|
setSftpDoubleClickBehavior(e.newValue);
|
|
}
|
|
}
|
|
// Sync SFTP auto-sync setting from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_AUTO_SYNC && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sftpAutoSync) {
|
|
setSftpAutoSync(newValue);
|
|
}
|
|
}
|
|
// Sync SFTP show hidden files setting from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_SHOW_HIDDEN_FILES && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sftpShowHiddenFiles) {
|
|
setSftpShowHiddenFiles(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_EDITOR_WORD_WRAP && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.editorWordWrap) {
|
|
setEditorWordWrapState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SESSION_LOGS_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sessionLogsEnabled) {
|
|
setSessionLogsEnabled(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SESSION_LOGS_DIR && e.newValue !== null) {
|
|
if (e.newValue !== s.sessionLogsDir) {
|
|
setSessionLogsDir(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SESSION_LOGS_FORMAT && e.newValue) {
|
|
if (
|
|
(e.newValue === 'txt' || e.newValue === 'raw' || e.newValue === 'html') &&
|
|
e.newValue !== s.sessionLogsFormat
|
|
) {
|
|
setSessionLogsFormat(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SESSION_LOGS_TIMESTAMPS_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sessionLogsTimestampsEnabled) {
|
|
setSessionLogsTimestampsEnabled(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SSH_DEBUG_LOGS_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sshDebugLogsEnabled) {
|
|
setSshDebugLogsEnabled(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SSH_DEEP_LINK_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sshDeepLinkEnabled) {
|
|
setSshDeepLinkEnabledState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_JMS_DEEP_LINK_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.jmsDeepLinkEnabled) {
|
|
setJmsDeepLinkEnabledState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_EXPLORER_CONTEXT_MENU_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.explorerContextMenuEnabled) {
|
|
setExplorerContextMenuEnabledState(newValue);
|
|
}
|
|
}
|
|
// Sync SFTP compressed upload setting from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_USE_COMPRESSED_UPLOAD && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true' || e.newValue === 'enabled';
|
|
if (newValue !== s.sftpUseCompressedUpload) {
|
|
setSftpUseCompressedUpload(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SFTP_SKIP_UNCHANGED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sftpSkipUnchanged) {
|
|
setSftpSkipUnchanged(newValue);
|
|
}
|
|
}
|
|
// Sync SFTP auto-open sidebar setting from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_AUTO_OPEN_SIDEBAR && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sftpAutoOpenSidebar) {
|
|
setSftpAutoOpenSidebar(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SFTP_FOLLOW_TERMINAL_CWD && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.sftpFollowTerminalCwd) {
|
|
setSftpFollowTerminalCwd(newValue);
|
|
}
|
|
}
|
|
// Sync SFTP default view mode from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_DEFAULT_VIEW_MODE && e.newValue) {
|
|
if ((e.newValue === 'list' || e.newValue === 'tree') && e.newValue !== s.sftpDefaultViewMode) {
|
|
setSftpDefaultViewMode(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SHOW_RECENT_HOSTS && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.showRecentHosts) {
|
|
setShowRecentHostsState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_HOST_CLICK_BEHAVIOR && e.newValue !== null) {
|
|
if (isHostClickBehavior(e.newValue) && e.newValue !== s.hostClickBehavior) {
|
|
setHostClickBehaviorState(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SHOW_ONLY_UNGROUPED_HOSTS_IN_ROOT && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.showOnlyUngroupedHostsInRoot) {
|
|
setShowOnlyUngroupedHostsInRootState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SHOW_SFTP_TAB && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.showSftpTab) {
|
|
setShowSftpTabState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SHOW_HOST_TREE_SIDEBAR && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.showHostTreeSidebar) {
|
|
setShowHostTreeSidebarState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_TERMINAL_SIDE_PANEL_AUTO_OPEN && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.terminalSidePanelAutoOpen) {
|
|
setTerminalSidePanelAutoOpenState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_TERMINAL_SIDE_PANEL_AUTO_OPEN_TAB && e.newValue !== null) {
|
|
if (isTerminalSidePanelAutoOpenTab(e.newValue) && e.newValue !== s.terminalSidePanelAutoOpenTab) {
|
|
setTerminalSidePanelAutoOpenTabState(e.newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SHELL_ONLY_TAB_NUMBER_SHORTCUTS && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.shellOnlyTabNumberShortcuts) {
|
|
setShellOnlyTabNumberShortcutsState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SHOW_TAB_NUMBER_BADGES && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.showTabNumberBadges) {
|
|
setShowTabNumberBadgesState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_DISABLE_TERMINAL_FONT_ZOOM && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.disableTerminalFontZoom) {
|
|
setDisableTerminalFontZoomState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_RESTORE_PREVIOUS_SESSION && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.restorePreviousSession) {
|
|
setRestorePreviousSessionState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_RESTORE_TERMINAL_CWD && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.restoreTerminalCwd) {
|
|
setRestoreTerminalCwdState(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_STARTUP_LANDING && e.newValue !== null) {
|
|
if (isStartupLanding(e.newValue) && e.newValue !== s.startupLanding) {
|
|
setStartupLandingState(e.newValue);
|
|
}
|
|
}
|
|
// Sync global hotkey enabled setting from other windows
|
|
if (e.key === STORAGE_KEY_GLOBAL_HOTKEY_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.globalHotkeyEnabled) {
|
|
setGlobalHotkeyEnabled(newValue);
|
|
}
|
|
}
|
|
// Sync auto-update enabled setting from other windows
|
|
if (e.key === STORAGE_KEY_AUTO_UPDATE_ENABLED && e.newValue !== null) {
|
|
const newValue = e.newValue === 'true';
|
|
if (newValue !== s.autoUpdateEnabled) {
|
|
setAutoUpdateEnabled(newValue);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_WINDOW_OPACITY && e.newValue !== null) {
|
|
setWindowOpacity(e.newValue);
|
|
}
|
|
if (e.key === STORAGE_KEY_APP_ICON_VARIANT && e.newValue !== null) {
|
|
const newValue = resolveAppIconVariant(e.newValue);
|
|
if (newValue !== s.appIconVariant) {
|
|
setAppIconVariant(newValue);
|
|
}
|
|
}
|
|
// Sync workspace focus style from other windows
|
|
if (e.key === STORAGE_KEY_WORKSPACE_FOCUS_STYLE && e.newValue !== null) {
|
|
if (e.newValue === 'dim' || e.newValue === 'border') {
|
|
setWorkspaceFocusStyleState(e.newValue);
|
|
}
|
|
}
|
|
// Sync transfer concurrency from other windows
|
|
if (e.key === STORAGE_KEY_SFTP_TRANSFER_CONCURRENCY && e.newValue !== null) {
|
|
const num = Number(e.newValue);
|
|
if (num >= 1 && num <= 16) {
|
|
setSftpTransferConcurrencyState(num);
|
|
}
|
|
}
|
|
if (e.key === STORAGE_KEY_SSH_TRANSPORT_IDLE_TTL_MS && e.newValue !== null) {
|
|
const num = Number(e.newValue);
|
|
if (num === 0 || num === 60_000 || num === 300_000 || num === 900_000 || num === 1_800_000) {
|
|
setSshTransportIdleTtlMsState((prev) => (prev === num ? prev : num));
|
|
}
|
|
}
|
|
};
|
|
|
|
window.addEventListener('storage', handleStorageChange);
|
|
return () => window.removeEventListener('storage', handleStorageChange);
|
|
}, [
|
|
enabled,
|
|
applyIncomingCustomKeyBindings,
|
|
mergeIncomingTerminalSettings,
|
|
setAccentMode,
|
|
setAutoUpdateEnabled,
|
|
applyIncomingCustomAccent,
|
|
setCustomCSS,
|
|
setDarkUiThemeId,
|
|
setEditorWordWrapState,
|
|
setFollowAppTerminalThemeState,
|
|
setGlobalHotkeyEnabled,
|
|
setHostClickBehaviorState,
|
|
setWindowOpacity,
|
|
setAppIconVariant,
|
|
setHotkeyScheme,
|
|
setLightUiThemeId,
|
|
setSessionLogsDir,
|
|
setSessionLogsEnabled,
|
|
setSessionLogsFormat,
|
|
setSessionLogsTimestampsEnabled,
|
|
setSshDeepLinkEnabledState,
|
|
setJmsDeepLinkEnabledState,
|
|
setExplorerContextMenuEnabledState,
|
|
setSshDebugLogsEnabled,
|
|
setSftpAutoOpenSidebar,
|
|
setSftpFollowTerminalCwd,
|
|
setSftpAutoSync,
|
|
setSftpDefaultViewMode,
|
|
setSftpDoubleClickBehavior,
|
|
setSftpShowHiddenFiles,
|
|
setSftpTransferConcurrencyState,
|
|
setSshTransportIdleTtlMsState,
|
|
setSftpUseCompressedUpload,
|
|
setSftpSkipUnchanged,
|
|
setShowOnlyUngroupedHostsInRootState,
|
|
setShowHostTreeSidebarState,
|
|
setTerminalSidePanelAutoOpenState,
|
|
setTerminalSidePanelAutoOpenTabState,
|
|
setShowRecentHostsState,
|
|
setShowSftpTabState,
|
|
setShellOnlyTabNumberShortcutsState,
|
|
setShowTabNumberBadgesState,
|
|
setDisableTerminalFontZoomState,
|
|
setRestorePreviousSessionState,
|
|
setRestoreTerminalCwdState,
|
|
setStartupLandingState,
|
|
setTerminalFontFamilyId,
|
|
setTerminalFontSize,
|
|
setTerminalThemeDarkId,
|
|
setTerminalThemeId,
|
|
setTerminalThemeLightId,
|
|
setTheme,
|
|
setUiFontFamilyId,
|
|
setUiLanguage,
|
|
setWorkspaceFocusStyleState,
|
|
]);
|
|
|
|
|
|
}
|