lint fix wip

This commit is contained in:
Nicolas Cantu 2026-01-06 18:09:23 +01:00
parent e07a2cae53
commit 07b9d9d7bb
8 changed files with 104 additions and 42 deletions

View File

@ -11,6 +11,8 @@ interface PublicKeys {
} }
export function KeyManagementManager(): React.ReactElement { export function KeyManagementManager(): React.ReactElement {
console.log('[KeyManagementManager] Component rendered')
const [publicKeys, setPublicKeys] = useState<PublicKeys | null>(null) const [publicKeys, setPublicKeys] = useState<PublicKeys | null>(null)
const [accountExists, setAccountExists] = useState(false) const [accountExists, setAccountExists] = useState(false)
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
@ -253,7 +255,10 @@ export function KeyManagementManager(): React.ReactElement {
)} )}
{/* Sync Progress Bar - Always show if connected, even if publicKeys not loaded yet */} {/* Sync Progress Bar - Always show if connected, even if publicKeys not loaded yet */}
<SyncProgressBar /> {(() => {
console.log('[KeyManagementManager] Rendering SyncProgressBar')
return <SyncProgressBar />
})()}
{!publicKeys && !accountExists && ( {!publicKeys && !accountExists && (
<div className="bg-yellow-900/20 border border-yellow-400/50 rounded-lg p-4 mb-6"> <div className="bg-yellow-900/20 border border-yellow-400/50 rounded-lg p-4 mb-6">

View File

@ -7,6 +7,8 @@ import { objectCache } from '@/lib/objectCache'
import { t } from '@/lib/i18n' import { t } from '@/lib/i18n'
export function SyncProgressBar(): React.ReactElement | null { export function SyncProgressBar(): React.ReactElement | null {
console.log('[SyncProgressBar] Component function called')
const [syncProgress, setSyncProgress] = useState<SyncProgress | null>(null) const [syncProgress, setSyncProgress] = useState<SyncProgress | null>(null)
const [isSyncing, setIsSyncing] = useState(false) const [isSyncing, setIsSyncing] = useState(false)
const [lastSyncDate, setLastSyncDate] = useState<number | null>(null) const [lastSyncDate, setLastSyncDate] = useState<number | null>(null)

View File

@ -38,24 +38,24 @@ function WordInputWithAutocomplete({
} }
}, [value]) }, [value])
const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => { const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
const newValue = e.target.value.trim().toLowerCase() const newValue = event.target.value.trim().toLowerCase()
onChange(newValue) onChange(newValue)
} }
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => { const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>): void => {
if (e.key === 'ArrowDown') { if (event.key === 'ArrowDown') {
e.preventDefault() event.preventDefault()
setSelectedIndex((prev) => (prev < suggestions.length - 1 ? prev + 1 : prev)) setSelectedIndex((prev) => (prev < suggestions.length - 1 ? prev + 1 : prev))
} else if (e.key === 'ArrowUp') { } else if (event.key === 'ArrowUp') {
e.preventDefault() event.preventDefault()
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1)) setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1))
} else if (e.key === 'Enter' && selectedIndex >= 0 && suggestions[selectedIndex]) { } else if (event.key === 'Enter' && selectedIndex >= 0 && suggestions[selectedIndex]) {
e.preventDefault() event.preventDefault()
onChange(suggestions[selectedIndex] ?? '') onChange(suggestions[selectedIndex] ?? '')
setShowSuggestions(false) setShowSuggestions(false)
inputRef.current?.blur() inputRef.current?.blur()
} else if (e.key === 'Escape') { } else if (event.key === 'Escape') {
setShowSuggestions(false) setShowSuggestions(false)
inputRef.current?.blur() inputRef.current?.blur()
} }
@ -244,8 +244,8 @@ export function UnlockAccountModal({ onSuccess, onClose }: UnlockAccountModalPro
await nostrAuthService.unlockAccount(words) await nostrAuthService.unlockAccount(words)
onSuccess() onSuccess()
onClose() onClose()
} catch (e) { } catch (unlockError) {
setError(e instanceof Error ? e.message : 'Échec du déverrouillage. Vérifiez vos mots-clés.') setError(unlockError instanceof Error ? unlockError.message : 'Échec du déverrouillage. Vérifiez vos mots-clés.')
} finally { } finally {
setLoading(false) setLoading(false)
} }

View File

@ -90,8 +90,8 @@ export class AlbyService {
amount: request.amount, amount: request.amount,
expiresAt: Math.floor(Date.now() / 1000) + (request.expiry ?? 3600), expiresAt: Math.floor(Date.now() / 1000) + (request.expiry ?? 3600),
} }
} catch (error) { } catch (invoiceError) {
const err = error instanceof Error ? error : new Error(String(error)) const err = invoiceError instanceof Error ? invoiceError : new Error(String(invoiceError))
console.error('Alby createInvoice error:', err) console.error('Alby createInvoice error:', err)
throw new Error(`Failed to create invoice: ${err.message}`) throw new Error(`Failed to create invoice: ${err.message}`)
} }
@ -117,8 +117,8 @@ export class AlbyService {
try { try {
const response = await webln.sendPayment(invoice) const response = await webln.sendPayment(invoice)
return { preimage: response.preimage } return { preimage: response.preimage }
} catch (error) { } catch (paymentError) {
const err = error instanceof Error ? error : new Error(String(error)) const err = paymentError instanceof Error ? paymentError : new Error(String(paymentError))
console.error('Alby sendPayment error:', err) console.error('Alby sendPayment error:', err)
throw new Error(`Failed to send payment: ${err.message}`) throw new Error(`Failed to send payment: ${err.message}`)
} }

View File

@ -86,13 +86,13 @@ export async function getPurchaseById(purchaseId: string, timeoutMs: number = 50
} }
sub.on('event', async (event: Event): Promise<void> => { sub.on('event', async (event: Event): Promise<void> => {
const parsed = await parsePurchaseFromEvent(event) const purchaseParsed = await parsePurchaseFromEvent(event)
if (parsed?.id === purchaseId) { if (purchaseParsed?.id === purchaseId) {
// Cache the parsed purchase // Cache the parsed purchase
if (parsed.hash) { if (purchaseParsed.hash) {
await objectCache.set('purchase', parsed.hash, event, parsed, 0, false, parsed.index) await objectCache.set('purchase', purchaseParsed.hash, event, purchaseParsed, 0, false, purchaseParsed.index)
} }
done(parsed) done(purchaseParsed)
} }
}) })
@ -128,13 +128,13 @@ export function getPurchasesForArticle(articleId: string, timeoutMs: number = 50
} }
sub.on('event', async (event: Event): Promise<void> => { sub.on('event', async (event: Event): Promise<void> => {
const parsed = await parsePurchaseFromEvent(event) const purchaseParsed = await parsePurchaseFromEvent(event)
if (parsed?.articleId === articleId) { if (purchaseParsed?.articleId === articleId) {
// Cache the parsed purchase // Cache the parsed purchase
if (parsed.hash) { if (purchaseParsed.hash) {
await objectCache.set('purchase', parsed.hash, event, parsed, 0, false, parsed.index) await objectCache.set('purchase', purchaseParsed.hash, event, purchaseParsed, 0, false, purchaseParsed.index)
} }
results.push(parsed) results.push(purchaseParsed)
} }
}) })

View File

@ -93,13 +93,13 @@ export async function getReviewTipById(reviewTipId: string, timeoutMs: number =
} }
sub.on('event', async (event: Event): Promise<void> => { sub.on('event', async (event: Event): Promise<void> => {
const parsed = await parseReviewTipFromEvent(event) const reviewTipParsed = await parseReviewTipFromEvent(event)
if (parsed?.id === reviewTipId) { if (reviewTipParsed?.id === reviewTipId) {
// Cache the parsed review tip // Cache the parsed review tip
if (parsed.hash) { if (reviewTipParsed.hash) {
await objectCache.set('review_tip', parsed.hash, event, parsed, 0, false, parsed.index) await objectCache.set('review_tip', reviewTipParsed.hash, event, reviewTipParsed, 0, false, reviewTipParsed.index ?? 0)
} }
done(parsed) done(reviewTipParsed)
} }
}) })

View File

@ -93,13 +93,13 @@ export async function getSponsoringById(sponsoringId: string, timeoutMs: number
} }
sub.on('event', async (event: Event) => { sub.on('event', async (event: Event) => {
const parsed = await parseSponsoringFromEvent(event) const sponsoringParsed = await parseSponsoringFromEvent(event)
if (parsed?.id === sponsoringId) { if (sponsoringParsed?.id === sponsoringId) {
// Cache the parsed sponsoring // Cache the parsed sponsoring
if (parsed.hash) { if (sponsoringParsed.hash) {
await objectCache.set('sponsoring', parsed.hash, event, parsed, 0, false, parsed.index) await objectCache.set('sponsoring', sponsoringParsed.hash, event, sponsoringParsed, 0, false, sponsoringParsed.index ?? 0)
} }
done(parsed) done(sponsoringParsed)
} }
}) })
@ -135,13 +135,13 @@ export function getSponsoringByAuthor(authorPubkey: string, timeoutMs: number =
} }
sub.on('event', async (event: Event): Promise<void> => { sub.on('event', async (event: Event): Promise<void> => {
const parsed = await parseSponsoringFromEvent(event) const sponsoringParsed = await parseSponsoringFromEvent(event)
if (parsed?.authorPubkey === authorPubkey) { if (sponsoringParsed?.authorPubkey === authorPubkey) {
// Cache the parsed sponsoring // Cache the parsed sponsoring
if (parsed.hash) { if (sponsoringParsed.hash) {
await objectCache.set('sponsoring', parsed.hash, event, parsed, 0, false, parsed.index) await objectCache.set('sponsoring', sponsoringParsed.hash, event, sponsoringParsed, 0, false, sponsoringParsed.index ?? 0)
} }
results.push(parsed) results.push(sponsoringParsed)
} }
}) })

View File

@ -3,6 +3,9 @@ import type { AppProps } from 'next/app'
import { useI18n } from '@/hooks/useI18n' import { useI18n } from '@/hooks/useI18n'
import React from 'react' import React from 'react'
import { platformSyncService } from '@/lib/platformSync' import { platformSyncService } from '@/lib/platformSync'
import { nostrAuthService } from '@/lib/nostrAuth'
import { syncUserContentToCache } from '@/lib/userContentSync'
import { getLastSyncDate, getCurrentTimestamp } from '@/lib/syncStorage'
function I18nProvider({ children }: { children: React.ReactNode }): React.ReactElement { function I18nProvider({ children }: { children: React.ReactNode }): React.ReactElement {
// Get saved locale from localStorage or default to French // Get saved locale from localStorage or default to French
@ -64,6 +67,58 @@ export default function App({ Component, pageProps }: AppProps): React.ReactElem
} }
}, []) }, [])
// Start user content sync on app mount if connected
React.useEffect(() => {
let syncInProgress = false
const startUserSync = async (): Promise<void> => {
if (syncInProgress) {
return
}
const state = nostrAuthService.getState()
if (!state.connected || !state.pubkey) {
return
}
// Check if already recently synced (within last hour)
const storedLastSyncDate = await getLastSyncDate()
const currentTimestamp = getCurrentTimestamp()
const isRecentlySynced = storedLastSyncDate >= currentTimestamp - 3600
if (isRecentlySynced) {
console.log('[App] User content already synced recently, skipping')
return
}
syncInProgress = true
console.log('[App] Starting user content sync...')
try {
await syncUserContentToCache(state.pubkey)
console.log('[App] User content sync completed')
} catch (error) {
console.error('[App] Error during user content sync:', error)
} finally {
syncInProgress = false
}
}
// Try to start sync immediately
void startUserSync()
// Also listen to connection changes to sync when user connects
const unsubscribe = nostrAuthService.subscribe((state) => {
if (state.connected && state.pubkey && !syncInProgress) {
void startUserSync()
}
})
return () => {
unsubscribe()
}
}, [])
return ( return (
<I18nProvider> <I18nProvider>
<Component {...pageProps} /> <Component {...pageProps} />