story-research-zapwall/lib/settingsCache.ts
Nicolas Cantu cc49c9d7c1 Add language preference selector in settings
**Motivations:**
- Allow users to set their preferred language (fr/en) in the settings page
- Load language preference from localStorage at startup to configure the application locale

**Root causes:**
- Language preference was only available in the header via LanguageSelector component
- Language preference was stored in IndexedDB instead of localStorage
- No centralized language settings management in the settings page

**Correctifs:**
- Created LanguageSettingsManager component for settings page
- Migrated language storage from IndexedDB to localStorage for consistency
- Updated _app.tsx to load locale from localStorage synchronously at startup
- Updated useI18n hook to use localStorage instead of IndexedDB
- Updated LanguageSelector component to use localStorage instead of IndexedDB

**Evolutions:**
- Added language preference section in settings page (displayed first)
- Language preference is now loaded at application startup from localStorage
- Added translations for language settings (settings.language.*)

**Pages affectées:**
- components/LanguageSettingsManager.tsx (new)
- pages/settings.tsx
- pages/_app.tsx
- hooks/useI18n.ts
- components/LanguageSelector.tsx
- locales/fr.txt
- locales/en.txt
2026-01-06 14:57:38 +01:00

130 lines
3.6 KiB
TypeScript

/**
* IndexedDB cache for application settings (excluding keys)
* Stores settings and last sync date for background synchronization
*/
const DB_NAME = 'nostr_paywall_settings'
const DB_VERSION = 1
const STORE_NAME = 'settings'
export interface SettingsData {
// Settings excluding keys (relays, NIP-95 APIs, etc.)
relays?: Array<{ id: string; url: string; enabled: boolean; priority: number; createdAt: number }>
nip95Apis?: Array<{ id: string; url: string; enabled: boolean; priority: number; createdAt: number }>
platformLightningAddress?: string
// Last sync date (Unix timestamp) for background synchronization
lastSyncDate?: number
// Metadata
updatedAt: number
}
class SettingsCacheService {
private db: IDBDatabase | null = null
private async initDB(): Promise<IDBDatabase> {
if (this.db) {
return this.db
}
return new Promise((resolve, reject) => {
if (typeof window === 'undefined' || !window.indexedDB) {
reject(new Error('IndexedDB is not available'))
return
}
const request = indexedDB.open(DB_NAME, DB_VERSION)
request.onerror = () => {
reject(new Error(`Failed to open IndexedDB: ${request.error}`))
}
request.onsuccess = () => {
this.db = request.result
resolve(this.db)
}
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result
if (!db.objectStoreNames.contains(STORE_NAME)) {
const store = db.createObjectStore(STORE_NAME, { keyPath: 'key' })
store.createIndex('updatedAt', 'updatedAt', { unique: false })
}
}
})
}
/**
* Get settings (excluding keys) and last sync date
*/
async getSettings(): Promise<SettingsData | null> {
try {
const db = await this.initDB()
const transaction = db.transaction([STORE_NAME], 'readonly')
const store = transaction.objectStore(STORE_NAME)
return new Promise((resolve, reject) => {
const request = store.get('settings')
request.onsuccess = () => {
const result = request.result as { key: string; value: SettingsData } | undefined
resolve(result?.value ?? null)
}
request.onerror = () => reject(request.error)
})
} catch (error) {
console.error('Error retrieving settings from cache:', error)
return null
}
}
/**
* Save settings (excluding keys) and last sync date
*/
async saveSettings(settings: SettingsData): Promise<void> {
try {
const db = await this.initDB()
const transaction = db.transaction([STORE_NAME], 'readwrite')
const store = transaction.objectStore(STORE_NAME)
await new Promise<void>((resolve, reject) => {
const request = store.put({
key: 'settings',
value: {
...settings,
updatedAt: Date.now(),
},
})
request.onsuccess = () => resolve()
request.onerror = () => reject(request.error)
})
} catch (error) {
console.error('Error saving settings to cache:', error)
throw error
}
}
/**
* Update last sync date
*/
async updateLastSyncDate(timestamp: number): Promise<void> {
const settings = await this.getSettings()
await this.saveSettings({
...settings,
lastSyncDate: timestamp,
updatedAt: Date.now(),
} as SettingsData)
}
/**
* Get last sync date
*/
async getLastSyncDate(): Promise<number | null> {
const settings = await this.getSettings()
return settings?.lastSyncDate ?? null
}
}
export const settingsCache = new SettingsCacheService()