/** * Settings view — language, font, and display preferences. */ import { getTranslations, type LanguageCode } from '../core/i18n'; const LANGUAGES = [ { code: 'en', name: 'English', local: 'English' }, { code: 'ru', name: 'Russian', local: 'Русский' }, { code: 'cu', name: 'Church Slavonic', local: 'Церковнославянский' }, ]; const CU_FONTS = [ { id: '', name: 'System Default' }, { id: 'Ponomar', name: 'Ponomar' }, { id: 'Fedorovsk', name: 'Fedorovsk' }, { id: 'Menaion', name: 'Menaion' }, { id: 'Monomakh', name: 'Monomakh' }, { id: 'Triodion', name: 'Triodion' }, { id: 'Vilnius', name: 'Vilnius' }, { id: 'Voskresensky', name: 'Voskresensky' }, ]; const SETTINGS_KEY = 'ponomar-settings'; interface Settings { language: string; cuFont: string; fontSize: number; defaultBibleVersion: string; showVerseNumbers: boolean; verseNewLine: boolean; calendarType: 'julian' | 'gregorian'; serviceRole: 'priest' | 'reader' | 'auto'; } const DEFAULT_SETTINGS: Settings = { language: 'en', cuFont: 'Ponomar', fontSize: 16, defaultBibleVersion: 'kjv', showVerseNumbers: true, verseNewLine: false, calendarType: 'julian', serviceRole: 'priest', }; function defaultBibleForLanguage(lang: string): string { const map: Record = { en: 'kjv', ru: 'synod', cu: 'elis' }; return map[lang] || 'kjv'; } function detectBrowserLanguage(): LanguageCode { const lang = navigator.language || (navigator as any).userLanguage || ''; if (lang.startsWith('ru')) return 'ru'; if (lang.startsWith('cu')) return 'cu'; return 'en'; } function loadSettings(): Settings { try { const stored = localStorage.getItem(SETTINGS_KEY); if (stored) { const parsed = JSON.parse(stored); // Migrate old usePonomarFont to cuFont if (parsed.usePonomarFont !== undefined) { parsed.cuFont = parsed.usePonomarFont ? 'Ponomar' : ''; delete parsed.usePonomarFont; } return { ...DEFAULT_SETTINGS, ...parsed }; } } catch { /* ignore */ } return { ...DEFAULT_SETTINGS, language: detectBrowserLanguage(), defaultBibleVersion: defaultBibleForLanguage(detectBrowserLanguage()) }; } function saveSettings(settings: Settings) { localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings)); } function fontClass(fontName: string): string { if (!fontName) return 'font-system-slavonic'; const lower = fontName.toLowerCase(); const map: Record = { ponomar: 'font-ponomar', fedorovsk: 'font-fedrovsk', indiction: 'font-indiction', menaion: 'font-menaion', monomakh: 'font-monomakh', triodion: 'font-triodion', vilnius: 'font-vilnius', voskresensky: 'font-voskresensky', }; return map[lower] || 'font-slavonic'; } export { loadSettings, saveSettings, fontClass }; export type { Settings }; export class SettingsView { private container: HTMLElement; private settings: Settings; private onLanguageChange?: () => void; constructor(container: HTMLElement, onLanguageChange?: () => void) { this.container = container; this.settings = loadSettings(); this.onLanguageChange = onLanguageChange; } render() { const t = getTranslations(this.settings.language as LanguageCode); this.container.innerHTML = `

${t.settings.title}

${t.settings.fontSettings}

${t.settings.fontPreview}

Сохрани́ мѧ, гдⷭ҇и, ꙗ҆́кѡ на тѧ̀ ᲂу҆пова́хъ

${t.settings.calendarType}

${t.settings.bibleSettings}

${t.settings.about}

${t.settings.aboutText}

${t.settings.aboutLicense}

`; // Event listeners document.getElementById('language')?.addEventListener('change', (e) => { this.settings.language = (e.target as HTMLSelectElement).value; this.settings.defaultBibleVersion = defaultBibleForLanguage(this.settings.language); saveSettings(this.settings); const bibleSelect = document.getElementById('default-bible') as HTMLSelectElement | null; if (bibleSelect) bibleSelect.value = this.settings.defaultBibleVersion; this.onLanguageChange?.(); }); document.getElementById('cu-font')?.addEventListener('change', (e) => { this.settings.cuFont = (e.target as HTMLSelectElement).value; saveSettings(this.settings); this.updateFontPreview(); }); document.getElementById('font-size')?.addEventListener('input', (e) => { this.settings.fontSize = parseInt((e.target as HTMLInputElement).value, 10); document.getElementById('font-size-value')!.textContent = `${this.settings.fontSize}px`; document.documentElement.style.setProperty('--liturgical-font-size', this.settings.fontSize + 'px'); saveSettings(this.settings); }); document.getElementById('default-bible')?.addEventListener('change', (e) => { this.settings.defaultBibleVersion = (e.target as HTMLSelectElement).value; saveSettings(this.settings); }); document.getElementById('show-verses')?.addEventListener('change', (e) => { this.settings.showVerseNumbers = (e.target as HTMLInputElement).checked; saveSettings(this.settings); }); document.getElementById('verse-newline')?.addEventListener('change', (e) => { this.settings.verseNewLine = (e.target as HTMLInputElement).checked; saveSettings(this.settings); }); document.querySelectorAll('input[name="calendar-type"]').forEach(el => { el.addEventListener('change', (e) => { this.settings.calendarType = (e.target as HTMLInputElement).value as 'julian' | 'gregorian'; saveSettings(this.settings); }); }); document.getElementById('install-pwa')?.addEventListener('click', async () => { const prompt = (window as any).__deferredPrompt; if (prompt) { prompt.prompt(); await prompt.userChoice; (window as any).__deferredPrompt = null; document.getElementById('install-pwa')?.remove(); } }); this.updateFontPreview(); } private updateFontPreview() { const preview = document.getElementById('font-preview'); if (preview) { preview.className = `${fontClass(this.settings.cuFont)} text-lg`; } } }