import { EventEmitter } from '$lib/utils/EventEmitter'; import { get } from 'svelte/store'; import { accessibilitySettings, uiSettings } from '$lib/stores/mudStore'; export interface Settings { accessibility: { textToSpeech: boolean; highContrast: boolean; fontSize: number; lineSpacing: number; speechRate: number; speechPitch: number; speechVolume: number; interruptSpeechOnEnter: boolean; }; ui: { isDarkMode: boolean; showTimestamps: boolean; showSidebar: boolean; splitViewDirection: 'horizontal' | 'vertical'; inputHistorySize: number; outputBufferSize: number; ansiColor: boolean; font: string; debugGmcp: boolean; globalVolume: number; }; } export class SettingsManager extends EventEmitter { private settings: Settings; private readonly STORAGE_KEY = 'svelte-mud-settings'; constructor() { super(); // Initialize with default settings this.settings = { accessibility: { textToSpeech: false, highContrast: false, fontSize: 16, lineSpacing: 1.2, speechRate: 1, speechPitch: 1, speechVolume: 1, interruptSpeechOnEnter: true }, ui: { isDarkMode: true, showTimestamps: true, showSidebar: true, splitViewDirection: 'horizontal', inputHistorySize: 100, outputBufferSize: 1000, ansiColor: true, font: 'monospace', debugGmcp: false, globalVolume: 0.7 } }; // Load settings from storage this.loadSettings(); } /** * Load settings from localStorage */ private loadSettings(): void { if (typeof window === 'undefined') { return; // Skip during SSR } try { const storedSettings = localStorage.getItem(this.STORAGE_KEY); if (storedSettings) { const parsedSettings = JSON.parse(storedSettings); // Merge with defaults to ensure all properties exist this.settings = { accessibility: { ...this.settings.accessibility, ...parsedSettings.accessibility }, ui: { ...this.settings.ui, ...parsedSettings.ui } }; console.log('Loaded settings from localStorage:', this.settings); // Update Svelte stores with loaded settings accessibilitySettings.set(this.settings.accessibility); uiSettings.set(this.settings.ui); this.emit('settingsLoaded', this.settings); } else { console.log('No settings found in localStorage, using defaults'); // Update Svelte stores with default settings accessibilitySettings.set(this.settings.accessibility); uiSettings.set(this.settings.ui); } } catch (error) { console.error('Failed to load settings from localStorage:', error); } } /** * Save settings to localStorage */ public saveSettings(): void { if (typeof window === 'undefined') { return; // Skip during SSR } try { // Get current values from stores this.settings.accessibility = get(accessibilitySettings); this.settings.ui = get(uiSettings); localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.settings)); console.log('Saved settings to localStorage:', this.settings); this.emit('settingsSaved', this.settings); } catch (error) { console.error('Failed to save settings to localStorage:', error); } } /** * Update accessibility settings */ public updateAccessibilitySettings(newSettings: Partial): void { accessibilitySettings.update(current => { const updated = { ...current, ...newSettings }; this.settings.accessibility = updated; this.saveSettings(); return updated; }); this.emit('accessibilitySettingsUpdated', get(accessibilitySettings)); } /** * Update UI settings */ public updateUiSettings(newSettings: Partial): void { uiSettings.update(current => { const updated = { ...current, ...newSettings }; this.settings.ui = updated; this.saveSettings(); return updated; }); this.emit('uiSettingsUpdated', get(uiSettings)); } /** * Reset settings to defaults */ public resetSettings(): void { // Create default settings const defaultSettings: Settings = { accessibility: { textToSpeech: false, highContrast: false, fontSize: 16, lineSpacing: 1.2, speechRate: 1, speechPitch: 1, speechVolume: 1, interruptSpeechOnEnter: true }, ui: { isDarkMode: true, showTimestamps: true, showSidebar: true, splitViewDirection: 'horizontal', inputHistorySize: 100, outputBufferSize: 1000, ansiColor: true, font: 'monospace', debugGmcp: false, globalVolume: 0.7 } }; // Update stores accessibilitySettings.set(defaultSettings.accessibility); uiSettings.set(defaultSettings.ui); // Update internal settings and save this.settings = defaultSettings; this.saveSettings(); this.emit('settingsReset', defaultSettings); } /** * Import settings from a JSON string */ public importSettings(json: string): void { try { const imported = JSON.parse(json); if (typeof imported === 'object' && imported !== null) { // Create a valid settings object with defaults for missing properties const newSettings: Settings = { accessibility: { ...this.settings.accessibility, ...(imported.accessibility || {}) }, ui: { ...this.settings.ui, ...(imported.ui || {}) } }; // Update stores accessibilitySettings.set(newSettings.accessibility); uiSettings.set(newSettings.ui); // Update internal settings and save this.settings = newSettings; this.saveSettings(); this.emit('settingsImported', newSettings); } } catch (error) { console.error('Failed to import settings:', error); throw new Error('Failed to import settings. Invalid format.'); } } /** * Export settings to a JSON string */ public exportSettings(): string { // Get current values from stores this.settings.accessibility = get(accessibilitySettings); this.settings.ui = get(uiSettings); return JSON.stringify(this.settings, null, 2); } } // Create a singleton instance export const settingsManager = new SettingsManager();