From a4a39fd0ba2c725208f1b515fa02985a181ef278 Mon Sep 17 00:00:00 2001 From: Nicolas Cantu Date: Tue, 6 Jan 2026 01:11:20 +0100 Subject: [PATCH] fix 'Chargement..' for profil --- components/ConditionalPublishButton.tsx | 44 ++++++++-------------- components/DocsContent.tsx | 4 +- components/Nip95ConfigManager.tsx | 9 ++--- lib/articlePublisherHelpersPresentation.ts | 4 +- lib/articleQueries.ts | 3 +- lib/nostr.ts | 5 ++- lib/platformConfig.ts | 4 ++ lib/reviews.ts | 4 +- lib/seriesQueries.ts | 4 +- lib/sponsoring.ts | 3 +- locales/en.txt | 5 +++ locales/fr.txt | 5 +++ public/locales/en.txt | 16 ++++++++ public/locales/fr.txt | 16 ++++++++ 14 files changed, 84 insertions(+), 42 deletions(-) diff --git a/components/ConditionalPublishButton.tsx b/components/ConditionalPublishButton.tsx index d65ea09..a8dc864 100644 --- a/components/ConditionalPublishButton.tsx +++ b/components/ConditionalPublishButton.tsx @@ -16,24 +16,15 @@ function CreateAuthorPageLink() { ) } -function PublishLink() { - return ( - - {t('nav.publish')} - - ) -} - -function LoadingButton() { - return ( -
- {t('nav.loading')} -
- ) -} - function AuthorProfileLink({ presentation, profile }: { presentation: Article; profile: { name?: string; picture?: string } | null }) { - const authorName = presentation.title.replace(/^Présentation de /, '') || profile?.name || 'Auteur' + // Extract author name from presentation title or profile + // Title format: "Présentation de " or just use profile name + let authorName = presentation.title.replace(/^Présentation de /, '').trim() + if (!authorName || authorName === 'Présentation') { + authorName = profile?.name || 'Auteur' + } + + // Extract picture from presentation (bannerUrl or from JSON metadata) or profile const picture = presentation.bannerUrl || profile?.picture return ( @@ -48,6 +39,7 @@ function AuthorProfileLink({ presentation, profile }: { presentation: Article; p alt={authorName} fill className="object-cover" + sizes="32px" /> ) : ( @@ -64,19 +56,16 @@ export function ConditionalPublishButton() { const { connected, pubkey, profile } = useNostrAuth() const { checkPresentationExists } = useAuthorPresentation(pubkey ?? null) const [presentation, setPresentation] = useState
(null) - const [loading, setLoading] = useState(false) useEffect(() => { const check = async () => { if (!connected || !pubkey) { setPresentation(null) - setLoading(false) return } - setLoading(true) + // Check for presentation asynchronously, but don't show loading state const pres = await checkPresentationExists() setPresentation(pres) - setLoading(false) } void check() }, [connected, pubkey, checkPresentationExists]) @@ -85,14 +74,11 @@ export function ConditionalPublishButton() { return } - if (loading) { - return + // If presentation exists, show author profile link with image/fallback + if (presentation) { + return } - if (!presentation) { - return - } - - // If presentation exists, show author profile link instead of publish button - return + // Otherwise, show create author page button immediately (no loading state) + return } diff --git a/components/DocsContent.tsx b/components/DocsContent.tsx index 8ddafcb..8c0fd12 100644 --- a/components/DocsContent.tsx +++ b/components/DocsContent.tsx @@ -1,5 +1,5 @@ -import React from 'react' import { renderMarkdown } from '@/lib/markdownRenderer' +import { t } from '@/lib/i18n' interface DocsContentProps { content: string @@ -10,7 +10,7 @@ export function DocsContent({ content, loading }: DocsContentProps) { if (loading) { return (
-

Chargement de la documentation...

+

{t('docs.loading')}

) } diff --git a/components/Nip95ConfigManager.tsx b/components/Nip95ConfigManager.tsx index cc32a95..770ccd2 100644 --- a/components/Nip95ConfigManager.tsx +++ b/components/Nip95ConfigManager.tsx @@ -219,13 +219,13 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
setEditingId(api.id)} - title="Click to edit URL" + title={t('settings.nip95.list.editUrl')} > {api.url}
)}
- Priority: {api.priority} | ID: {api.id} + {t('settings.nip95.list.priorityLabel', { priority: api.priority, id: api.id })}
@@ -273,11 +273,10 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)

- Note: Endpoints are tried in priority order (lower number = higher priority). - Only enabled endpoints will be used for uploads. + {t('settings.nip95.note.title')} {t('settings.nip95.note.priority')}

- If an endpoint fails, the next enabled endpoint will be tried automatically. + {t('settings.nip95.note.fallback')}

diff --git a/lib/articlePublisherHelpersPresentation.ts b/lib/articlePublisherHelpersPresentation.ts index 39314ab..655dfbb 100644 --- a/lib/articlePublisherHelpersPresentation.ts +++ b/lib/articlePublisherHelpersPresentation.ts @@ -4,7 +4,7 @@ import type { AuthorPresentationDraft } from './articlePublisher' import type { SimplePoolWithSub } from '@/types/nostr-tools-extended' import { buildTags, extractTagsFromEvent, buildTagFilter } from './nostrTagSystem' import { getPrimaryRelaySync } from './config' -import { PLATFORM_SERVICE } from './platformConfig' +import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig' import { generateAuthorHashId } from './hashIdGenerator' import { generateObjectUrl } from './urlGenerator' import { getLatestVersion } from './versionManager' @@ -104,6 +104,7 @@ export function parsePresentationEvent(event: Event): import('@/types/nostr').Au // Try to extract profile JSON from tag first (new format) let profileData: { + authorName?: string presentation?: string contentDescription?: string mainnetAddress?: string @@ -191,6 +192,7 @@ export async function fetchAuthorPresentationFromPool( authorPubkey: pubkey, service: PLATFORM_SERVICE, }), + since: MIN_EVENT_DATE, limit: 100, // Get all versions to find the latest }, ] diff --git a/lib/articleQueries.ts b/lib/articleQueries.ts index 1fb8ad7..995352e 100644 --- a/lib/articleQueries.ts +++ b/lib/articleQueries.ts @@ -6,7 +6,7 @@ import type { Article } from '@/types/nostr' import { parseArticleFromEvent } from './nostrEventParsing' import { buildTagFilter } from './nostrTagSystem' import { getPrimaryRelaySync } from './config' -import { PLATFORM_SERVICE } from './platformConfig' +import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig' function createSeriesSubscription(pool: SimplePool, seriesId: string, limit: number) { const filters = [ @@ -16,6 +16,7 @@ function createSeriesSubscription(pool: SimplePool, seriesId: string, limit: num seriesId, service: PLATFORM_SERVICE, }), + since: MIN_EVENT_DATE, limit, }, ] diff --git a/lib/nostr.ts b/lib/nostr.ts index f734873..8a66644 100644 --- a/lib/nostr.ts +++ b/lib/nostr.ts @@ -13,7 +13,7 @@ import { checkZapReceipt as checkZapReceiptHelper } from './nostrZapVerification import { subscribeWithTimeout } from './nostrSubscription' import { getPrimaryRelay, getPrimaryRelaySync } from './config' import { buildTagFilter } from './nostrTagSystem' -import { PLATFORM_SERVICE } from './platformConfig' +import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig' class NostrService { private pool: SimplePool | null = null @@ -89,12 +89,14 @@ class NostrService { // Subscribe to both 'publication' and 'author' type events // Authors are identified by tag type='author' in the tag system // Filter by service='zapwall.fr' to only get notes from this platform + // Limit to events published on or after January 6, 2026 const filters = [ { ...buildTagFilter({ type: 'publication', service: PLATFORM_SERVICE, }), + since: MIN_EVENT_DATE, limit, }, { @@ -102,6 +104,7 @@ class NostrService { type: 'author', service: PLATFORM_SERVICE, }), + since: MIN_EVENT_DATE, limit, }, ] diff --git a/lib/platformConfig.ts b/lib/platformConfig.ts index 1067c1c..eff0e9b 100644 --- a/lib/platformConfig.ts +++ b/lib/platformConfig.ts @@ -1,3 +1,7 @@ export const PLATFORM_NPUB = 'npub18s03s39fa80ce2n3cmm0zme3jqehc82h6ld9sxq03uejqm3d05gsae0fuu' export const PLATFORM_BITCOIN_ADDRESS = 'bc1qerauk5yhqytl6z93ckvwkylup8s0256uenzg9y' export const PLATFORM_SERVICE = 'zapwall.fr' + +// Minimum date for Nostr events: January 6, 2026 00:00:00 UTC +// Timestamp Unix: 1736115200 +export const MIN_EVENT_DATE = 1736115200 diff --git a/lib/reviews.ts b/lib/reviews.ts index df64e0a..7354017 100644 --- a/lib/reviews.ts +++ b/lib/reviews.ts @@ -4,7 +4,7 @@ import type { Review } from '@/types/nostr' import { parseReviewFromEvent } from './nostrEventParsing' import { buildTagFilter } from './nostrTagSystem' import { getPrimaryRelaySync } from './config' -import { PLATFORM_SERVICE } from './platformConfig' +import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig' function buildReviewFilters(articleId: string) { const tagFilter = buildTagFilter({ @@ -17,8 +17,10 @@ function buildReviewFilters(articleId: string) { kinds: number[] '#quote'?: string[] '#article'?: string[] + since?: number } = { kinds: Array.isArray(tagFilter.kinds) ? tagFilter.kinds as number[] : [1], + since: MIN_EVENT_DATE, } if (tagFilter['#quote']) { filterObj['#quote'] = tagFilter['#quote'] as string[] diff --git a/lib/seriesQueries.ts b/lib/seriesQueries.ts index ebf9e53..a7038b4 100644 --- a/lib/seriesQueries.ts +++ b/lib/seriesQueries.ts @@ -4,7 +4,7 @@ import type { Series } from '@/types/nostr' import { parseSeriesFromEvent } from './nostrEventParsing' import { buildTagFilter } from './nostrTagSystem' import { getPrimaryRelaySync } from './config' -import { PLATFORM_SERVICE } from './platformConfig' +import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig' function buildSeriesFilters(authorPubkey: string) { const tagFilter = buildTagFilter({ @@ -18,6 +18,7 @@ function buildSeriesFilters(authorPubkey: string) { kinds: tagFilter.kinds as number[], ...(tagFilter.authors ? { authors: tagFilter.authors as string[] } : {}), ...(tagFilter['#series'] ? { '#series': tagFilter['#series'] as string[] } : {}), + since: MIN_EVENT_DATE, }, ] } @@ -66,6 +67,7 @@ function buildSeriesByIdFilters(seriesId: string) { type: 'series', service: PLATFORM_SERVICE, }), + since: MIN_EVENT_DATE, }, ] } diff --git a/lib/sponsoring.ts b/lib/sponsoring.ts index cbaf890..0817c64 100644 --- a/lib/sponsoring.ts +++ b/lib/sponsoring.ts @@ -2,7 +2,7 @@ import { nostrService } from './nostr' import type { Article } from '@/types/nostr' import { getPrimaryRelaySync } from './config' import { buildTagFilter, extractTagsFromEvent } from './nostrTagSystem' -import { PLATFORM_SERVICE } from './platformConfig' +import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig' function subscribeToPresentation(pool: import('nostr-tools').SimplePool, pubkey: string): Promise { const filters = [ @@ -12,6 +12,7 @@ function subscribeToPresentation(pool: import('nostr-tools').SimplePool, pubkey: authorPubkey: pubkey, service: PLATFORM_SERVICE, }), + since: MIN_EVENT_DATE, limit: 1, }, ] diff --git a/locales/en.txt b/locales/en.txt index c83f62b..3dc3fd5 100644 --- a/locales/en.txt +++ b/locales/en.txt @@ -192,3 +192,8 @@ settings.nip95.list.cancel=Cancel settings.nip95.list.remove=Remove settings.nip95.remove.confirm=Are you sure you want to remove this endpoint? settings.nip95.empty=No endpoints configured +settings.nip95.list.priorityLabel=Priority: {{priority}} | ID: {{id}} +settings.nip95.list.editUrl=Click to edit URL +settings.nip95.note.title=Note: +settings.nip95.note.priority=Endpoints are tried in priority order (lower number = higher priority). Only enabled endpoints will be used for uploads. +settings.nip95.note.fallback=If an endpoint fails, the next enabled endpoint will be tried automatically. diff --git a/locales/fr.txt b/locales/fr.txt index 396ae70..cca3f1f 100644 --- a/locales/fr.txt +++ b/locales/fr.txt @@ -192,3 +192,8 @@ settings.nip95.list.cancel=Annuler settings.nip95.list.remove=Supprimer settings.nip95.remove.confirm=Êtes-vous sûr de vouloir supprimer cet endpoint ? settings.nip95.empty=Aucun endpoint configuré +settings.nip95.list.priorityLabel=Priorité: {{priority}} | ID: {{id}} +settings.nip95.list.editUrl=Cliquer pour modifier l'URL +settings.nip95.note.title=Note : +settings.nip95.note.priority=Les endpoints sont essayés dans l'ordre de priorité (nombre plus bas = priorité plus haute). Seuls les endpoints activés seront utilisés pour les uploads. +settings.nip95.note.fallback=Si un endpoint échoue, le prochain endpoint activé sera essayé automatiquement. diff --git a/public/locales/en.txt b/public/locales/en.txt index 04d1a72..a1e7149 100644 --- a/public/locales/en.txt +++ b/public/locales/en.txt @@ -18,6 +18,17 @@ nav.publish=Publish profile nav.createAuthorPage=Create author page nav.loading=Loading... +# Documentation +docs.title=Documentation +docs.userGuide=User Guide +docs.faq=FAQ +docs.publishing=Publishing Guide +docs.payment=Payment Guide +docs.error=Error +docs.error.loadFailed=Unable to load documentation. +docs.meta.description=Complete documentation for zapwall.fr +docs.loading=Loading documentation... + # Categories category.science-fiction=Science Fiction category.scientific-research=Scientific Research @@ -182,3 +193,8 @@ settings.nip95.list.cancel=Cancel settings.nip95.list.remove=Remove settings.nip95.remove.confirm=Are you sure you want to remove this endpoint? settings.nip95.empty=No endpoints configured +settings.nip95.list.priorityLabel=Priority: {{priority}} | ID: {{id}} +settings.nip95.list.editUrl=Click to edit URL +settings.nip95.note.title=Note: +settings.nip95.note.priority=Endpoints are tried in priority order (lower number = higher priority). Only enabled endpoints will be used for uploads. +settings.nip95.note.fallback=If an endpoint fails, the next enabled endpoint will be tried automatically. diff --git a/public/locales/fr.txt b/public/locales/fr.txt index fe44680..f517e8f 100644 --- a/public/locales/fr.txt +++ b/public/locales/fr.txt @@ -18,6 +18,17 @@ nav.publish=Publier le profil nav.createAuthorPage=Créer page auteur nav.loading=Chargement... +# Documentation +docs.title=Documentation +docs.userGuide=Guide d'utilisation +docs.faq=FAQ +docs.publishing=Guide de publication +docs.payment=Guide de paiement +docs.error=Erreur +docs.error.loadFailed=Impossible de charger la documentation. +docs.meta.description=Documentation complète pour zapwall.fr +docs.loading=Chargement de la documentation... + # Categories category.science-fiction=Science-fiction category.scientific-research=Recherche scientifique @@ -182,3 +193,8 @@ settings.nip95.list.cancel=Annuler settings.nip95.list.remove=Supprimer settings.nip95.remove.confirm=Êtes-vous sûr de vouloir supprimer cet endpoint ? settings.nip95.empty=Aucun endpoint configuré +settings.nip95.list.priorityLabel=Priorité: {{priority}} | ID: {{id}} +settings.nip95.list.editUrl=Cliquer pour modifier l'URL +settings.nip95.note.title=Note : +settings.nip95.note.priority=Les endpoints sont essayés dans l'ordre de priorité (nombre plus bas = priorité plus haute). Seuls les endpoints activés seront utilisés pour les uploads. +settings.nip95.note.fallback=Si un endpoint échoue, le prochain endpoint activé sera essayé automatiquement.