mirror of
https://github.com/layer-systems/website.git
synced 2026-09-12 21:53:40 +02:00
fix: reject empty-identifier addresses and surface bookmark load errors
Per review: - parseAddress() now rejects an empty d-identifier as malformed (e.g. "30023:<pubkey>:") 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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BYiUtZMQeA5RHggQw73wto
This commit is contained in:
@@ -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 (
|
||||
<AppLayout>
|
||||
@@ -60,6 +66,23 @@ export default function BookmarksApp({ setTitle }: AppProps) {
|
||||
<Skeleton key={index} className="h-16 w-full" />
|
||||
))}
|
||||
</div>
|
||||
) : isError ? (
|
||||
<EmptyState
|
||||
title="Couldn't load your bookmarks"
|
||||
hint="None of your relays responded. Check the Relays app or try again."
|
||||
action={
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
notes.refetch();
|
||||
articles.refetch();
|
||||
}}
|
||||
>
|
||||
Try again
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
) : isEmpty ? (
|
||||
<EmptyState
|
||||
title="No bookmarks yet"
|
||||
|
||||
@@ -101,12 +101,16 @@ interface ParsedAddress {
|
||||
identifier: string;
|
||||
}
|
||||
|
||||
/** Parses a NIP-01 `kind:pubkey:d-identifier` address tag value, or null if malformed. */
|
||||
/**
|
||||
* Parses a NIP-01 `kind:pubkey:d-identifier` address tag value, or null if
|
||||
* malformed — including an empty identifier, which would otherwise produce
|
||||
* a `#d: ['']` relay query and a bookmark nothing can reliably resolve.
|
||||
*/
|
||||
function parseAddress(address: string): ParsedAddress | null {
|
||||
const [kindPart, pubkey, ...rest] = address.split(':');
|
||||
const kind = Number(kindPart);
|
||||
const identifier = rest.join(':');
|
||||
if (!Number.isInteger(kind) || !pubkey) return null;
|
||||
if (!Number.isInteger(kind) || !pubkey || !identifier) return null;
|
||||
return { kind, pubkey, identifier };
|
||||
}
|
||||
|
||||
@@ -148,7 +152,11 @@ export function useMyBookmarkedArticles() {
|
||||
{ signal: AbortSignal.any([signal, AbortSignal.timeout(6000)]) },
|
||||
);
|
||||
const wanted = new Set(addresses);
|
||||
return events.filter((event) => 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,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user