Browse Source

bug-fixes

imwald
Silberengel 1 month ago
parent
commit
9302260cad
  1. 1
      src/components/ErrorBoundary.tsx
  2. 8
      src/components/NoteList/index.tsx
  3. 6
      src/lib/wisp-trending-relay.ts
  4. 53
      src/services/client.service.ts

1
src/components/ErrorBoundary.tsx

@ -16,6 +16,7 @@ function isLikelyBrokenReactContextFromHmr(message: string): boolean {
return ( return (
/must be used within (a )?[\w]+/i.test(message) || /must be used within (a )?[\w]+/i.test(message) ||
message.includes('useNostr must be used within') || message.includes('useNostr must be used within') ||
message.includes('useContentPolicy must be used within') ||
message.includes('useInterestList must be used within') || message.includes('useInterestList must be used within') ||
(message.includes('useContext') && message.includes('null')) (message.includes('useContext') && message.includes('null'))
) )

8
src/components/NoteList/index.tsx

@ -27,7 +27,7 @@ import { isLocalNetworkUrl, normalizeUrl } from '@/lib/url'
import { eventPassesNoteListKindPicker } from '@/lib/feed-kind-filter' import { eventPassesNoteListKindPicker } from '@/lib/feed-kind-filter'
import { shouldIncludeZapReceiptAtReplyThreshold } from '@/lib/event-metadata' import { shouldIncludeZapReceiptAtReplyThreshold } from '@/lib/event-metadata'
import { isTouchDevice } from '@/lib/utils' import { isTouchDevice } from '@/lib/utils'
import { useContentPolicy } from '@/providers/ContentPolicyProvider' import { useContentPolicyOptional } from '@/providers/ContentPolicyProvider'
import { useDeletedEvent } from '@/providers/DeletedEventProvider' import { useDeletedEvent } from '@/providers/DeletedEventProvider'
import { useMuteList } from '@/contexts/mute-list-context' import { useMuteList } from '@/contexts/mute-list-context'
import { muteSetHas } from '@/lib/mute-set' import { muteSetHas } from '@/lib/mute-set'
@ -827,7 +827,11 @@ const NoteList = forwardRef(
const { startLogin, pubkey } = useNostr() const { startLogin, pubkey } = useNostr()
const { isUserTrusted } = useUserTrust() const { isUserTrusted } = useUserTrust()
const { mutePubkeySet } = useMuteList() const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers, isOffline } = useContentPolicy() const contentPolicy = useContentPolicyOptional()
const hideContentMentioningMutedUsers = contentPolicy?.hideContentMentioningMutedUsers ?? false
const isOffline =
contentPolicy?.isOffline ??
(!navigator.onLine || (navigator as Navigator & { connection?: { type?: string } }).connection?.type === 'none')
const { isEventDeleted } = useDeletedEvent() const { isEventDeleted } = useDeletedEvent()
const { zapReplyThreshold } = useZap() const { zapReplyThreshold } = useZap()
const { favoriteRelays, blockedRelays } = useFavoriteRelays() const { favoriteRelays, blockedRelays } = useFavoriteRelays()

6
src/lib/wisp-trending-relay.ts

@ -2,9 +2,9 @@ import { ExtendedKind } from '@/constants'
import { normalizeUrl } from '@/lib/url' import { normalizeUrl } from '@/lib/url'
/** /**
* Trending notes stream from nostrarchives, consumed by * Trending notes stream from nostrarchives (path-based relay URL). The WebSocket speaks **standard NIP-01**
* {@link https://github.com/barrydeen/wisp | Wisp} (Android). Same URL shape as Wisp’s * `REQ` / `EVENT` / `EOSE` safe for nostr-tools {@link SimplePool}. Same URL shape as Wisps
* `buildTrendingRelayUrl` / `FEED_KINDS` REQ. * {@link https://github.com/barrydeen/wisp | Wisp} (Android) `buildTrendingRelayUrl` / `FEED_KINDS` REQ.
*/ */
export type WispTrendingMetric = 'reactions' | 'replies' | 'reposts' | 'zaps' export type WispTrendingMetric = 'reactions' | 'replies' | 'reposts' | 'zaps'

53
src/services/client.service.ts

@ -622,6 +622,50 @@ class ClientService extends EventTarget {
}) })
} }
/**
* When the user explicitly picked relays, reorder **only within that list** using a bounded
* {@link fetchRelayListWithPublishTimeout} for the author not {@link fetchRelayLists} for every
* reply/mention context (which could stall publish for a long time on slow or failing relays).
*/
private async prioritizeSpecifiedRelayPickerUrls(
pickerUrls: string[],
event: NEvent,
favoriteRelayUrls: string[] = []
): Promise<string[]> {
const deduped = dedupeNormalizeRelayUrlsOrdered(pickerUrls)
let relayList: TRelayList
try {
relayList = await this.fetchRelayListWithPublishTimeout(event.pubkey)
} catch {
relayList = this.emptyRelayListForPublish()
}
const writeSet = new Set<string>()
for (const u of relayList.write ?? []) {
const n = normalizeUrl(u) || u
if (n) writeSet.add(n)
}
for (const u of relayList.httpWrite ?? []) {
const n = normalizeHttpRelayUrl(u) || u
if (n) writeSet.add(n)
}
const favSet = new Set(
favoriteRelayUrls.map((f) => normalizeUrl(f) || f).filter((u): u is string => !!u)
)
const outbox: string[] = []
const favRest: string[] = []
const other: string[] = []
for (const u of deduped) {
const n = normalizeAnyRelayUrl(u) || u
if (!n) continue
if (writeSet.has(n)) outbox.push(u)
else if (favSet.has(n)) favRest.push(u)
else other.push(u)
}
const merged = dedupeNormalizeRelayUrlsOrdered([...outbox, ...favRest, ...other])
return this.filterPublishingRelays(merged, event).slice(0, MAX_PUBLISH_RELAYS)
}
private async prioritizePublishUrlList( private async prioritizePublishUrlList(
relayUrls: string[], relayUrls: string[],
event: NEvent, event: NEvent,
@ -632,7 +676,7 @@ class ClientService extends EventTarget {
const pubkeyOrder = Array.from(new Set([event.pubkey, ...ctx])) const pubkeyOrder = Array.from(new Set([event.pubkey, ...ctx]))
let lists: TRelayList[] = [] let lists: TRelayList[] = []
try { try {
lists = await this.fetchRelayLists(pubkeyOrder) lists = await this.fetchRelayListsWithPublishTimeout(pubkeyOrder)
} catch { } catch {
lists = [] lists = []
} }
@ -1120,7 +1164,12 @@ class ClientService extends EventTarget {
if (specifiedRelayUrls?.length) { if (specifiedRelayUrls?.length) {
const checkedCount = specifiedRelayUrls.length const checkedCount = specifiedRelayUrls.length
relays = await this.prioritizePublishUrlListWithTimeout(relays, event, favoriteRelayUrls ?? []) /**
* User already chose relays do not block publish on {@link fetchRelayLists} for every reply/mention
* context pubkey (can take tens of seconds on bad networks). Reorder only within the picker set:
* author's NIP-65 write relays first, then favorites among the selection, then remaining picker order.
*/
relays = await this.prioritizeSpecifiedRelayPickerUrls(relays, event, favoriteRelayUrls ?? [])
if (checkedCount > relays.length) { if (checkedCount > relays.length) {
logger.info('[Publish] Relay picker: checked count exceeds per-publish cap (stage 1)', { logger.info('[Publish] Relay picker: checked count exceeds per-publish cap (stage 1)', {
checkedInRelayPicker: checkedCount, checkedInRelayPicker: checkedCount,

Loading…
Cancel
Save