**Motivations:** - total_sponsoring should be calculated from cache, not stored in tags - Author searches should use cache first, not query Nostr directly - All elements should be read/written from/to database - Background sync should scan all notes with service='zapwall.fr' tag and update cache - Sync should run at startup and resume on each page navigation **Root causes:** - total_sponsoring was stored in tags which required updates on every sponsoring payment - Author queries were querying Nostr directly instead of using cache - No background sync service to keep cache up to date with new notes **Correctifs:** - Removed totalSponsoring from AuthorTags interface and buildAuthorTags - Modified getAuthorSponsoring to calculate from cache (sponsoring queries) instead of tags - Modified parsePresentationEvent to set totalSponsoring to 0 (calculated on demand from cache) - Modified fetchAuthorByHashId and fetchAuthorPresentationFromPool to use cache first and calculate totalSponsoring from cache - Created platformSyncService that scans all notes with service='zapwall.fr' tag and caches them - Modified _app.tsx to start continuous sync on mount and resume on page navigation - All author presentations now calculate totalSponsoring from cache when loaded **Evolutions:** - Cache-first architecture: all queries check cache before querying Nostr - Background sync service keeps cache up to date automatically - totalSponsoring is always calculated from actual sponsoring data in cache - Better performance: cache queries are faster than Nostr queries - Non-blocking sync: background sync doesn't block UI **Pages affectées:** - lib/nostrTagSystemTypes.ts - lib/nostrTagSystemBuild.ts - lib/articlePublisherHelpersPresentation.ts - lib/sponsoring.ts - lib/authorQueries.ts - lib/platformSync.ts (new) - pages/_app.tsx
73 lines
2.2 KiB
TypeScript
73 lines
2.2 KiB
TypeScript
import '@/styles/globals.css'
|
|
import type { AppProps } from 'next/app'
|
|
import { useI18n } from '@/hooks/useI18n'
|
|
import React from 'react'
|
|
import { platformSyncService } from '@/lib/platformSync'
|
|
|
|
function I18nProvider({ children }: { children: React.ReactNode }) {
|
|
// Get saved locale from localStorage or default to French
|
|
const getInitialLocale = (): 'fr' | 'en' => {
|
|
if (typeof window === 'undefined') {
|
|
return 'fr'
|
|
}
|
|
try {
|
|
const savedLocale = 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 <div className="min-h-screen bg-cyber-darker flex items-center justify-center text-neon-cyan">Loading...</div>
|
|
}
|
|
|
|
return <>{children}</>
|
|
}
|
|
|
|
export default function App({ Component, pageProps }: AppProps): React.ReactElement {
|
|
// Start platform sync on app mount and resume on each page navigation
|
|
React.useEffect(() => {
|
|
// Start continuous sync (runs periodically in background)
|
|
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)
|
|
platformSyncService.stopSync()
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<I18nProvider>
|
|
<Component {...pageProps} />
|
|
</I18nProvider>
|
|
)
|
|
}
|