From ff4aaa00c85a20b53107431fea87c3c9e2c5e2b8 Mon Sep 17 00:00:00 2001 From: highperfocused Date: Sun, 6 Sep 2026 18:19:39 +0200 Subject: [PATCH] fix: reject empty-identifier addresses and surface bookmark load errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per review: - parseAddress() now rejects an empty d-identifier as malformed (e.g. "30023::") instead of producing a "#d: ['']" relay query and an unopenable bookmark. - useMyBookmarkedArticles() filters out matched events with empty content, the same non-renderable criteria the Reader's own list uses, so a broken/blank article can't land in the Bookmarked view. - BookmarksApp now distinguishes "the query failed" from "there are no bookmarks" — React Query leaves data undefined in both cases, so a relay/network failure no longer reads as an empty list. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto --- src/apps/bookmarks/index.tsx | 25 ++++++++++++++++++++++++- src/hooks/useBookmarks.ts | 14 +++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/apps/bookmarks/index.tsx b/src/apps/bookmarks/index.tsx index f8252d4..dbe4dea 100644 --- a/src/apps/bookmarks/index.tsx +++ b/src/apps/bookmarks/index.tsx @@ -5,6 +5,7 @@ import type { NostrEvent } from '@nostrify/nostrify'; import { AppBody, AppLayout, AppSectionTitle, AppToolbar, EmptyState } from '@/components/os/AppChrome'; import { LoginRequired } from '@/components/nostr/LoginRequired'; import { NoteCard } from '@/components/nostr/NoteCard'; +import { Button } from '@/components/ui/button'; import { Skeleton } from '@/components/ui/skeleton'; import { useAuthor } from '@/hooks/useAuthor'; import { useBookmarkedNoteIds, useMyBookmarkedArticles } from '@/hooks/useBookmarks'; @@ -45,7 +46,12 @@ export default function BookmarksApp({ setTitle }: AppProps) { } const isLoading = (noteIds.length > 0 && notes.isLoading) || articles.isLoading; - const isEmpty = !isLoading && (notes.data?.length ?? 0) === 0 && (articles.data?.length ?? 0) === 0; + // React Query leaves `data` undefined on a failed query too, so an error + // must be checked before treating "no data" as "no bookmarks" — otherwise + // a relay/network failure reads as an empty list. + const isError = notes.isError || articles.isError; + const isEmpty = + !isLoading && !isError && (notes.data?.length ?? 0) === 0 && (articles.data?.length ?? 0) === 0; return ( @@ -60,6 +66,23 @@ export default function BookmarksApp({ setTitle }: AppProps) { ))} + ) : isError ? ( + { + notes.refetch(); + articles.refetch(); + }} + > + Try again + + } + /> ) : isEmpty ? ( wanted.has(`${event.kind}:${event.pubkey}:${tagValue(event, 'd')}`)); + return events.filter( + (event) => + wanted.has(`${event.kind}:${event.pubkey}:${tagValue(event, 'd')}`) && + event.content.trim().length > 0, + ); }, staleTime: 60_000, });