lint fix wip
This commit is contained in:
parent
b7d65a55c7
commit
e97d2b32cc
@ -5,7 +5,7 @@ export function AuthorMnemonicIcons({ value, getMnemonicIcons }: { value: string
|
||||
return (
|
||||
<div className="flex items-center gap-1 flex-shrink-0">
|
||||
{getMnemonicIcons(value).map((icon, idx) => (
|
||||
<span key={idx} className="text-sm" title={`Mnemonic icon ${idx + 1}`}>
|
||||
<span key={`mnemonic-icon-${idx}-${icon}`} className="text-sm" title={`Mnemonic icon ${idx + 1}`}>
|
||||
{icon}
|
||||
</span>
|
||||
))}
|
||||
|
||||
@ -47,7 +47,7 @@ export function AuthorOption({
|
||||
<span className="flex-1 truncate text-cyber-accent">{displayName}</span>
|
||||
<div className="flex items-center gap-1 flex-shrink-0">
|
||||
{mnemonicIcons.map((icon, idx) => (
|
||||
<span key={idx} className="text-sm" title={`Mnemonic icon ${idx + 1}`}>
|
||||
<span key={`mnemonic-icon-${idx}-${icon}`} className="text-sm" title={`Mnemonic icon ${idx + 1}`}>
|
||||
{icon}
|
||||
</span>
|
||||
))}
|
||||
|
||||
@ -224,11 +224,15 @@ function PresentationForm({
|
||||
disabled={loading ?? deleting}
|
||||
className="w-full px-4 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ?? deleting
|
||||
? t('publish.publishing')
|
||||
: hasExistingPresentation === true
|
||||
? t('presentation.update.button')
|
||||
: t('publish.button')}
|
||||
{(() => {
|
||||
if (loading ?? deleting) {
|
||||
return t('publish.publishing')
|
||||
}
|
||||
if (hasExistingPresentation === true) {
|
||||
return t('presentation.update.button')
|
||||
}
|
||||
return t('publish.button')
|
||||
})()}
|
||||
</button>
|
||||
</div>
|
||||
{hasExistingPresentation && (
|
||||
@ -279,7 +283,7 @@ function useAuthorPresentationState(pubkey: string | null, existingAuthorName?:
|
||||
if (existingAuthorName && existingAuthorName !== draft.authorName && !existingPresentation) {
|
||||
setDraft((prev) => ({ ...prev, authorName: existingAuthorName }))
|
||||
}
|
||||
}, [existingAuthorName, existingPresentation])
|
||||
}, [existingAuthorName, existingPresentation, draft.authorName])
|
||||
|
||||
const handleSubmit = useCallback(
|
||||
async (e: FormEvent<HTMLFormElement>) => {
|
||||
|
||||
@ -25,7 +25,7 @@ export function RecoveryPhraseDisplay({
|
||||
<div className="grid grid-cols-2 gap-4 mb-4">
|
||||
{recoveryPhrase.map((word, index) => (
|
||||
<div
|
||||
key={index}
|
||||
key={`recovery-word-${index}-${word}`}
|
||||
className="bg-cyber-dark border border-neon-cyan/30 rounded-lg p-3 text-center font-mono text-lg"
|
||||
>
|
||||
<span className="text-cyber-accent/70 text-sm mr-2">{index + 1}.</span>
|
||||
|
||||
@ -53,21 +53,35 @@ export function SyncStatus(): React.ReactElement | null {
|
||||
setProgress(newProgress)
|
||||
})
|
||||
|
||||
// Check current progress immediately
|
||||
const currentProgress = syncProgressManager.getProgress()
|
||||
if (currentProgress) {
|
||||
setProgress(currentProgress)
|
||||
}
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (!progress || progress.completed) {
|
||||
// Show indicator if we have progress and it's not completed
|
||||
if (!progress) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Always show indicator during sync, even if completed is false (means sync is in progress)
|
||||
if (progress.completed) {
|
||||
return null
|
||||
}
|
||||
|
||||
const relayName = progress.currentRelay ? getRelayDisplayName(progress.currentRelay) : null
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 ml-2" title={progress.currentRelay ? getRelayDisplayName(progress.currentRelay) : t('settings.sync.connecting')}>
|
||||
<div className="flex items-center gap-2 ml-2" title={relayName ?? t('settings.sync.connecting')}>
|
||||
<SyncIcon />
|
||||
{progress.currentRelay ? (
|
||||
{relayName ? (
|
||||
<span className="text-neon-cyan text-xs font-mono max-w-[200px] truncate">
|
||||
{getRelayDisplayName(progress.currentRelay)}
|
||||
{relayName}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-cyber-accent/70 text-xs italic">
|
||||
|
||||
@ -102,15 +102,19 @@ function HomeContent({
|
||||
<ArticleFiltersComponent filters={filters} onFiltersChange={setFilters} articles={allArticles} />
|
||||
)}
|
||||
|
||||
{isInitialLoad ? (
|
||||
{(() => {
|
||||
if (isInitialLoad) {
|
||||
return (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-cyber-accent/70">{t('common.loading')}</p>
|
||||
</div>
|
||||
) : shouldShowAuthors ? (
|
||||
<AuthorsList {...authorsListProps} />
|
||||
) : (
|
||||
<ArticlesList {...articlesListProps} />
|
||||
)}
|
||||
)
|
||||
}
|
||||
if (shouldShowAuthors) {
|
||||
return <AuthorsList {...authorsListProps} />
|
||||
}
|
||||
return <ArticlesList {...articlesListProps} />
|
||||
})()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -382,7 +382,7 @@ export function KeyManagementManager(): React.ReactElement {
|
||||
<div className="grid grid-cols-2 gap-4 mb-4">
|
||||
{recoveryPhrase.map((word, index) => (
|
||||
<div
|
||||
key={index}
|
||||
key={`recovery-word-${index}-${word}`}
|
||||
className="bg-cyber-dark border border-neon-cyan/30 rounded-lg p-3 text-center font-mono text-lg"
|
||||
>
|
||||
<span className="text-cyber-accent/70 text-sm mr-2">{index + 1}.</span>
|
||||
|
||||
@ -129,7 +129,7 @@ function WordInputs({
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{words.map((word, index) => (
|
||||
<WordInputWithAutocomplete
|
||||
key={index}
|
||||
key={`word-input-${index}-${word}`}
|
||||
index={index}
|
||||
value={word}
|
||||
onChange={(value) => onWordChange(index, value)}
|
||||
|
||||
@ -193,6 +193,8 @@ export function getPurchasesByPayer(payerPubkey: string, timeoutMs: number = 500
|
||||
sub.on('eose', (): void => {
|
||||
void done()
|
||||
})
|
||||
setTimeout(() => done(), timeoutMs).unref?.()
|
||||
setTimeout((): void => {
|
||||
void done()
|
||||
}, timeoutMs).unref?.()
|
||||
})
|
||||
}
|
||||
|
||||
@ -154,7 +154,9 @@ export function getReviewTipsForArticle(articleId: string, timeoutMs: number = 5
|
||||
sub.on('eose', (): void => {
|
||||
void done()
|
||||
})
|
||||
setTimeout(() => done(), timeoutMs).unref?.()
|
||||
setTimeout((): void => {
|
||||
void done()
|
||||
}, timeoutMs).unref?.()
|
||||
})
|
||||
}
|
||||
|
||||
@ -198,6 +200,8 @@ export function getReviewTipsForReview(reviewId: string, timeoutMs: number = 500
|
||||
sub.on('eose', (): void => {
|
||||
void done()
|
||||
})
|
||||
setTimeout(() => done(), timeoutMs).unref?.()
|
||||
setTimeout((): void => {
|
||||
void done()
|
||||
}, timeoutMs).unref?.()
|
||||
})
|
||||
}
|
||||
|
||||
@ -154,6 +154,8 @@ export function getSponsoringByAuthor(authorPubkey: string, timeoutMs: number =
|
||||
sub.on('eose', (): void => {
|
||||
void done()
|
||||
})
|
||||
setTimeout(() => done(), timeoutMs).unref?.()
|
||||
setTimeout((): void => {
|
||||
void done()
|
||||
}, timeoutMs).unref?.()
|
||||
})
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ import { getLatestVersion } from './versionManager'
|
||||
import { buildTagFilter } from './nostrTagSystemFilter'
|
||||
import { getPrimaryRelaySync } from './config'
|
||||
import { tryWithRelayRotation } from './relayRotation'
|
||||
import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
|
||||
import { PLATFORM_SERVICE } from './platformConfig'
|
||||
import { parseObjectId } from './urlGenerator'
|
||||
import type { SimplePoolWithSub } from '@/types/nostr-tools-extended'
|
||||
|
||||
@ -24,6 +24,9 @@ async function fetchAndCachePublications(
|
||||
pool: SimplePoolWithSub,
|
||||
authorPubkey: string
|
||||
): Promise<void> {
|
||||
const { getLastSyncDate } = await import('./syncStorage')
|
||||
const lastSyncDate = await getLastSyncDate()
|
||||
|
||||
const filters = [
|
||||
{
|
||||
...buildTagFilter({
|
||||
@ -31,7 +34,7 @@ async function fetchAndCachePublications(
|
||||
authorPubkey,
|
||||
service: PLATFORM_SERVICE,
|
||||
}),
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000, // Get all publications
|
||||
},
|
||||
]
|
||||
@ -148,6 +151,9 @@ async function fetchAndCacheSeries(
|
||||
pool: SimplePoolWithSub,
|
||||
authorPubkey: string
|
||||
): Promise<void> {
|
||||
const { getLastSyncDate } = await import('./syncStorage')
|
||||
const lastSyncDate = await getLastSyncDate()
|
||||
|
||||
// Fetch all events for series to cache them properly
|
||||
const filters = [
|
||||
{
|
||||
@ -156,7 +162,7 @@ async function fetchAndCacheSeries(
|
||||
authorPubkey,
|
||||
service: PLATFORM_SERVICE,
|
||||
}),
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000, // Get all series events
|
||||
},
|
||||
]
|
||||
@ -278,12 +284,15 @@ async function fetchAndCachePurchases(
|
||||
pool: SimplePoolWithSub,
|
||||
payerPubkey: string
|
||||
): Promise<void> {
|
||||
const { getLastSyncDate } = await import('./syncStorage')
|
||||
const lastSyncDate = await getLastSyncDate()
|
||||
|
||||
const filters = [
|
||||
{
|
||||
kinds: [9735], // Zap receipt
|
||||
authors: [payerPubkey],
|
||||
'#kind_type': ['purchase'],
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000,
|
||||
},
|
||||
]
|
||||
@ -376,12 +385,15 @@ async function fetchAndCacheSponsoring(
|
||||
pool: SimplePoolWithSub,
|
||||
authorPubkey: string
|
||||
): Promise<void> {
|
||||
const { getLastSyncDate } = await import('./syncStorage')
|
||||
const lastSyncDate = await getLastSyncDate()
|
||||
|
||||
const filters = [
|
||||
{
|
||||
kinds: [9735], // Zap receipt
|
||||
'#p': [authorPubkey],
|
||||
'#kind_type': ['sponsoring'],
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000,
|
||||
},
|
||||
]
|
||||
@ -474,12 +486,15 @@ async function fetchAndCacheReviewTips(
|
||||
pool: SimplePoolWithSub,
|
||||
authorPubkey: string
|
||||
): Promise<void> {
|
||||
const { getLastSyncDate } = await import('./syncStorage')
|
||||
const lastSyncDate = await getLastSyncDate()
|
||||
|
||||
const filters = [
|
||||
{
|
||||
kinds: [9735], // Zap receipt
|
||||
'#p': [authorPubkey],
|
||||
'#kind_type': ['review_tip'],
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000,
|
||||
},
|
||||
]
|
||||
@ -579,6 +594,9 @@ async function fetchAndCachePaymentNotes(
|
||||
pool: SimplePoolWithSub,
|
||||
userPubkey: string
|
||||
): Promise<void> {
|
||||
const { getLastSyncDate } = await import('./syncStorage')
|
||||
const lastSyncDate = await getLastSyncDate()
|
||||
|
||||
// Payment notes are kind 1 with type='payment'
|
||||
// They can be: as payer (authors) or as recipient (#recipient tag)
|
||||
const filters = [
|
||||
@ -587,7 +605,7 @@ async function fetchAndCachePaymentNotes(
|
||||
authors: [userPubkey],
|
||||
'#payment': [''],
|
||||
'#service': [PLATFORM_SERVICE],
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000,
|
||||
},
|
||||
{
|
||||
@ -595,7 +613,7 @@ async function fetchAndCachePaymentNotes(
|
||||
'#recipient': [userPubkey],
|
||||
'#payment': [''],
|
||||
'#service': [PLATFORM_SERVICE],
|
||||
since: MIN_EVENT_DATE,
|
||||
since: lastSyncDate,
|
||||
limit: 1000,
|
||||
},
|
||||
]
|
||||
|
||||
@ -5,7 +5,6 @@ import React from 'react'
|
||||
import { platformSyncService } from '@/lib/platformSync'
|
||||
import { nostrAuthService } from '@/lib/nostrAuth'
|
||||
import { syncUserContentToCache } from '@/lib/userContentSync'
|
||||
import { getLastSyncDate, getCurrentTimestamp } from '@/lib/syncStorage'
|
||||
import { syncProgressManager } from '@/lib/syncProgressManager'
|
||||
import { relaySessionManager } from '@/lib/relaySessionManager'
|
||||
|
||||
@ -74,27 +73,20 @@ export default function App({ Component, pageProps }: AppProps): React.ReactElem
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Start user content sync on app mount if connected
|
||||
// Start user content sync on app mount and on each page navigation if connected
|
||||
React.useEffect(() => {
|
||||
let syncInProgress = false
|
||||
|
||||
const startUserSync = async (): Promise<void> => {
|
||||
if (syncInProgress) {
|
||||
console.log('[App] Sync already in progress, skipping')
|
||||
return
|
||||
}
|
||||
|
||||
const state = nostrAuthService.getState()
|
||||
console.log('[App] Checking connection state:', { connected: state.connected, hasPubkey: Boolean(state.pubkey) })
|
||||
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')
|
||||
console.log('[App] Not connected or no pubkey, skipping sync')
|
||||
return
|
||||
}
|
||||
|
||||
@ -121,7 +113,16 @@ export default function App({ Component, pageProps }: AppProps): React.ReactElem
|
||||
// Try to start sync immediately
|
||||
void startUserSync()
|
||||
|
||||
// Also listen to connection changes to sync when user connects
|
||||
// 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()
|
||||
@ -129,6 +130,7 @@ export default function App({ Component, pageProps }: AppProps): React.ReactElem
|
||||
})
|
||||
|
||||
return () => {
|
||||
router.events?.off('routeChangeComplete', handleRouteChange)
|
||||
unsubscribe()
|
||||
}
|
||||
}, [])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user