lint fix wip

This commit is contained in:
Nicolas Cantu 2026-01-07 02:17:26 +01:00
parent d068b67deb
commit 64c94b6679
5 changed files with 150 additions and 36 deletions

View File

@ -12,12 +12,14 @@ export function useI18n(locale: Locale = 'fr'): {
useEffect(() => {
const load = async (): Promise<void> => {
try {
// Get saved locale from localStorage or use provided locale
// Get saved locale from IndexedDB or use provided locale
let savedLocale: Locale | null = null
try {
if (typeof window !== 'undefined') {
savedLocale = localStorage.getItem('zapwall-locale') as Locale | null
}
// Migrate from localStorage if needed
const { localeStorage } = await import('@/lib/localeStorage')
await localeStorage.migrateFromLocalStorage()
// Load from IndexedDB
savedLocale = await localeStorage.getLocale()
} catch {
// Fallback to provided locale
}

View File

@ -77,8 +77,8 @@ async function buildParsedArticleFromDraft(
paid: false,
thumbnailUrl: draft.bannerUrl ?? '',
invoice: invoice.invoice,
paymentHash: invoice.paymentHash ?? undefined,
category: draft.category,
...(invoice.paymentHash ? { paymentHash: invoice.paymentHash } : {}),
...(draft.category ? { category: draft.category } : {}),
...(draft.seriesId ? { seriesId: draft.seriesId } : {}),
...(draft.bannerUrl ? { bannerUrl: draft.bannerUrl } : {}),
...(draft.pages && draft.pages.length > 0 ? { pages: draft.pages } : {}),
@ -93,10 +93,27 @@ async function publishPreviewWithInvoice(
invoice: AlbyInvoice,
authorPubkey: string,
presentationId: string,
extraTags?: string[][]
extraTags?: string[][],
customArticle?: Article
): Promise<import('nostr-tools').Event | null> {
// Build parsed article object
const { article, hash, version, index } = await buildParsedArticleFromDraft(draft, invoice, authorPubkey)
// Build parsed article object (use custom article if provided, e.g., for updates with version)
let article: Article
let hash: string
let version: number
let index: number
if (customArticle) {
article = customArticle
hash = customArticle.hash
version = customArticle.version
index = customArticle.index ?? 0
} else {
const built = await buildParsedArticleFromDraft(draft, invoice, authorPubkey)
article = built.article
hash = built.hash
version = built.version
index = built.index
}
// Build event template
const previewEventTemplate = await createPreviewEvent(draft, invoice, authorPubkey, presentationId, extraTags)
@ -152,8 +169,8 @@ export async function publishSeries(params: {
const {category} = params
requireCategory(category)
// Map category to new system
const newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Map category to new system (not used but kept for future reference)
const _newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Generate hash ID from series data
const hashId = await generateSeriesHashId({
@ -241,8 +258,8 @@ async function buildSeriesEvent(
content: string
tags: string[][]
}> {
// Map category to new system
const newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Map category to new system (not used but kept for future reference)
const _newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Generate hash ID from series data
const hashId = await generateSeriesHashId({
@ -307,8 +324,8 @@ export async function publishReview(params: {
const {category} = params
requireCategory(category)
// Map category to new system
const newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Map category to new system (not used but kept for future reference)
const _newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Generate hash ID from review data
const { generateReviewHashId } = await import('./hashIdGenerator')
@ -400,8 +417,8 @@ async function buildReviewEvent(
content: string
tags: string[][]
}> {
// Map category to new system
const newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Map category to new system (not used but kept for future reference)
const _newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
// Generate hash ID from review data
const { generateReviewHashId } = await import('./hashIdGenerator')
@ -502,12 +519,36 @@ async function publishUpdate(
): Promise<ArticleUpdateResult> {
const {category} = draft
requireCategory(category)
// Get original article from IndexedDB to retrieve current version
const { objectCache } = await import('./objectCache')
const originalArticle = await objectCache.getById('publication', originalArticleId) as Article | null
if (!originalArticle) {
return updateFailure(originalArticleId, 'Original article not found in cache')
}
// Verify user is the author
if (originalArticle.pubkey !== authorPubkey) {
return updateFailure(originalArticleId, 'Only the author can update this article')
}
const presentationId = await ensurePresentation(authorPubkey)
const invoice = await createArticleInvoice(draft)
const newCategory = category === 'science-fiction' ? 'sciencefiction' : 'research'
const updateTags = await buildUpdateTags(draft, originalArticleId, newCategory, authorPubkey)
const publishedEvent = await publishPreviewWithInvoice(draft, invoice, authorPubkey, presentationId, updateTags)
// Use current version from original article
const currentVersion = originalArticle.version ?? 0
const updateTags = await buildUpdateTags(draft, originalArticleId, newCategory, authorPubkey, currentVersion)
// Build parsed article with incremented version
const { article, hash, version, index } = await buildParsedArticleFromDraft(draft, invoice, authorPubkey)
const updatedArticle: Article = {
...article,
version: currentVersion + 1, // Increment version for update
}
const publishedEvent = await publishPreviewWithInvoice(draft, invoice, authorPubkey, presentationId, updateTags, updatedArticle)
if (!publishedEvent) {
return updateFailure(originalArticleId, 'Failed to publish article update')
}
@ -547,14 +588,83 @@ function updateFailure(originalArticleId: string, error?: string): ArticleUpdate
export async function deleteArticleEvent(articleId: string, authorPubkey: string, authorPrivateKey?: string): Promise<void> {
ensureKeys(authorPubkey, authorPrivateKey)
const deleteEvent = {
kind: 5,
created_at: Math.floor(Date.now() / 1000),
tags: [['e', articleId]] as string[][],
content: 'deleted',
} as const
const published = await nostrService.publishEvent(deleteEvent)
if (!published) {
// Get original event from IndexedDB cache
const { objectCache } = await import('./objectCache')
const originalEvent = await objectCache.getEventById('publication', articleId)
if (!originalEvent) {
throw new Error('Article not found in cache')
}
// Verify user is the author
if (originalEvent.pubkey !== authorPubkey) {
throw new Error('Only the author can delete this article')
}
// Build delete event (new version with hidden=true)
const { buildDeleteEvent } = await import('./objectModification')
const deleteEventTemplate = await buildDeleteEvent(originalEvent, authorPubkey)
if (!deleteEventTemplate) {
throw new Error('Failed to build delete event')
}
// Parse the original article to get hash/version/index
const { parseArticleFromEvent } = await import('./nostrEventParsing')
const originalParsed = await parseArticleFromEvent(originalEvent)
if (!originalParsed) {
throw new Error('Failed to parse original article')
}
// Increment version for deletion
const { extractTagsFromEvent } = await import('./nostrTagSystem')
const tags = extractTagsFromEvent(deleteEventTemplate)
const newVersion = tags.version ?? originalParsed.version + 1
const {hash} = originalParsed
const index = originalParsed.index ?? 0
// Build updated parsed Article object with hidden flag
const deletedArticle: Article = {
...originalParsed,
version: newVersion,
}
// Set private key in orchestrator
const privateKey = authorPrivateKey ?? nostrService.getPrivateKey()
if (!privateKey) {
throw new Error('Private key required for signing')
}
const { writeOrchestrator } = await import('./writeOrchestrator')
writeOrchestrator.setPrivateKey(privateKey)
// Finalize event
const { finalizeEvent } = await import('nostr-tools')
const { hexToBytes } = await import('nostr-tools/utils')
const secretKey = hexToBytes(privateKey)
const event = finalizeEvent(deleteEventTemplate, secretKey)
// Get active relays
const { relaySessionManager } = await import('./relaySessionManager')
const activeRelays = await relaySessionManager.getActiveRelays()
const { getPrimaryRelay } = await import('./config')
const relays = activeRelays.length > 0 ? activeRelays : [await getPrimaryRelay()]
// Publish via writeOrchestrator (parallel network + local write)
const result = await writeOrchestrator.writeAndPublish(
{
objectType: 'publication',
hash,
event,
parsed: deletedArticle,
version: newVersion,
hidden: true, // Mark as hidden (deleted)
index,
},
relays
)
if (!result.success) {
throw new Error('Failed to publish delete event')
}
}

View File

@ -59,8 +59,8 @@ async function buildParsedArticleFromDraft(
paid: false,
thumbnailUrl: draft.bannerUrl ?? '',
invoice: invoice.invoice,
paymentHash: invoice.paymentHash ?? undefined,
category: draft.category,
...(invoice.paymentHash ? { paymentHash: invoice.paymentHash } : {}),
...(draft.category ? { category: draft.category } : {}),
...(draft.seriesId ? { seriesId: draft.seriesId } : {}),
...(draft.bannerUrl ? { bannerUrl: draft.bannerUrl } : {}),
...(draft.pages && draft.pages.length > 0 ? { pages: draft.pages } : {}),
@ -123,10 +123,9 @@ export async function publishPreview(
if (returnStatus) {
// Return PublishResult format
const { publishResult } = await import('./publishResult')
return {
event,
relayStatuses: relays.map((relayUrl, idx) => {
relayStatuses: relays.map((relayUrl, _idx) => {
const isSuccess = typeof result.published === 'object' && result.published.includes(relayUrl)
return {
relayUrl,

View File

@ -63,10 +63,13 @@ export class NostrAuthService {
void this.saveStateToStorage()
this.notifyListeners()
// Sync user content to IndexedDB cache (background operation)
// Sync user content via Service Worker (background operation)
if (result.publicKey) {
const { syncUserContentToCache } = await import('@/lib/userContentSync')
void syncUserContentToCache(result.publicKey)
const { swClient } = await import('@/lib/swClient')
const isReady = await swClient.isReady()
if (isReady) {
void swClient.startUserSync(result.publicKey)
}
}
return result

View File

@ -237,7 +237,7 @@ class WriteService {
data: { type, objectType, objectId, eventId, notificationData: data },
})
})
} else {
}
// Fallback: direct write
const { notificationService } = await import('./notificationService')
await notificationService.createNotification({
@ -247,7 +247,7 @@ class WriteService {
eventId,
data,
})
}
} catch (error) {
console.error('[WriteService] Error creating notification:', error)