/** * Settings Panel Module * Handles user settings UI and persistence */ const Settings = { // Current settings state current: {}, // DOM elements elements: {}, /** * Initialize the settings module */ init() { this.cacheElements(); this.bindEvents(); }, /** * Cache DOM element references */ cacheElements() { this.elements = { panel: document.getElementById('settings-panel'), overlay: document.getElementById('overlay'), btnSettings: document.getElementById('btn-settings'), btnClose: document.getElementById('btn-close-settings'), btnSave: document.getElementById('btn-save-settings'), btnReset: document.getElementById('btn-reset-settings'), // Text settings fontFamily: document.getElementById('font-family'), fontSize: document.getElementById('font-size'), fontSizeValue: document.getElementById('font-size-value'), fontWeight: document.getElementById('font-weight'), textColor: document.getElementById('text-color'), textAlign: document.getElementById('text-align'), // Background settings backgroundColor: document.getElementById('background-color'), backgroundOpacity: document.getElementById('background-opacity'), opacityValue: document.getElementById('opacity-value'), borderRadius: document.getElementById('border-radius'), radiusValue: document.getElementById('radius-value'), padding: document.getElementById('padding'), paddingValue: document.getElementById('padding-value'), // Behavior settings maxWords: document.getElementById('max-words'), maxWordsValue: document.getElementById('max-words-value'), // Caption display captionContainer: document.getElementById('caption-container'), }; }, /** * Bind event listeners */ bindEvents() { // Panel open/close this.elements.btnSettings.addEventListener('click', () => this.openPanel()); this.elements.btnClose.addEventListener('click', () => this.closePanel()); this.elements.overlay.addEventListener('click', () => this.closePanel()); // Save/Reset this.elements.btnSave.addEventListener('click', () => this.saveSettings()); this.elements.btnReset.addEventListener('click', () => this.resetSettings()); // Live preview on input change const inputs = [ 'fontFamily', 'fontSize', 'fontWeight', 'textColor', 'textAlign', 'backgroundColor', 'backgroundOpacity', 'borderRadius', 'padding', 'maxWords' ]; inputs.forEach(name => { const element = this.elements[name]; if (element) { element.addEventListener('input', () => this.updatePreview()); } }); // Update value displays for range inputs this.elements.fontSize.addEventListener('input', (e) => { this.elements.fontSizeValue.textContent = e.target.value; }); this.elements.backgroundOpacity.addEventListener('input', (e) => { this.elements.opacityValue.textContent = e.target.value; }); this.elements.borderRadius.addEventListener('input', (e) => { this.elements.radiusValue.textContent = e.target.value; }); this.elements.padding.addEventListener('input', (e) => { this.elements.paddingValue.textContent = e.target.value; }); this.elements.maxWords.addEventListener('input', (e) => { this.elements.maxWordsValue.textContent = e.target.value; }); }, /** * Open settings panel */ openPanel() { this.elements.panel.classList.remove('hidden'); this.elements.overlay.classList.remove('hidden'); }, /** * Close settings panel */ closePanel() { this.elements.panel.classList.add('hidden'); this.elements.overlay.classList.add('hidden'); }, /** * Apply settings to the UI */ applySettings(settings) { this.current = settings; // Update form values this.elements.fontFamily.value = settings.font_family; this.elements.fontSize.value = settings.font_size; this.elements.fontSizeValue.textContent = settings.font_size; this.elements.fontWeight.value = settings.font_weight; this.elements.textColor.value = settings.text_color; this.elements.textAlign.value = settings.text_align; this.elements.backgroundColor.value = settings.background_color; this.elements.backgroundOpacity.value = Math.round(settings.background_opacity * 100); this.elements.opacityValue.textContent = Math.round(settings.background_opacity * 100); this.elements.borderRadius.value = settings.border_radius; this.elements.radiusValue.textContent = settings.border_radius; this.elements.padding.value = settings.padding; this.elements.paddingValue.textContent = settings.padding; this.elements.maxWords.value = settings.max_words || 30; this.elements.maxWordsValue.textContent = settings.max_words || 30; // Apply to caption container this.updatePreview(); }, /** * Update live preview of caption styling */ updatePreview() { const container = this.elements.captionContainer; const opacity = this.elements.backgroundOpacity.value / 100; // Parse background color and apply opacity const bgColor = this.elements.backgroundColor.value; const r = parseInt(bgColor.slice(1, 3), 16); const g = parseInt(bgColor.slice(3, 5), 16); const b = parseInt(bgColor.slice(5, 7), 16); container.style.fontFamily = this.elements.fontFamily.value; container.style.fontSize = `${this.elements.fontSize.value}px`; container.style.fontWeight = this.elements.fontWeight.value; container.style.color = this.elements.textColor.value; container.style.textAlign = this.elements.textAlign.value; container.style.backgroundColor = `rgba(${r}, ${g}, ${b}, ${opacity})`; container.style.borderRadius = `${this.elements.borderRadius.value}px`; container.style.padding = `${this.elements.padding.value}px`; // Store max words for caption management this.current.max_words = parseInt(this.elements.maxWords.value); }, /** * Get current form values as settings object */ getFormValues() { return { font_family: this.elements.fontFamily.value, font_size: parseInt(this.elements.fontSize.value), font_weight: this.elements.fontWeight.value, text_color: this.elements.textColor.value, text_align: this.elements.textAlign.value, background_color: this.elements.backgroundColor.value, background_opacity: this.elements.backgroundOpacity.value / 100, border_radius: parseInt(this.elements.borderRadius.value), padding: parseInt(this.elements.padding.value), max_words: parseInt(this.elements.maxWords.value), }; }, /** * Save settings to server */ async saveSettings() { const settings = this.getFormValues(); try { const response = await fetch('/api/settings', { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(settings), }); if (response.ok) { this.current = await response.json(); this.closePanel(); console.log('Settings saved'); } else { console.error('Failed to save settings'); } } catch (error) { console.error('Error saving settings:', error); } }, /** * Reset settings to defaults */ async resetSettings() { if (!confirm('Reset all settings to defaults?')) { return; } try { const response = await fetch('/api/settings/reset', { method: 'POST', }); if (response.ok) { const settings = await response.json(); this.applySettings(settings); console.log('Settings reset to defaults'); } else { console.error('Failed to reset settings'); } } catch (error) { console.error('Error resetting settings:', error); } }, /** * Fetch settings from server */ async fetchSettings() { try { const response = await fetch('/api/settings'); if (response.ok) { const settings = await response.json(); this.applySettings(settings); } } catch (error) { console.error('Error fetching settings:', error); } } };