import { useEffect, useMemo, useState } from 'react'; import { X } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import ProviderLoginModal from '../../provider-auth/view/ProviderLoginModal'; import { Button } from '../../../shared/view/ui'; import SettingsSidebar from '../view/SettingsSidebar'; import AgentsSettingsTab from '../view/tabs/agents-settings/AgentsSettingsTab'; import AppearanceSettingsTab from '../view/tabs/AppearanceSettingsTab'; import CredentialsSettingsTab from '../view/tabs/api-settings/CredentialsSettingsTab'; import VoiceSettingsTab from '../view/tabs/VoiceSettingsTab'; import GitSettingsTab from '../view/tabs/git-settings/GitSettingsTab'; import BrowserUseSettingsTab from '../view/tabs/browser-use-settings/BrowserUseSettingsTab'; import ComputerUseSettingsTab from '../view/tabs/computer-use-settings/ComputerUseSettingsTab'; import NotificationsSettingsTab from '../view/tabs/NotificationsSettingsTab'; import TasksSettingsTab from '../view/tabs/tasks-settings/TasksSettingsTab'; import PluginSettingsTab from '../../plugins/view/PluginSettingsTab'; import AboutTab from '../view/tabs/AboutTab'; import { useSettingsController } from '../hooks/useSettingsController'; import { useWebPush } from '../../../hooks/useWebPush'; import type { SettingsProps } from '../types/types'; type DesktopNotificationsState = { enabled: boolean; supported: boolean; connectedCount?: number; targetCount?: number; lastError?: string | null; }; function Settings({ isOpen, onClose, projects = [], initialTab = 'agents' }: SettingsProps) { const { t } = useTranslation('settings'); const desktopNotificationsBridge = useMemo(() => ( typeof window === 'undefined' ? null : ((window as any).cloudcliDesktopNotifications || null) ), []); const [desktopNotificationsState, setDesktopNotificationsState] = useState(null); const { activeTab, setActiveTab, saveStatus, projectSortOrder, setProjectSortOrder, codeEditorSettings, updateCodeEditorSetting, claudePermissions, setClaudePermissions, notificationPreferences, setNotificationPreferences, cursorPermissions, setCursorPermissions, codexPermissionMode, setCodexPermissionMode, providerAuthStatus, geminiPermissionMode, setGeminiPermissionMode, openLoginForProvider, showLoginModal, setShowLoginModal, loginProvider, handleLoginComplete, } = useSettingsController({ isOpen, initialTab }); const { permission: pushPermission, isSubscribed: isPushSubscribed, isLoading: isPushLoading, subscribe: pushSubscribe, unsubscribe: pushUnsubscribe, } = useWebPush(); const handleEnablePush = async () => { await pushSubscribe(); // Server sets webPush: true in preferences on subscribe; sync local state setNotificationPreferences({ ...notificationPreferences, channels: { ...notificationPreferences.channels, webPush: true }, }); }; const handleDisablePush = async () => { await pushUnsubscribe(); // Server sets webPush: false in preferences on unsubscribe; sync local state setNotificationPreferences({ ...notificationPreferences, channels: { ...notificationPreferences.channels, webPush: false }, }); }; useEffect(() => { if (!desktopNotificationsBridge) return undefined; let mounted = true; desktopNotificationsBridge.getState().then((state: any) => { if (mounted) { setDesktopNotificationsState(state?.desktopNotifications || null); } }).catch(() => {}); const unsubscribe = desktopNotificationsBridge.onStateUpdated?.((state: any) => { if (mounted) { setDesktopNotificationsState(state?.desktopNotifications || null); } }); return () => { mounted = false; unsubscribe?.(); }; }, [desktopNotificationsBridge]); const handleEnableDesktopNotifications = async () => { if (!desktopNotificationsBridge) return; const state = await desktopNotificationsBridge.update({ enabled: true }); setDesktopNotificationsState(state?.desktopNotifications || null); setNotificationPreferences({ ...notificationPreferences, channels: { ...notificationPreferences.channels, desktop: true }, }); }; const handleDisableDesktopNotifications = async () => { if (!desktopNotificationsBridge) return; const state = await desktopNotificationsBridge.update({ enabled: false }); setDesktopNotificationsState(state?.desktopNotifications || null); setNotificationPreferences({ ...notificationPreferences, channels: { ...notificationPreferences.channels, desktop: false }, }); }; if (!isOpen) { return null; } const isAuthenticated = Boolean(loginProvider && providerAuthStatus[loginProvider].authenticated); return (
{/* Header */}

{t('title')}

{saveStatus === 'success' && ( {t('saveStatus.success')} )}
{/* Body: sidebar + content */}
{/* Content */}
{activeTab === 'appearance' && ( updateCodeEditorSetting('theme', value)} onCodeEditorWordWrapChange={(value) => updateCodeEditorSetting('wordWrap', value)} onCodeEditorShowMinimapChange={(value) => updateCodeEditorSetting('showMinimap', value)} onCodeEditorLineNumbersChange={(value) => updateCodeEditorSetting('lineNumbers', value)} onCodeEditorFontSizeChange={(value) => updateCodeEditorSetting('fontSize', value)} /> )} {activeTab === 'git' && } {activeTab === 'agents' && ( )} {activeTab === 'tasks' && } {activeTab === 'browser' && } {activeTab === 'computer' && } {activeTab === 'notifications' && ( )} {activeTab === 'api' && } {activeTab === 'voice' && } {activeTab === 'plugins' && } {activeTab === 'about' && }
setShowLoginModal(false)} provider={loginProvider || 'claude'} onComplete={handleLoginComplete} isAuthenticated={isAuthenticated} />
); } export default Settings;