diff --git a/package-lock.json b/package-lock.json index 04c8a71e..df1e51a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jumble-imwald", - "version": "19.2.0", + "version": "19.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jumble-imwald", - "version": "19.2.0", + "version": "19.2.1", "license": "MIT", "dependencies": { "@asciidoctor/core": "^3.0.4", diff --git a/package.json b/package.json index 55972e9e..b222fe9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jumble-imwald", - "version": "19.2.0", + "version": "19.2.1", "description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble", "private": true, "type": "module", diff --git a/src/components/Explore/ExploreRelayReviews.tsx b/src/components/Explore/ExploreRelayReviews.tsx index 960db49c..259b9b7b 100644 --- a/src/components/Explore/ExploreRelayReviews.tsx +++ b/src/components/Explore/ExploreRelayReviews.tsx @@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next' const REVIEW_QUERY_LIMIT = 100 const SHOW_COUNT = 20 -/** Fewer sockets + faster aggregate EOSE than full inbox stack; read-only mirrors still appended then capped. */ +/** Fewer sockets + faster aggregate EOSE than full inbox stack; read-only mirrors prepended then capped. */ const EXPLORE_REVIEWS_MAX_RELAYS = 12 /** After all relays EOSE, wait longer than default so slow mirrors can flush events (default query eose is 500ms). */ const EXPLORE_REVIEWS_EOSE_TAIL_MS = 4500 diff --git a/src/pages/primary/SpellsPage/fauxSpellFeeds.ts b/src/pages/primary/SpellsPage/fauxSpellFeeds.ts index 02f56a35..8b7f03b7 100644 --- a/src/pages/primary/SpellsPage/fauxSpellFeeds.ts +++ b/src/pages/primary/SpellsPage/fauxSpellFeeds.ts @@ -4,9 +4,10 @@ * waiting for every relay to EOSE on a one-shot query. * * **Why faux feeds can feel slow:** each timeline shard opens live REQs over the prioritized relay - * stack (see {@link applyFauxSpellCapsToSubRequests}). The **interests** spell uses **one** shard: all subscribed - * topics go in a single `#t` filter (NIP-01 OR semantics). The notifications spell uses a narrow - * kind list vs full profile kinds. + * stack (see {@link applyFauxSpellCapsToSubRequests}). Read-only mirrors are **prepended** in + * {@link appendCuratedReadOnlyRelays} so the per-shard relay cap still includes aggregators (otherwise + * inbox+favorites fill the cap and global kinds/media/hashtags never hit aggr). The **interests** spell + * uses **one** shard: all subscribed topics in one `#t` filter (NIP-01 OR semantics). */ import { ExtendedKind, PROFILE_FEED_KINDS, READ_ONLY_RELAY_URLS } from '@/constants' import { buildProfileAugmentedReadRelayUrls } from '@/lib/favorites-feed-relays' @@ -17,7 +18,7 @@ import type { TFeedSubRequest } from '@/types' import { type Event, type Filter, kinds } from 'nostr-tools' /** Default caps for every faux spell feed (relays per subrequest, events per REQ). */ -export const FAUX_SPELL_MAX_RELAYS = 6 +export const FAUX_SPELL_MAX_RELAYS = 10 export const FAUX_SPELL_EVENT_LIMIT = 200 /** Profile Media tab: single REQ `limit` (matches merged cap in NoteList one-shot). */ @@ -68,21 +69,23 @@ export const NOTIFICATION_SPELL_KINDS = [ const INTERESTS_MAX_TOPICS = 80 /** - * Append {@link READ_ONLY_RELAY_URLS} (e.g. aggr) after the curated set so every faux REQ includes them unless blocked. + * Put {@link READ_ONLY_RELAY_URLS} (e.g. aggr) **first**, then curated relays. Faux spells cap URL count + * ({@link FAUX_SPELL_MAX_RELAYS}); appending read-only at the end dropped mirrors whenever inbox+favorites + * filled the cap. */ export function appendCuratedReadOnlyRelays(curated: string[], blockedRelays: string[]): string[] { const blocked = new Set(blockedRelays.map((b) => normalizeUrl(b) || b)) const seen = new Set() const out: string[] = [] - for (const u of curated) { + for (const u of READ_ONLY_RELAY_URLS) { const k = normalizeUrl(u) || u - if (!k || seen.has(k)) continue + if (!k || blocked.has(k) || seen.has(k)) continue seen.add(k) out.push(k) } - for (const u of READ_ONLY_RELAY_URLS) { + for (const u of curated) { const k = normalizeUrl(u) || u - if (!k || blocked.has(k) || seen.has(k)) continue + if (!k || seen.has(k)) continue seen.add(k) out.push(k) } diff --git a/src/pages/primary/SpellsPage/index.tsx b/src/pages/primary/SpellsPage/index.tsx index 8ee0d775..7c3bb90a 100644 --- a/src/pages/primary/SpellsPage/index.tsx +++ b/src/pages/primary/SpellsPage/index.tsx @@ -657,10 +657,14 @@ const SpellsPage = forwardRef(function SpellsPage( const syncFauxSubRequests = useMemo(() => { if (!selectedFauxSpell || selectedFauxSpell === 'following') return [] + /** Widen relay pool: these filters are not kind-1-only; skipping strip keeps fast-read mirrors in the stack. */ const fauxSpellSkipKind1Blocked = selectedFauxSpell === 'calendar' || selectedFauxSpell === 'discussions' || - selectedFauxSpell === 'followPacks' + selectedFauxSpell === 'followPacks' || + selectedFauxSpell === 'media' || + selectedFauxSpell === 'bookmarks' || + selectedFauxSpell === 'interests' const feedUrls = getRelayUrlsWithFavoritesFastReadAndInbox( favoriteRelays, blockedRelays, @@ -676,9 +680,7 @@ const SpellsPage = forwardRef(function SpellsPage( return [{ urls: feedUrls, filter: buildMentionsSpellFilter(pubkey) }] } if (selectedFauxSpell === 'discussions') { - // Same as followPacks: prioritized stack is capped (MAX_REQ_RELAY_URLS); tier-4 FAST_READ - // (incl. aggr) is often dropped when inbox + favorites fill the cap. Append read-only aggr so - // kind-11 discussions still resolve; also recover when feedUrls is empty (all blocked / no list). + // Read-only prepended in appendCuratedReadOnlyRelays so FAUX_SPELL_MAX_RELAYS still includes aggr. const urls = appendCuratedReadOnlyRelays(feedUrls, blockedRelays) if (!urls.length) return [] return [{ urls, filter: buildDiscussionFilter() }]