import '@/styles/globals.css' import type { AppProps } from 'next/app' import { useI18n } from '@/hooks/useI18n' import React from 'react' import { platformSyncService } from '@/lib/platformSync' import { nostrAuthService } from '@/lib/nostrAuth' import { syncUserContentToCache } from '@/lib/userContentSync' import { syncProgressManager } from '@/lib/syncProgressManager' import { relaySessionManager } from '@/lib/relaySessionManager' import { publishWorker } from '@/lib/publishWorker' import { swSyncHandler } from '@/lib/swSyncHandler' import { swClient } from '@/lib/swClient' function I18nProvider({ children }: { children: React.ReactNode }): React.ReactElement { // Get saved locale from localStorage or default to French const getInitialLocale = (): 'fr' | 'en' => { if (typeof window === 'undefined') { return 'fr' } try { const savedLocale = window.localStorage.getItem('zapwall-locale') as 'fr' | 'en' | null if (savedLocale === 'fr' || savedLocale === 'en') { return savedLocale } } catch { // Fallback to browser locale detection } // Try to detect browser locale const browserLocale = navigator.language.split('-')[0] return browserLocale === 'en' ? 'en' : 'fr' } const [initialLocale, setInitialLocale] = React.useState<'fr' | 'en'>('fr') const [localeLoaded, setLocaleLoaded] = React.useState(false) React.useEffect(() => { const locale = getInitialLocale() setInitialLocale(locale) setLocaleLoaded(true) }, []) const { loaded } = useI18n(initialLocale) if (!localeLoaded || !loaded) { return
Loading...
} return children as React.ReactElement } export default function App({ Component, pageProps }: AppProps): React.ReactElement { // Initialize relay session manager on app mount (reset all relays to active) React.useEffect(() => { void relaySessionManager.initialize() }, []) // Initialize Service Worker and sync handler React.useEffect(() => { if (typeof window !== 'undefined') { void swSyncHandler.initialize() } }, []) // Start publish worker on app mount to republish unpublished objects React.useEffect(() => { void publishWorker.start() return () => { void publishWorker.stop() } }, []) // Start platform sync on app mount and resume on each page navigation React.useEffect(() => { // Start continuous sync (runs periodically in background, uses Service Worker if available) void platformSyncService.startContinuousSync() // Also trigger a sync on each page navigation const handleRouteChange = (): void => { if (!platformSyncService.isSyncing()) { void platformSyncService.startSync() } } // Listen to route changes const router = require('next/router').default router.events?.on('routeChangeComplete', handleRouteChange) return () => { router.events?.off('routeChangeComplete', handleRouteChange) void platformSyncService.stopSync() } }, []) // Start user content sync on app mount and on each page navigation if connected React.useEffect(() => { let syncInProgress = false const startUserSync = async (): Promise => { if (syncInProgress) { console.warn('[App] Sync already in progress, skipping') return } const state = nostrAuthService.getState() console.warn('[App] Checking connection state:', { connected: state.connected, hasPubkey: Boolean(state.pubkey) }) if (!state.connected || !state.pubkey) { console.warn('[App] Not connected or no pubkey, skipping sync') return } syncInProgress = true console.warn('[App] Starting user content sync...') // Try to use Service Worker for background sync try { const isReady = await swClient.isReady() if (isReady) { console.warn('[App] Using Service Worker for user content sync') await swClient.startUserSync(state.pubkey) // Still sync immediately in main thread for UI feedback } } catch (error) { console.warn('[App] Service Worker not available, using direct sync:', error) } try { await syncUserContentToCache(state.pubkey, (progress) => { syncProgressManager.setProgress(progress) if (progress.completed) { syncProgressManager.setProgress(null) } }) console.warn('[App] User content sync completed') syncProgressManager.setProgress(null) } catch (error) { console.error('[App] Error during user content sync:', error) syncProgressManager.setProgress(null) } finally { syncInProgress = false } } // Try to start sync immediately void startUserSync() // Also listen to connection changes and route changes to sync when user connects or navigates const router = require('next/router').default const handleRouteChange = (): void => { if (!syncInProgress) { void startUserSync() } } router.events?.on('routeChangeComplete', handleRouteChange) const unsubscribe = nostrAuthService.subscribe((state) => { if (state.connected && state.pubkey && !syncInProgress) { void startUserSync() } }) return () => { router.events?.off('routeChangeComplete', handleRouteChange) unsubscribe() } }, []) return ( ) }