From fd54a07f5b3381e480e142f4753beeea8d04dfab Mon Sep 17 00:00:00 2001 From: Silberengel Date: Fri, 22 May 2026 15:16:05 +0200 Subject: [PATCH] bug-fix --- src/components/PostEditor/PostContent.tsx | 20 +++++++++++++ src/pages/secondary/RelayPage/index.tsx | 2 +- src/services/client.service.ts | 36 ++++++++++++----------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/components/PostEditor/PostContent.tsx b/src/components/PostEditor/PostContent.tsx index a5eaf70c..4632bbac 100644 --- a/src/components/PostEditor/PostContent.tsx +++ b/src/components/PostEditor/PostContent.tsx @@ -1408,6 +1408,15 @@ export default function PostContent({ if (parentEvent) { mergePublishedReplyIntoThread(cleanEvent, relayStatuses) + } else { + client.addEventToCache(cleanEvent) + if (openFrom?.length) { + for (const relayUrl of openFrom) { + window.dispatchEvent( + new CustomEvent('relay-refresh-needed', { detail: { relayUrl } }) + ) + } + } } onPublishSuccess?.() @@ -1452,6 +1461,17 @@ export default function PostContent({ const clean = { ...partialEvent } delete (clean as any).relayStatuses mergePublishedReplyIntoThread(clean, (error as any).relayStatuses) + } else if (partialEvent) { + const clean = { ...partialEvent } + delete (clean as any).relayStatuses + client.addEventToCache(clean) + if (openFrom?.length) { + for (const relayUrl of openFrom) { + window.dispatchEvent( + new CustomEvent('relay-refresh-needed', { detail: { relayUrl } }) + ) + } + } } postEditorCache.clearPostCache({ kind: getDeterminedKind, defaultContent, parentEvent }) if (isDiscussionThread && !parentEvent) { diff --git a/src/pages/secondary/RelayPage/index.tsx b/src/pages/secondary/RelayPage/index.tsx index f1000829..545dd69f 100644 --- a/src/pages/secondary/RelayPage/index.tsx +++ b/src/pages/secondary/RelayPage/index.tsx @@ -39,7 +39,7 @@ const RelayPage = forwardRef(({ url, index, hideTitlebar = false }: { url?: stri controls={hideTitlebar ? undefined : } displayScrollToTopButton > - + ) }) diff --git a/src/services/client.service.ts b/src/services/client.service.ts index 7950bb31..bc25366c 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -2848,28 +2848,31 @@ class ClientService extends EventTarget { connectionSlotPriority?: boolean } = {} ) { - let relays = Array.from(new Set(urls)) + const originalDedupedRelays = Array.from(new Set(urls)) + let wsRelayUrls = originalDedupedRelays if (navigator.onLine) { - relays = stripLocalNetworkRelaysForWssReq(relays) + // HTTPS index relays are polled via HTTP API — never WebSocket REQ (see httpTimelinePollBases below). + wsRelayUrls = stripLocalNetworkRelaysForWssReq(originalDedupedRelays) } else { // While offline, strip non-local relays before any further processing so the // capital-letter-tag fallback below cannot re-introduce internet relays. - relays = relays.filter((url) => isLocalNetworkUrl(url)) + wsRelayUrls = originalDedupedRelays.filter((url) => isLocalNetworkUrl(url)) } if (relayFiltersUseCapitalLetterTagKeys(filter as Filter)) { - relays = relayUrlsStripExtendedTagReqBlocked(relays) - if (relays.length === 0 && navigator.onLine && !relayAuthoritativeTimeline) { - relays = relayUrlsStripExtendedTagReqBlocked([...FAST_READ_RELAY_URLS]) + wsRelayUrls = relayUrlsStripExtendedTagReqBlocked(wsRelayUrls) + if (wsRelayUrls.length === 0 && navigator.onLine && !relayAuthoritativeTimeline) { + wsRelayUrls = relayUrlsStripExtendedTagReqBlocked([...FAST_READ_RELAY_URLS]) } } - const key = this.generateTimelineKey(relays, filter) + const timelineUrls = originalDedupedRelays + const key = this.generateTimelineKey(timelineUrls, filter) let timeline = this.timelines[key] if (!timeline || Array.isArray(timeline)) { this.timelines[key] = { refs: [], filter, - urls: relays, + urls: timelineUrls, ...(relayAuthoritativeTimeline ? { disablePersist: true as const } : {}) } timeline = this.timelines[key] @@ -2879,7 +2882,7 @@ class ClientService extends EventTarget { // relay sent a full `limit` batch whose newest row was still older than that head, `newRefs` became // empty and `tl.refs` was replaced with [] or failed to adopt fresh rows (feed looked permanently stale). timeline.filter = filter - timeline.urls = relays + timeline.urls = timelineUrls timeline.refs = [] if (relayAuthoritativeTimeline) { timeline.disablePersist = true @@ -2898,7 +2901,10 @@ class ClientService extends EventTarget { let eosedAt: number | null = null let eventIds = new Set() - const httpTimelinePollBases = httpIndexBasesForRelayQuery(relays, this.viewerHttpIndexRelayBases) + const httpTimelinePollBases = httpIndexBasesForRelayQuery( + originalDedupedRelays, + this.viewerHttpIndexRelayBases + ).filter((u) => !relaySessionStrikes.isReadHttpSkipped(u)) let httpPollIntervalId: ReturnType | null = null let httpPollCursorUnix = 0 const clearHttpTimelinePoll = () => { @@ -3112,7 +3118,7 @@ class ClientService extends EventTarget { that.timelines[key] = { refs: events.map((evt) => [evt.id, evt.created_at]), filter, - urls: relays, + urls: timelineUrls, ...(relayAuthoritativeTimeline ? { disablePersist: true as const } : {}) } } else if (tl.refs.length === 0) { @@ -3134,12 +3140,8 @@ class ClientService extends EventTarget { } // HTTP index relays are handled via httpTimelinePollBases above — never pass them to the WS subscribe path. - const httpPollKeys = new Set( - httpIndexBasesForRelayQuery(relays, this.viewerHttpIndexRelayBases).map((u) => - canonicalRelaySessionKey(u) - ) - ) - const wsRelays = relays.filter((u) => !httpPollKeys.has(canonicalRelaySessionKey(u))) + const httpPollKeys = new Set(httpTimelinePollBases.map((u) => canonicalRelaySessionKey(u))) + const wsRelays = wsRelayUrls.filter((u) => !httpPollKeys.has(canonicalRelaySessionKey(u))) // When there are HTTP relays but NO WS relays, subscribe([]) would fire oneose + onBatchEnd // immediately (via microtask) — before the HTTP initial poll returns any events. That causes: