import { create } from 'zustand'; import { persist } from 'zustand/middleware'; export type FontSize = 'small' | 'medium' | 'large'; export type ListDensity = 'compact' | 'regular' | 'comfortable'; export type DeleteAction = 'trash' | 'permanent'; export type ReplyMode = 'reply' | 'replyAll'; export type DateFormat = 'regional' | 'iso' | 'custom'; export type TimeFormat = '12h' | '24h'; export type FirstDayOfWeek = 0 | 1; // 0 = Sunday, 1 = Monday export type ExternalContentPolicy = 'ask' | 'block' | 'allow'; interface SettingsState { // Appearance fontSize: FontSize; listDensity: ListDensity; animationsEnabled: boolean; // Language & Region dateFormat: DateFormat; timeFormat: TimeFormat; firstDayOfWeek: FirstDayOfWeek; // Email Behavior markAsReadDelay: number; // milliseconds (0 = instant, -1 = never) deleteAction: DeleteAction; showPreview: boolean; emailsPerPage: number; externalContentPolicy: ExternalContentPolicy; // Composer autoSaveDraftInterval: number; // milliseconds sendConfirmation: boolean; defaultReplyMode: ReplyMode; // Privacy & Security sessionTimeout: number; // minutes (0 = never) // Advanced debugMode: boolean; // Actions updateSetting: ( key: K, value: SettingsState[K] ) => void; resetToDefaults: () => void; exportSettings: () => string; importSettings: (json: string) => boolean; } const DEFAULT_SETTINGS = { // Appearance fontSize: 'medium' as FontSize, listDensity: 'regular' as ListDensity, animationsEnabled: true, // Language & Region dateFormat: 'regional' as DateFormat, timeFormat: '24h' as TimeFormat, firstDayOfWeek: 1 as FirstDayOfWeek, // Monday // Email Behavior markAsReadDelay: 0, // Instant deleteAction: 'trash' as DeleteAction, showPreview: true, emailsPerPage: 50, externalContentPolicy: 'ask' as ExternalContentPolicy, // Composer autoSaveDraftInterval: 60000, // 1 minute sendConfirmation: false, defaultReplyMode: 'reply' as ReplyMode, // Privacy & Security sessionTimeout: 0, // Never // Advanced debugMode: false, }; export const useSettingsStore = create()( persist( (set, get) => ({ ...DEFAULT_SETTINGS, updateSetting: (key, value) => { set({ [key]: value }); // Apply font size to document root if (key === 'fontSize') { applyFontSize(value as FontSize); } // Apply list density to document root if (key === 'listDensity') { applyListDensity(value as ListDensity); } // Apply animations to document root if (key === 'animationsEnabled') { applyAnimations(value as boolean); } }, resetToDefaults: () => { set(DEFAULT_SETTINGS); applyFontSize(DEFAULT_SETTINGS.fontSize); applyListDensity(DEFAULT_SETTINGS.listDensity); applyAnimations(DEFAULT_SETTINGS.animationsEnabled); }, exportSettings: () => { const state = get(); const settings = { fontSize: state.fontSize, listDensity: state.listDensity, animationsEnabled: state.animationsEnabled, dateFormat: state.dateFormat, timeFormat: state.timeFormat, firstDayOfWeek: state.firstDayOfWeek, markAsReadDelay: state.markAsReadDelay, deleteAction: state.deleteAction, showPreview: state.showPreview, emailsPerPage: state.emailsPerPage, externalContentPolicy: state.externalContentPolicy, autoSaveDraftInterval: state.autoSaveDraftInterval, sendConfirmation: state.sendConfirmation, defaultReplyMode: state.defaultReplyMode, sessionTimeout: state.sessionTimeout, debugMode: state.debugMode, }; return JSON.stringify(settings, null, 2); }, importSettings: (json: string) => { try { const settings = JSON.parse(json); // Validate settings if (typeof settings !== 'object' || settings === null) { return false; } // Apply settings Object.keys(settings).forEach((key) => { if (key in DEFAULT_SETTINGS) { set({ [key]: settings[key] }); } }); // Apply visual settings applyFontSize(get().fontSize); applyListDensity(get().listDensity); applyAnimations(get().animationsEnabled); return true; } catch (error) { console.error('Failed to import settings:', error); return false; } }, }), { name: 'settings-storage', version: 1, } ) ); // Helper functions to apply settings to DOM function applyFontSize(size: FontSize) { if (typeof document === 'undefined') return; const root = document.documentElement; const sizeMap = { small: '14px', medium: '16px', large: '18px', }; root.style.setProperty('--font-size-base', sizeMap[size]); } function applyListDensity(density: ListDensity) { if (typeof document === 'undefined') return; const root = document.documentElement; const densityMap = { compact: '32px', regular: '48px', comfortable: '64px', }; root.style.setProperty('--list-item-height', densityMap[density]); } function applyAnimations(enabled: boolean) { if (typeof document === 'undefined') return; const root = document.documentElement; if (enabled) { root.style.removeProperty('--transition-duration'); } else { root.style.setProperty('--transition-duration', '0s'); } } // Initialize settings on load if (typeof window !== 'undefined') { const store = useSettingsStore.getState(); applyFontSize(store.fontSize); applyListDensity(store.listDensity); applyAnimations(store.animationsEnabled); }