From 9267458bcaae8c465a62e374e99c09c9aaeb76d4 Mon Sep 17 00:00:00 2001 From: codytseng Date: Tue, 23 Sep 2025 22:42:25 +0800 Subject: [PATCH] feat: show relay close reasons in certain feeds --- src/components/NormalFeed/index.tsx | 7 ++++-- src/components/NoteList/index.tsx | 10 +++++++- src/components/Relay/index.tsx | 1 + src/components/SearchResult/index.tsx | 2 ++ src/pages/primary/NoteListPage/RelaysFeed.tsx | 1 + src/providers/NotificationProvider.tsx | 2 +- src/services/client.service.ts | 23 +++++++++++++------ 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/components/NormalFeed/index.tsx b/src/components/NormalFeed/index.tsx index c8516a8..734b376 100644 --- a/src/components/NormalFeed/index.tsx +++ b/src/components/NormalFeed/index.tsx @@ -1,5 +1,6 @@ import NoteList, { TNoteListRef } from '@/components/NoteList' import Tabs from '@/components/Tabs' +import { isTouchDevice } from '@/lib/utils' import { useKindFilter } from '@/providers/KindFilterProvider' import { useUserTrust } from '@/providers/UserTrustProvider' import storage from '@/services/local-storage.service' @@ -7,16 +8,17 @@ import { TFeedSubRequest, TNoteListMode } from '@/types' import { useMemo, useRef, useState } from 'react' import KindFilter from '../KindFilter' import { RefreshButton } from '../RefreshButton' -import { isTouchDevice } from '@/lib/utils' export default function NormalFeed({ subRequests, areAlgoRelays = false, - isMainFeed = false + isMainFeed = false, + showRelayCloseReason = false }: { subRequests: TFeedSubRequest[] areAlgoRelays?: boolean isMainFeed?: boolean + showRelayCloseReason?: boolean }) { const { hideUntrustedNotes } = useUserTrust() const { showKinds } = useKindFilter() @@ -63,6 +65,7 @@ export default function NormalFeed({ hideReplies={listMode === 'posts'} hideUntrustedNotes={hideUntrustedNotes} areAlgoRelays={areAlgoRelays} + showRelayCloseReason={showRelayCloseReason} /> ) diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index a470b32..ffcaada 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -27,6 +27,7 @@ import { } from 'react' import { useTranslation } from 'react-i18next' import PullToRefresh from 'react-simple-pull-to-refresh' +import { toast } from 'sonner' import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard' const LIMIT = 200 @@ -41,7 +42,8 @@ const NoteList = forwardRef( filterMutedNotes = true, hideReplies = false, hideUntrustedNotes = false, - areAlgoRelays = false + areAlgoRelays = false, + showRelayCloseReason = false }: { subRequests: TFeedSubRequest[] showKinds: number[] @@ -49,6 +51,7 @@ const NoteList = forwardRef( hideReplies?: boolean hideUntrustedNotes?: boolean areAlgoRelays?: boolean + showRelayCloseReason?: boolean }, ref ) => { @@ -184,6 +187,11 @@ const NoteList = forwardRef( [event, ...oldEvents].sort((a, b) => b.created_at - a.created_at) ) } + }, + onClose: (url, reason) => { + if (!showRelayCloseReason) return + if (reason === 'closed by caller') return + toast.error(`${url}: ${reason}`) } }, { diff --git a/src/components/Relay/index.tsx b/src/components/Relay/index.tsx index 9791367..6e6005e 100644 --- a/src/components/Relay/index.tsx +++ b/src/components/Relay/index.tsx @@ -55,6 +55,7 @@ export default function Relay({ url, className }: { url?: string; className?: st subRequests={[ { urls: [normalizedUrl], filter: debouncedInput ? { search: debouncedInput } : {} } ]} + showRelayCloseReason /> ) diff --git a/src/components/SearchResult/index.tsx b/src/components/SearchResult/index.tsx index bf2e71a..beaddaa 100644 --- a/src/components/SearchResult/index.tsx +++ b/src/components/SearchResult/index.tsx @@ -20,6 +20,7 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa return ( ) } @@ -27,6 +28,7 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa return ( ) } diff --git a/src/pages/primary/NoteListPage/RelaysFeed.tsx b/src/pages/primary/NoteListPage/RelaysFeed.tsx index e600f2a..93b7397 100644 --- a/src/pages/primary/NoteListPage/RelaysFeed.tsx +++ b/src/pages/primary/NoteListPage/RelaysFeed.tsx @@ -31,6 +31,7 @@ export default function RelaysFeed() { subRequests={[{ urls: relayUrls, filter: {} }]} areAlgoRelays={areAlgoRelays} isMainFeed + showRelayCloseReason /> ) } diff --git a/src/providers/NotificationProvider.tsx b/src/providers/NotificationProvider.tsx index 6463c6b..59770b0 100644 --- a/src/providers/NotificationProvider.tsx +++ b/src/providers/NotificationProvider.tsx @@ -140,7 +140,7 @@ export function NotificationProvider({ children }: { children: React.ReactNode } }) } }, - onclose: (reasons) => { + onAllClose: (reasons) => { if (reasons.every((reason) => reason === 'closed by caller')) { return } diff --git a/src/services/client.service.ts b/src/services/client.service.ts index ae268c4..fe674b6 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -238,10 +238,12 @@ class ClientService extends EventTarget { subRequests: { urls: string[]; filter: TSubRequestFilter }[], { onEvents, - onNew + onNew, + onClose }: { onEvents: (events: NEvent[], eosed: boolean) => void onNew: (evt: NEvent) => void + onClose?: (url: string, reason: string) => void }, { startLogin, @@ -285,7 +287,8 @@ class ClientService extends EventTarget { if (newEventIdSet.has(evt.id)) return newEventIdSet.add(evt.id) onNew(evt) - } + }, + onClose }, { startLogin, needSort } ) @@ -337,12 +340,14 @@ class ClientService extends EventTarget { onevent, oneose, onclose, - startLogin + startLogin, + onAllClose }: { onevent?: (evt: NEvent) => void oneose?: (eosed: boolean) => void - onclose?: (reasons: string[]) => void + onclose?: (url: string, reason: string) => void startLogin?: () => void + onAllClose?: (reasons: string[]) => void } ) { const relays = Array.from(new Set(urls)) @@ -437,8 +442,9 @@ class ClientService extends EventTarget { // close the subscription closedCount++ closeReasons.push(reason) + onclose?.(url, reason) if (closedCount >= startedCount) { - onclose?.(closeReasons) + onAllClose?.(closeReasons) } return }, @@ -467,10 +473,12 @@ class ClientService extends EventTarget { filter: TSubRequestFilter, // filter with limit, { onEvents, - onNew + onNew, + onClose }: { onEvents: (events: NEvent[], eosed: boolean) => void onNew: (evt: NEvent) => void + onClose?: (url: string, reason: string) => void }, { startLogin, @@ -575,7 +583,8 @@ class ClientService extends EventTarget { timeline.refs = newRefs.concat(timeline.refs) onEvents([...events.concat(cachedEvents).slice(0, filter.limit)], true) } - } + }, + onclose: onClose }) return {