From 37dd93116bd88f31d6619b32ba0e032819808663 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Sat, 14 Feb 2026 19:01:03 +0100 Subject: [PATCH] bug-fixes --- src/lib/modules/profiles/ProfilePage.svelte | 46 +++++++++++++-- src/lib/services/nostr/nostr-client.ts | 14 +++-- src/routes/about/+page.svelte | 37 +----------- src/routes/discussions/+page.svelte | 7 --- src/routes/feed/+page.svelte | 64 ++++++++++++++++++--- src/routes/repos/[naddr]/+page.svelte | 4 -- src/routes/topics/[name]/+page.svelte | 13 ----- static/changelog.yaml | 4 +- static/healthz.json | 4 +- 9 files changed, 111 insertions(+), 82 deletions(-) diff --git a/src/lib/modules/profiles/ProfilePage.svelte b/src/lib/modules/profiles/ProfilePage.svelte index c15fd48..a828a8d 100644 --- a/src/lib/modules/profiles/ProfilePage.svelte +++ b/src/lib/modules/profiles/ProfilePage.svelte @@ -5,7 +5,7 @@ import FeedPost from '../feed/FeedPost.svelte'; import CommentComponent from '../comments/Comment.svelte'; import ProfileMenu from '../../components/profile/ProfileMenu.svelte'; - import { fetchProfile, fetchUserStatus, fetchUserStatusEvent, type ProfileData } from '../../services/user-data.js'; + import { fetchProfile, fetchUserStatus, fetchUserStatusEvent, fetchRelayLists, type ProfileData } from '../../services/user-data.js'; import { nostrClient } from '../../services/nostr/nostr-client.js'; import { relayManager } from '../../services/nostr/relay-manager.js'; import { config } from '../../services/nostr/config.js'; @@ -132,6 +132,34 @@ return unsubscribe; }); + /** + * Get relays for loading a profile, including the profile owner's relay lists + */ + async function getProfileRelaysForPubkey(pubkey: string): Promise { + // Start with base profile relays + const baseRelays = relayManager.getProfileReadRelays(); + + // Try to fetch relay lists from the profile owner (non-blocking) + try { + const { inbox } = await Promise.race([ + fetchRelayLists(pubkey, baseRelays), + new Promise<{ inbox: string[]; outbox: string[] }>((resolve) => + setTimeout(() => resolve({ inbox: [], outbox: [] }), 2000) + ) + ]); + + // Combine base relays with profile owner's inbox relays + const allRelays = [...baseRelays, ...inbox]; + + // Normalize and deduplicate + const normalized = allRelays.map(r => r.toLowerCase().trim()).filter(r => r.length > 0); + return Array.from(new Set(normalized)); + } catch (error) { + // If fetching relay lists fails, just use base relays + return baseRelays; + } + } + async function loadProfileEvent(pubkey: string) { if (!isMounted) return; try { @@ -144,7 +172,8 @@ } // Fetch from relays if not in cache - shorter timeout - const relays = relayManager.getProfileReadRelays(); + // Include profile owner's relay lists + const relays = await getProfileRelaysForPubkey(pubkey); const events = await nostrClient.fetchEvents( [{ kinds: [KIND.METADATA], authors: [pubkey], limit: 1 }], relays, @@ -632,11 +661,18 @@ loading = true; try { + // Step 0: Get relays including profile owner's relay lists (non-blocking, with timeout) + const profileRelaysPromise = getProfileRelaysForPubkey(pubkey); + // Step 1: Load profile and status first (fast from cache) - display immediately // fetchProfile uses parseProfile which prioritizes tags over JSON content - const profilePromise = fetchProfile(pubkey); - const statusPromise = fetchUserStatus(pubkey); - const statusEventPromise = fetchUserStatusEvent(pubkey); + // Use profile owner's relays if available, otherwise fall back to default + const relaysPromise = profileRelaysPromise.catch(() => relayManager.getProfileReadRelays()); + const relays = await relaysPromise; + + const profilePromise = fetchProfile(pubkey, relays); + const statusPromise = fetchUserStatus(pubkey, relays); + const statusEventPromise = fetchUserStatusEvent(pubkey, relays); activeFetchPromises.add(profilePromise); activeFetchPromises.add(statusPromise); activeFetchPromises.add(statusEventPromise); diff --git a/src/lib/services/nostr/nostr-client.ts b/src/lib/services/nostr/nostr-client.ts index dc4638a..afaebda 100644 --- a/src/lib/services/nostr/nostr-client.ts +++ b/src/lib/services/nostr/nostr-client.ts @@ -1360,21 +1360,23 @@ class NostrClient { */ private sanitizeFilters(filters: Filter[]): Filter[] { return filters.map(filter => { - if (filter.authors && filter.authors.length > 0) { + const filterWithAuthors = filter as Filter & { authors?: string[] }; + if (filterWithAuthors.authors && filterWithAuthors.authors.length > 0) { // Filter out invalid pubkeys - const validAuthors = filter.authors.filter(author => this.isValidPubkey(author)); + const validAuthors = filterWithAuthors.authors.filter(author => this.isValidPubkey(author)); if (validAuthors.length === 0) { // If no valid authors remain, remove the authors field entirely - const { authors, ...rest } = filter; - return rest; + const { authors, ...rest } = filterWithAuthors; + return rest as Filter; } - return { ...filter, authors: validAuthors }; + return { ...filter, authors: validAuthors } as Filter; } return filter; }).filter(filter => { + const filterWithAuthors = filter as Filter & { authors?: string[] }; // Remove filters that have no valid query parameters return (filter.ids && filter.ids.length > 0) || - (filter.authors && filter.authors.length > 0) || + (filterWithAuthors.authors && filterWithAuthors.authors.length > 0) || (filter.kinds && filter.kinds.length > 0) || (filter['#e'] && filter['#e'].length > 0) || (filter['#p'] && filter['#p'].length > 0) || diff --git a/src/routes/about/+page.svelte b/src/routes/about/+page.svelte index fdb422c..3ff21d3 100644 --- a/src/routes/about/+page.svelte +++ b/src/routes/about/+page.svelte @@ -1,6 +1,7 @@