Browse Source

bug-fixes

imwald
Silberengel 1 month ago
parent
commit
e9686c9193
  1. 18
      src/components/NoteList/index.tsx
  2. 21
      src/components/Relay/index.tsx
  3. 4
      src/components/Settings/SettingsMenuBody.tsx
  4. 2
      src/constants.ts
  5. 32
      src/services/client.service.ts

18
src/components/NoteList/index.tsx

@ -2054,8 +2054,15 @@ const NoteList = forwardRef(
if (oneShotFetch || mappedSubRequests.length === 0) return if (oneShotFetch || mappedSubRequests.length === 0) return
if (isSpellPageLocalWarmup) return if (isSpellPageLocalWarmup) return
const diskReq = mappedSubRequests as Array<{ urls: string[]; filter: TSubRequestFilter }> const diskReq = mappedSubRequests as Array<{ urls: string[]; filter: TSubRequestFilter }>
const strictSingleRelayShard =
mappedSubRequests.length === 1 &&
mappedSubRequests[0]!.urls.length === 1 &&
(hostPrimaryPageNameRef.current === 'relay' ||
(allowKindlessRelayExploreRef.current && useFilterAsIsRef.current))
void client void client
.getLocalFeedEvents(diskReq) .getLocalFeedEvents(diskReq, {
strictRelayShardSourcesOnly: strictSingleRelayShard
})
.then((diskRaw) => { .then((diskRaw) => {
if (!effectActive || timelineEffectStale()) return if (!effectActive || timelineEffectStale()) return
const diskNarrowed = narrowLiveBatch(diskRaw) const diskNarrowed = narrowLiveBatch(diskRaw)
@ -2429,8 +2436,15 @@ const NoteList = forwardRef(
urls: string[] urls: string[]
filter: TSubRequestFilter filter: TSubRequestFilter
}> }>
const strictSingleRelayShardOneShot =
mappedSubRequests.length === 1 &&
mappedSubRequests[0]!.urls.length === 1 &&
(hostPrimaryPageNameRef.current === 'relay' ||
(allowKindlessRelayExploreRef.current && useFilterAsIsRef.current))
void client void client
.getLocalFeedEvents(diskReqOneShot) .getLocalFeedEvents(diskReqOneShot, {
strictRelayShardSourcesOnly: strictSingleRelayShardOneShot
})
.then((diskRaw) => { .then((diskRaw) => {
if (!effectActive || timelineEffectStale()) return if (!effectActive || timelineEffectStale()) return
if (diskRaw.length === 0) return if (diskRaw.length === 0) return

21
src/components/Relay/index.tsx

@ -7,8 +7,10 @@ import type { TPrimaryPageName } from '@/PageManager'
import { SINGLE_RELAY_KINDLESS_REQ_LIMIT } from '@/constants' import { SINGLE_RELAY_KINDLESS_REQ_LIMIT } from '@/constants'
import { normalizeAnyRelayUrl } from '@/lib/url' import { normalizeAnyRelayUrl } from '@/lib/url'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider' import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import client from '@/services/client.service'
import type { TFeedSubRequest } from '@/types' import type { TFeedSubRequest } from '@/types'
import { forwardRef, useEffect, useMemo, useRef, useState } from 'react' import type { Event } from 'nostr-tools'
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import NotFound from '../NotFound' import NotFound from '../NotFound'
@ -77,6 +79,21 @@ const Relay = forwardRef<
] ]
}, [normalizedUrl, debouncedInput]) }, [normalizedUrl, debouncedInput])
/** When we know delivery relays, drop rows that never arrived from this feed’s relay (stale cache / mis-tagged). */
const relaySeenMatchKey = useMemo(
() => (normalizedUrl ? (normalizeAnyRelayUrl(normalizedUrl) || normalizedUrl).toLowerCase() : ''),
[normalizedUrl]
)
const shouldHideEventNotFromThisRelay = useCallback(
(ev: Event) => {
if (!relaySeenMatchKey) return false
const seen = client.getSeenEventRelayUrls(ev.id)
if (seen.length === 0) return false
return !seen.some((u) => (normalizeAnyRelayUrl(u) || u).toLowerCase() === relaySeenMatchKey)
},
[relaySeenMatchKey]
)
if (!normalizedUrl) { if (!normalizedUrl) {
return <NotFound /> return <NotFound />
} }
@ -101,6 +118,8 @@ const Relay = forwardRef<
showAllKinds showAllKinds
showFeedClientFilter showFeedClientFilter
hostPrimaryPageName={hostPrimaryPageName} hostPrimaryPageName={hostPrimaryPageName}
extraShouldHideEvent={shouldHideEventNotFromThisRelay}
extraShouldHideRepliesEvent={shouldHideEventNotFromThisRelay}
/> />
</div> </div>
) )

4
src/components/Settings/SettingsMenuBody.tsx

@ -144,10 +144,6 @@ export default function SettingsMenuBody({ className }: { className?: string })
</div> </div>
</SettingItem> </SettingItem>
</AboutInfoDialog> </AboutInfoDialog>
<div className="py-6 text-center text-muted-foreground">
<div className="app-chrome-title">Imwald</div>
<div className="font-semibold text-green-600 dark:text-green-500">Im Wald</div>
</div>
</div> </div>
) )
} }

2
src/constants.ts

@ -73,7 +73,7 @@ export const DESKTOP_APP_DOWNLOAD_URL_DEFAULT =
export const DEFAULT_FAVORITE_RELAYS = [ export const DEFAULT_FAVORITE_RELAYS = [
'wss://theforest.nostr1.com', 'wss://theforest.nostr1.com',
'wss://orly-relay.imwald.eu', 'wss://christpill.nostr1.com',
'wss://nostr.land', 'wss://nostr.land',
'wss://nostr21.com' 'wss://nostr21.com'
] ]

32
src/services/client.service.ts

@ -1895,7 +1895,16 @@ class ClientService extends EventTarget {
async getLocalFeedEvents( async getLocalFeedEvents(
subRequests: { urls: string[]; filter: TSubRequestFilter }[], subRequests: { urls: string[]; filter: TSubRequestFilter }[],
options?: { maxRowsScanned?: number; maxMatches?: number } options?: {
maxRowsScanned?: number
maxMatches?: number
/**
* When true, only load rows persisted for this feeds timeline shard(s) no global session scan or
* archive/publication sweeps. Used for single-relay explore so kindless `{ limit }` does not match every
* cached note while the UI is scoped to one relay.
*/
strictRelayShardSourcesOnly?: boolean
}
): Promise<NEvent[]> { ): Promise<NEvent[]> {
if (!subRequests.length) return [] if (!subRequests.length) return []
const filters = subRequests.map(({ filter }) => filter as Filter) const filters = subRequests.map(({ filter }) => filter as Filter)
@ -1921,6 +1930,14 @@ class ClientService extends EventTarget {
} }
} }
if (options?.strictRelayShardSourcesOnly) {
const timelineRows = await this.getTimelineDiskSnapshotEvents(subRequests).catch(() => [] as NEvent[])
add(timelineRows)
return [...byId.values()]
.sort((a, b) => b.created_at - a.created_at || b.id.localeCompare(a.id))
.slice(0, maxMatches)
}
add(this.eventService.getSessionEventsMatchingFilters(filters, maxMatches)) add(this.eventService.getSessionEventsMatchingFilters(filters, maxMatches))
const [timelineRows, archiveRows, publicationRows] = await Promise.all([ const [timelineRows, archiveRows, publicationRows] = await Promise.all([
@ -3285,6 +3302,7 @@ class ClientService extends EventTarget {
}) })
let relayListResolved = 0 let relayListResolved = 0
let contactsResolved = 0 let contactsResolved = 0
let profileResolved = 0
const chunkSize = 20 const chunkSize = 20
for (let i = 0; i * chunkSize < followings.length; i++) { for (let i = 0; i * chunkSize < followings.length; i++) {
if (signal.aborted) { if (signal.aborted) {
@ -3292,20 +3310,24 @@ class ClientService extends EventTarget {
return return
} }
const chunk = followings.slice(i * chunkSize, (i + 1) * chunkSize) const chunk = followings.slice(i * chunkSize, (i + 1) * chunkSize)
const [relayListEvents, contactsEvents] = await Promise.all([ const [relayListEvents, contactsEvents, metadataEvents] = await Promise.all([
this.replaceableEventService.fetchReplaceableEventsFromProfileFetchRelays(chunk, kinds.RelayList), this.replaceableEventService.fetchReplaceableEventsFromProfileFetchRelays(chunk, kinds.RelayList),
this.replaceableEventService.fetchReplaceableEventsFromProfileFetchRelays(chunk, kinds.Contacts), this.replaceableEventService.fetchReplaceableEventsFromProfileFetchRelays(chunk, kinds.Contacts),
Promise.all(chunk.map((pk) => this.fetchProfileEvent(pk))) this.replaceableEventService.fetchReplaceableEventsFromProfileFetchRelays(chunk, kinds.Metadata)
]) ])
relayListResolved += relayListEvents.filter(Boolean).length relayListResolved += relayListEvents.filter(Boolean).length
contactsResolved += contactsEvents.filter(Boolean).length contactsResolved += contactsEvents.filter(Boolean).length
await new Promise((resolve) => setTimeout(resolve, 1000)) const profiles = metadataEvents.filter((ev): ev is NEvent => Boolean(ev))
profileResolved += profiles.length
await Promise.allSettled(profiles.map((ev) => this.addUsernameToIndex(ev)))
profiles.forEach((ev) => this.updateProfileEventCache(ev))
} }
logger.info('[client] Prewarm: following profile + contacts + NIP-65 fetch finished', { logger.info('[client] Prewarm: following profile + contacts + NIP-65 fetch finished', {
pubkeySlice: pubkey.slice(0, 12), pubkeySlice: pubkey.slice(0, 12),
followingCount: followings.length, followingCount: followings.length,
relayListEventsResolved: relayListResolved, relayListEventsResolved: relayListResolved,
contactsEventsResolved: contactsResolved contactsEventsResolved: contactsResolved,
profileEventsResolved: profileResolved
}) })
} }

Loading…
Cancel
Save