lint fix wip
This commit is contained in:
parent
cc84d85193
commit
5b7b77aa9a
@ -5,9 +5,9 @@ interface ArticlePagesProps {
|
||||
pages: Page[]
|
||||
}
|
||||
|
||||
export function ArticlePages({ pages }: ArticlePagesProps): React.ReactElement {
|
||||
export function ArticlePages({ pages }: ArticlePagesProps): React.ReactElement | null {
|
||||
if (!pages || pages.length === 0) {
|
||||
return <></>
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -232,7 +232,7 @@ function PresentationForm({
|
||||
</button>
|
||||
</div>
|
||||
{hasExistingPresentation && (
|
||||
<DeleteButton onDelete={handleDelete} deleting={deleting} />
|
||||
<DeleteButton onDelete={() => { void handleDelete() }} deleting={deleting} />
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
@ -392,7 +392,7 @@ function NoAccountView(): React.ReactElement {
|
||||
</p>
|
||||
{error && <p className="text-sm text-red-400">{error}</p>}
|
||||
<NoAccountActionButtons
|
||||
onGenerate={handleGenerate}
|
||||
onGenerate={() => { void handleGenerate() }}
|
||||
onImport={() => setShowImportModal(true)}
|
||||
/>
|
||||
{generating && (
|
||||
@ -482,7 +482,7 @@ function AuthorPresentationFormView({
|
||||
loading={state.loading}
|
||||
handleSubmit={state.handleSubmit}
|
||||
deleting={state.deleting}
|
||||
handleDelete={state.handleDelete}
|
||||
handleDelete={() => { void state.handleDelete() }}
|
||||
hasExistingPresentation={existingPresentation !== null && existingPresentation !== undefined}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -165,7 +165,7 @@ export function ConnectButton(): React.ReactElement {
|
||||
error={error ?? createError}
|
||||
showUnlockModal={showUnlockModal}
|
||||
setShowUnlockModal={setShowUnlockModal}
|
||||
onCreateAccount={handleCreateAccount}
|
||||
onCreateAccount={() => { void handleCreateAccount() }}
|
||||
/>
|
||||
{showRecoveryStep && (
|
||||
<RecoveryStep
|
||||
|
||||
@ -163,10 +163,10 @@ export function CreateAccountModal({ onSuccess, onClose, initialStep = 'choose'
|
||||
loading,
|
||||
error,
|
||||
handleContinue,
|
||||
handleImport,
|
||||
() => { void handleImport() },
|
||||
setStep,
|
||||
setError,
|
||||
handleGenerate,
|
||||
() => { void handleGenerate() },
|
||||
onClose
|
||||
)
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ export function RecoveryStep({
|
||||
<div className="bg-cyber-dark border border-neon-cyan/30 rounded-lg p-6 max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto shadow-glow-cyan">
|
||||
<h2 className="text-2xl font-bold mb-4 text-neon-cyan">{t('account.create.recovery.title')}</h2>
|
||||
<RecoveryWarning />
|
||||
<RecoveryPhraseDisplay recoveryPhrase={recoveryPhrase} copied={copied} onCopy={handleCopy} />
|
||||
<RecoveryPhraseDisplay recoveryPhrase={recoveryPhrase} copied={copied} onCopy={() => { void handleCopy() }} />
|
||||
<PublicKeyDisplay npub={npub} />
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
|
||||
@ -27,9 +27,9 @@ function ImagePreview({ value }: { value: string }): React.ReactElement {
|
||||
|
||||
function UploadButtonLabel({ uploading, value }: { uploading: boolean; value: string | undefined }): React.ReactElement {
|
||||
if (uploading) {
|
||||
return <>{t('presentation.field.picture.uploading')}</>
|
||||
return <span>{t('presentation.field.picture.uploading')}</span>
|
||||
}
|
||||
return <>{value ? t('presentation.field.picture.change') : t('presentation.field.picture.upload')}</>
|
||||
return <span>{value ? t('presentation.field.picture.change') : t('presentation.field.picture.upload')}</span>
|
||||
}
|
||||
|
||||
function RemoveButton({ value, onChange }: { value: string | undefined; onChange: (url: string) => void }): React.ReactElement | null {
|
||||
|
||||
@ -252,8 +252,8 @@ export function KeyManagementManager(): React.ReactElement {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Sync Progress Bar */}
|
||||
{publicKeys && <SyncProgressBar />}
|
||||
{/* Sync Progress Bar - Always show if connected, even if publicKeys not loaded yet */}
|
||||
<SyncProgressBar />
|
||||
|
||||
{!publicKeys && !accountExists && (
|
||||
<div className="bg-yellow-900/20 border border-yellow-400/50 rounded-lg p-4 mb-6">
|
||||
|
||||
@ -213,6 +213,7 @@ function UnlockAccountForm({
|
||||
<div className="mb-4">
|
||||
<WordInputs words={words} onWordChange={handleWordChange} />
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
void handlePaste()
|
||||
}}
|
||||
|
||||
@ -29,25 +29,47 @@ export function useArticles(searchQuery: string = '', filters: ArticleFilters |
|
||||
const cachedAuthors = await objectCache.getAll('author')
|
||||
const authors = cachedAuthors as Article[]
|
||||
|
||||
// Calculate totalSponsoring for each author
|
||||
const authorsWithSponsoring = await Promise.all(
|
||||
authors.map(async (author) => {
|
||||
if (author.isPresentation && author.pubkey) {
|
||||
author.totalSponsoring = await getAuthorSponsoring(author.pubkey)
|
||||
}
|
||||
return author
|
||||
})
|
||||
)
|
||||
|
||||
if (authorsWithSponsoring.length > 0) {
|
||||
// Display authors immediately (with existing totalSponsoring if available)
|
||||
if (authors.length > 0) {
|
||||
setArticles((prev) => {
|
||||
// Merge with existing articles, avoiding duplicates
|
||||
const existingIds = new Set(prev.map((a) => a.id))
|
||||
const newAuthors = authorsWithSponsoring.filter((a) => !existingIds.has(a.id))
|
||||
const newAuthors = authors.filter((a) => !existingIds.has(a.id))
|
||||
const merged = [...prev, ...newAuthors].sort((a, b) => b.createdAt - a.createdAt)
|
||||
hasArticlesRef.current = merged.length > 0
|
||||
return merged
|
||||
})
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
// Calculate totalSponsoring asynchronously from cache (non-blocking)
|
||||
// Only update authors that don't have totalSponsoring yet
|
||||
const authorsNeedingSponsoring = authors.filter(
|
||||
(author) => author.isPresentation && author.pubkey && author.totalSponsoring === undefined
|
||||
)
|
||||
|
||||
if (authorsNeedingSponsoring.length > 0) {
|
||||
// Load sponsoring from cache in parallel (fast, no network)
|
||||
const sponsoringPromises = authorsNeedingSponsoring.map(async (author) => {
|
||||
if (author.pubkey) {
|
||||
const totalSponsoring = await getAuthorSponsoring(author.pubkey, true)
|
||||
return { authorId: author.id, totalSponsoring }
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const sponsoringResults = await Promise.all(sponsoringPromises)
|
||||
|
||||
// Update articles with sponsoring amounts
|
||||
setArticles((prev) =>
|
||||
prev.map((article) => {
|
||||
const sponsoringResult = sponsoringResults.find((r) => r?.authorId === article.id)
|
||||
if (sponsoringResult && article.isPresentation) {
|
||||
return { ...article, totalSponsoring: sponsoringResult.totalSponsoring }
|
||||
}
|
||||
return article
|
||||
})
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading authors from cache:', error)
|
||||
|
||||
@ -47,7 +47,7 @@ export class AlbyService {
|
||||
|
||||
try {
|
||||
await webln.enable()
|
||||
} catch (_error) {
|
||||
} catch {
|
||||
throw new Error('User rejected WebLN permission request')
|
||||
}
|
||||
}
|
||||
@ -175,7 +175,7 @@ export class AlbyService {
|
||||
}
|
||||
|
||||
setTimeout(checkPayment, interval)
|
||||
} catch (_error) {
|
||||
} catch {
|
||||
resolve({ paid: false, paymentHash })
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ async function tryUploadEndpoint(endpoint: string, formData: FormData, useProxy:
|
||||
try {
|
||||
const text = await response.text()
|
||||
errorMessage = text || `HTTP ${response.status} ${response.statusText}`
|
||||
} catch (_e) {
|
||||
} catch {
|
||||
errorMessage = `HTTP ${response.status} ${response.statusText}`
|
||||
}
|
||||
throw new Error(errorMessage)
|
||||
|
||||
@ -37,7 +37,7 @@ class NostrService {
|
||||
if (decoded.type === 'nsec' && typeof decoded.data === 'string') {
|
||||
this.privateKey = decoded.data
|
||||
}
|
||||
} catch (_e) {
|
||||
} catch {
|
||||
// Assume it's already a hex string
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,7 @@ class NostrService {
|
||||
if (decoded.type === 'npub' && typeof decoded.data === 'string') {
|
||||
this.publicKey = decoded.data
|
||||
}
|
||||
} catch (_e) {
|
||||
} catch {
|
||||
// Assume it's already a hex string
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,59 @@
|
||||
import { getSponsoringByAuthor } from './sponsoringQueries'
|
||||
import { objectCache } from './objectCache'
|
||||
import type { Article } from '@/types/nostr'
|
||||
import type { Sponsoring } from '@/types/nostr'
|
||||
|
||||
/**
|
||||
* Get total sponsoring for an author by their pubkey from IndexedDB cache
|
||||
* This is much faster than network queries
|
||||
* Returns both the amount and whether the cache was empty (to avoid duplicate calls)
|
||||
*/
|
||||
async function getAuthorSponsoringFromCache(pubkey: string): Promise<{ amount: number; cacheWasEmpty: boolean }> {
|
||||
try {
|
||||
const allSponsoring = await objectCache.getAll('sponsoring')
|
||||
const sponsoringList = allSponsoring as Sponsoring[]
|
||||
|
||||
// If cache is empty, return immediately
|
||||
if (sponsoringList.length === 0) {
|
||||
return { amount: 0, cacheWasEmpty: true }
|
||||
}
|
||||
|
||||
// Filter by author pubkey and sum amounts
|
||||
const amount = sponsoringList
|
||||
.filter((sponsoring) => sponsoring.authorPubkey === pubkey)
|
||||
.reduce((total, sponsoring) => total + sponsoring.amount, 0)
|
||||
|
||||
return { amount, cacheWasEmpty: false }
|
||||
} catch (error) {
|
||||
console.error('Error calculating author sponsoring from cache:', error)
|
||||
return { amount: 0, cacheWasEmpty: true }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total sponsoring for an author by their pubkey
|
||||
* Calculates from cache (sponsoring queries) instead of tags
|
||||
* First tries cache, then falls back to network query if needed
|
||||
* If cache is empty, returns 0 immediately (very fast, no network request)
|
||||
*/
|
||||
export async function getAuthorSponsoring(pubkey: string): Promise<number> {
|
||||
export async function getAuthorSponsoring(pubkey: string, useCacheOnly: boolean = true): Promise<number> {
|
||||
try {
|
||||
// Try cache first (much faster)
|
||||
const { amount: cachedAmount, cacheWasEmpty } = await getAuthorSponsoringFromCache(pubkey)
|
||||
|
||||
// If cache is empty, return 0 immediately (no network request)
|
||||
if (cacheWasEmpty) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (cachedAmount > 0 || useCacheOnly) {
|
||||
return cachedAmount
|
||||
}
|
||||
|
||||
// Fallback to network query if cache exists but cacheOnly is false
|
||||
const sponsoringList = await getSponsoringByAuthor(pubkey, 5000)
|
||||
// Sum all sponsoring amounts for this author
|
||||
return sponsoringList.reduce((total, sponsoring) => total + sponsoring.amount, 0)
|
||||
} catch (error) {
|
||||
console.error('Error calculating author sponsoring from cache:', error)
|
||||
console.error('Error calculating author sponsoring:', error)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user