import React, { useState, useEffect } from 'react'; import { motion } from 'framer-motion'; import { toast } from 'react-toastify'; import { classNames } from '~/utils/classNames'; import { Switch } from '~/components/ui/Switch'; import { themeStore, kTheme } from '~/lib/stores/theme'; import type { UserProfile } from '~/components/@settings/core/types'; import { useStore } from '@nanostores/react'; import { shortcutsStore } from '~/lib/stores/settings'; import { isMac } from '~/utils/os'; // Helper to format shortcut key display const formatShortcutKey = (key: string) => { if (key === '`') { return '`'; } return key.toUpperCase(); }; // Helper to get modifier key symbols/text const getModifierSymbol = (modifier: string): string => { switch (modifier) { case 'meta': return isMac ? '⌘' : 'Win'; case 'alt': return isMac ? '⌥' : 'Alt'; case 'ctrl': return isMac ? '⌃' : 'Ctrl'; case 'shift': return '⇧'; default: return modifier; } }; export default function SettingsTab() { const [currentTimezone, setCurrentTimezone] = useState(''); const [settings, setSettings] = useState(() => { const saved = localStorage.getItem('bolt_user_profile'); return saved ? JSON.parse(saved) : { theme: 'system', notifications: true, language: 'en', timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, }; }); useEffect(() => { setCurrentTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone); }, []); // Apply theme when settings changes useEffect(() => { if (settings.theme === 'system') { // Remove theme override localStorage.removeItem(kTheme); const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; document.querySelector('html')?.setAttribute('data-theme', prefersDark ? 'dark' : 'light'); themeStore.set(prefersDark ? 'dark' : 'light'); } else { themeStore.set(settings.theme); localStorage.setItem(kTheme, settings.theme); document.querySelector('html')?.setAttribute('data-theme', settings.theme); } }, [settings.theme]); // Save settings automatically when they change useEffect(() => { try { // Get existing profile data const existingProfile = JSON.parse(localStorage.getItem('bolt_user_profile') || '{}'); // Merge with new settings const updatedProfile = { ...existingProfile, theme: settings.theme, notifications: settings.notifications, language: settings.language, timezone: settings.timezone, }; localStorage.setItem('bolt_user_profile', JSON.stringify(updatedProfile)); toast.success('Settings updated'); } catch (error) { console.error('Error saving settings:', error); toast.error('Failed to update settings'); } }, [settings]); return (
{/* Theme & Language */}
Appearance
{(['light', 'dark', 'system'] as const).map((theme) => ( ))}
{settings.notifications ? 'Notifications are enabled' : 'Notifications are disabled'} { // Update local state setSettings((prev) => ({ ...prev, notifications: checked })); // Update localStorage immediately const existingProfile = JSON.parse(localStorage.getItem('bolt_user_profile') || '{}'); const updatedProfile = { ...existingProfile, notifications: checked, }; localStorage.setItem('bolt_user_profile', JSON.stringify(updatedProfile)); // Dispatch storage event for other components window.dispatchEvent( new StorageEvent('storage', { key: 'bolt_user_profile', newValue: JSON.stringify(updatedProfile), }), ); toast.success(`Notifications ${checked ? 'enabled' : 'disabled'}`); }} />
{/* Timezone */}
Time Settings
{/* Keyboard Shortcuts */}
Keyboard Shortcuts
{Object.entries(useStore(shortcutsStore)).map(([name, shortcut]) => (
{name.replace(/([A-Z])/g, ' $1').toLowerCase()} {shortcut.description && ( {shortcut.description} )}
{shortcut.ctrlOrMetaKey && ( {getModifierSymbol(isMac ? 'meta' : 'ctrl')} )} {shortcut.ctrlKey && ( {getModifierSymbol('ctrl')} )} {shortcut.metaKey && ( {getModifierSymbol('meta')} )} {shortcut.altKey && ( {getModifierSymbol('alt')} )} {shortcut.shiftKey && ( {getModifierSymbol('shift')} )} {formatShortcutKey(shortcut.key)}
))}
); }