diff --git a/src/shared/notes/mentions/user.tsx b/src/shared/notes/mentions/user.tsx
index 338c349b4..cc1df7d91 100644
--- a/src/shared/notes/mentions/user.tsx
+++ b/src/shared/notes/mentions/user.tsx
@@ -20,12 +20,7 @@ export const MentionUser = memo(function MentionUser({ pubkey }: { pubkey: strin
}
className="break-words text-blue-500 hover:text-blue-600"
>
- {'@' +
- (user?.name ||
- user?.display_name ||
- user?.displayName ||
- user?.username ||
- 'unknown')}
+ {'@' + (user?.name || user?.displayName || user?.username || 'unknown')}
);
});
diff --git a/src/shared/notes/preview/video.tsx b/src/shared/notes/preview/video.tsx
index 3f956388f..a21ab4aef 100644
--- a/src/shared/notes/preview/video.tsx
+++ b/src/shared/notes/preview/video.tsx
@@ -1,27 +1,19 @@
+import { MediaPlayer, MediaProvider } from '@vidstack/react';
import {
- MediaControlBar,
- MediaController,
- MediaFullscreenButton,
- MediaLoadingIndicator,
- MediaMuteButton,
- MediaPlayButton,
- MediaTimeRange,
-} from 'media-chrome/dist/react';
+ DefaultVideoLayout,
+ defaultLayoutIcons,
+} from '@vidstack/react/player/layouts/default';
export function VideoPreview({ url }: { url: string }) {
return (
-
-
-
-
-
-
-
-
-
-
+
+
+
);
}
diff --git a/src/shared/user.tsx b/src/shared/user.tsx
index 9f7b705e5..d348cf3c1 100644
--- a/src/shared/user.tsx
+++ b/src/shared/user.tsx
@@ -40,20 +40,33 @@ export const User = memo(function User({
embedProfile?: string;
subtext?: string;
}) {
- const { status, user } = useProfile(pubkey, embedProfile);
+ const { isLoading, user } = useProfile(pubkey, embedProfile);
- const createdAt = useMemo(() => formatCreatedAt(time, variant === 'chat'), [pubkey]);
- const svgURI = useMemo(
+ const createdAt = useMemo(() => formatCreatedAt(time, variant === 'chat'), [time]);
+ const fallbackName = useMemo(() => displayNpub(pubkey, 16), [pubkey]);
+ const fallbackAvatar = useMemo(
() => 'data:image/svg+xml;utf8,' + encodeURIComponent(minidenticon(pubkey, 90, 50)),
[pubkey]
);
if (variant === 'mention') {
- if (status === 'pending') {
+ if (isLoading) {
return (
-
-
+
+
+
+
+
+ {fallbackName}
+
+ ·
+ {createdAt}
+
);
}
@@ -70,7 +83,7 @@ export const User = memo(function User({
/>
@@ -78,10 +91,7 @@ export const User = memo(function User({
- {user?.name ||
- user?.display_name ||
- user?.displayName ||
- displayNpub(pubkey, 16)}
+ {user?.name || user?.display_name || user?.displayName || fallbackName}
·
{createdAt}
@@ -91,11 +101,19 @@ export const User = memo(function User({
}
if (variant === 'notify') {
- if (status === 'pending') {
+ if (isLoading) {
return (
-
-
+
+
+
+
+ {fallbackName}
+
);
}
@@ -112,24 +130,21 @@ export const User = memo(function User({
/>
- {user?.name ||
- user?.display_name ||
- user?.displayName ||
- displayNpub(pubkey, 16)}
+ {user?.name || user?.display_name || user?.displayName || fallbackName}
);
}
if (variant === 'large') {
- if (status === 'pending') {
+ if (isLoading) {
return (
@@ -153,7 +168,7 @@ export const User = memo(function User({
/>
@@ -172,7 +187,7 @@ export const User = memo(function User({
}
if (variant === 'simple') {
- if (status === 'pending') {
+ if (isLoading) {
return (
@@ -196,7 +211,7 @@ export const User = memo(function User({
/>
@@ -207,7 +222,7 @@ export const User = memo(function User({
{user?.name || user?.display_name || user?.displayName}
- {user?.nip05 || user?.username || displayNpub(pubkey, 16)}
+ {user?.nip05 || user?.username || fallbackName}
@@ -215,7 +230,7 @@ export const User = memo(function User({
}
if (variant === 'avatar') {
- if (status === 'pending') {
+ if (isLoading) {
return (
);
@@ -232,7 +247,7 @@ export const User = memo(function User({
/>
@@ -242,7 +257,7 @@ export const User = memo(function User({
}
if (variant === 'miniavatar') {
- if (status === 'pending') {
+ if (isLoading) {
return (
);
@@ -259,7 +274,7 @@ export const User = memo(function User({
/>
@@ -269,9 +284,23 @@ export const User = memo(function User({
}
if (variant === 'childnote') {
- if (status === 'pending') {
+ if (isLoading) {
return (
-
+ <>
+
+
+
+
+
{fallbackName}
+
+ {subtext}:
+
+
+ >
);
}
@@ -287,7 +316,7 @@ export const User = memo(function User({
/>
@@ -295,10 +324,7 @@ export const User = memo(function User({
- {user?.display_name ||
- user?.name ||
- user?.displayName ||
- displayNpub(pubkey, 16)}{' '}
+ {user?.display_name || user?.name || user?.displayName || fallbackName}{' '}
{subtext}:
@@ -309,7 +335,7 @@ export const User = memo(function User({
}
if (variant === 'stacked') {
- if (status === 'pending') {
+ if (isLoading) {
return (
);
@@ -326,7 +352,7 @@ export const User = memo(function User({
/>
@@ -336,7 +362,7 @@ export const User = memo(function User({
}
if (variant === 'ministacked') {
- if (status === 'pending') {
+ if (isLoading) {
return (
);
@@ -353,7 +379,7 @@ export const User = memo(function User({
/>
@@ -363,7 +389,7 @@ export const User = memo(function User({
}
if (variant === 'repost') {
- if (status === 'pending') {
+ if (isLoading) {
return (
@@ -389,11 +415,11 @@ export const User = memo(function User({
alt={pubkey}
loading="lazy"
decoding="async"
- className="h-6 w-6 rounded"
+ className="h-6 w-6 rounded object-cover"
/>
@@ -401,10 +427,7 @@ export const User = memo(function User({
- {user?.name ||
- user?.display_name ||
- user?.displayName ||
- displayNpub(pubkey, 16)}
+ {user?.name || user?.display_name || user?.displayName || fallbackName}
reposted
@@ -414,13 +437,13 @@ export const User = memo(function User({
}
if (variant === 'thread') {
- if (status === 'pending') {
+ if (isLoading) {
return (
-
+
-
);
@@ -434,11 +457,11 @@ export const User = memo(function User({
alt={pubkey}
loading="lazy"
decoding="async"
- className="h-10 w-10 rounded-lg ring-1 ring-neutral-200/50 dark:ring-neutral-800/50"
+ className="h-10 w-10 rounded-lg object-cover ring-1 ring-neutral-200/50 dark:ring-neutral-800/50"
/>
@@ -451,19 +474,27 @@ export const User = memo(function User({
{createdAt}
·
- {displayNpub(pubkey, 16)}
+ {fallbackName}
);
}
- if (status === 'pending') {
+ if (isLoading) {
return (
);
@@ -483,7 +514,7 @@ export const User = memo(function User({
/>
@@ -492,10 +523,7 @@ export const User = memo(function User({
- {user?.name ||
- user?.display_name ||
- user?.displayName ||
- displayNpub(pubkey, 16)}
+ {user?.name || user?.display_name || user?.displayName || fallbackName}
{createdAt}
@@ -515,11 +543,11 @@ export const User = memo(function User({
alt={pubkey}
loading="lazy"
decoding="async"
- className="h-10 w-10 rounded-lg"
+ className="h-10 w-10 rounded-lg object-cover"
/>
@@ -541,7 +569,7 @@ export const User = memo(function User({
/>
) : (
- {displayNpub(pubkey, 16)}
+ {fallbackName}
)}
diff --git a/src/shared/widgets/thread.tsx b/src/shared/widgets/thread.tsx
index 8e10d255c..dcb70fe25 100644
--- a/src/shared/widgets/thread.tsx
+++ b/src/shared/widgets/thread.tsx
@@ -21,7 +21,7 @@ import { useNostr } from '@utils/hooks/useNostr';
import { Widget } from '@utils/types';
export function ThreadWidget({ widget }: { widget: Widget }) {
- const { status, data } = useEvent(widget.content);
+ const { isFetching, isError, data } = useEvent(widget.content);
const { getEventThread } = useNostr();
const renderKind = useCallback(
@@ -59,16 +59,22 @@ export function ThreadWidget({ widget }: { widget: Widget }) {
- {status === 'pending' ? (
+ {isFetching ? (
) : (
<>
-
- {renderKind(data)}
-
+ {isError ? (
+
Failed to fetch event
+ ) : (
+ <>
+
+ {renderKind(data)}
+
+ >
+ )}
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index b0e140f1b..e11b57e32 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -1,9 +1,3 @@
-export const FULL_RELAYS = [
- 'wss://relay.damus.io',
- 'wss://relay.nostr.band/all',
- 'wss://nostr.mutinywallet.com',
-];
-
export const FETCH_LIMIT = 20;
export const HASHTAGS = [
diff --git a/src/utils/hooks/useEvent.ts b/src/utils/hooks/useEvent.ts
index 6082ff740..7617aba31 100644
--- a/src/utils/hooks/useEvent.ts
+++ b/src/utils/hooks/useEvent.ts
@@ -1,4 +1,4 @@
-import { NDKEvent } from '@nostr-dev-kit/ndk';
+import { NDKEvent, NDKSubscriptionCacheUsage, NostrEvent } from '@nostr-dev-kit/ndk';
import { useQuery } from '@tanstack/react-query';
import { nip19 } from 'nostr-tools';
import { AddressPointer } from 'nostr-tools/lib/types/nip19';
@@ -7,7 +7,7 @@ import { useNDK } from '@libs/ndk/provider';
export function useEvent(id: undefined | string, embed?: undefined | string) {
const { ndk } = useNDK();
- const { status, data } = useQuery({
+ const { status, isFetching, isError, data } = useQuery({
queryKey: ['event', id],
queryFn: async () => {
const naddr = id.startsWith('naddr')
@@ -24,27 +24,33 @@ export function useEvent(id: undefined | string, embed?: undefined | string) {
const rEvent = [...rEvents].slice(-1)[0];
- if (!rEvent) return Promise.reject(new Error('event not found'));
+ if (!rEvent) throw new Error('event not found');
return rEvent;
}
// return embed event (nostr.band api)
if (embed) {
- const event: NDKEvent = JSON.parse(embed);
- return event;
+ const embedEvent: NostrEvent = JSON.parse(embed);
+ const ndkEvent = new NDKEvent(ndk, embedEvent);
+
+ return ndkEvent;
}
// get event from relay
- const event = await ndk.fetchEvent(id);
+ const event = await ndk.fetchEvent(id, {
+ cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
+ });
+
+ if (!event)
+ throw new Error(`Cannot get event with ${id}, will be retry after 10 seconds`);
- if (!event) return Promise.reject(new Error('event not found'));
return event;
},
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
- staleTime: Infinity,
+ retry: 2,
});
- return { status, data };
+ return { status, isFetching, isError, data };
}
diff --git a/src/utils/hooks/useProfile.ts b/src/utils/hooks/useProfile.ts
index 918b2ec1c..c9b10ac9d 100644
--- a/src/utils/hooks/useProfile.ts
+++ b/src/utils/hooks/useProfile.ts
@@ -1,48 +1,54 @@
-import { NDKUserProfile } from '@nostr-dev-kit/ndk';
-import { useQuery, useQueryClient } from '@tanstack/react-query';
+import { NDKSubscriptionCacheUsage, NDKUserProfile } from '@nostr-dev-kit/ndk';
+import { useQuery } from '@tanstack/react-query';
import { nip19 } from 'nostr-tools';
import { useNDK } from '@libs/ndk/provider';
export function useProfile(pubkey: string, embed?: string) {
- const queryClient = useQueryClient();
const { ndk } = useNDK();
const {
- status,
+ isLoading,
+ isError,
data: user,
- error,
} = useQuery({
queryKey: ['user', pubkey],
queryFn: async () => {
- // parse data from nostr.band api
- if (embed) {
- const profile: NDKUserProfile = JSON.parse(embed);
- return profile;
- }
+ try {
+ // parse data from nostr.band api
+ if (embed) {
+ const profile: NDKUserProfile = JSON.parse(embed);
+ return profile;
+ }
- // get clean pubkey without any special characters
- let hexstring = pubkey.replace(/[^a-zA-Z0-9]/g, '');
+ // get clean pubkey without any special characters
+ let hexstring = pubkey.replace(/[^a-zA-Z0-9]/g, '');
- if (hexstring.startsWith('npub1') || hexstring.startsWith('nprofile1')) {
- const decoded = nip19.decode(hexstring);
- if (decoded.type === 'nprofile') hexstring = decoded.data.pubkey;
- if (decoded.type === 'npub') hexstring = decoded.data;
- }
+ if (hexstring.startsWith('npub1') || hexstring.startsWith('nprofile1')) {
+ const decoded = nip19.decode(hexstring);
+ if (decoded.type === 'nprofile') hexstring = decoded.data.pubkey;
+ if (decoded.type === 'npub') hexstring = decoded.data;
+ }
- const user = ndk.getUser({ pubkey: hexstring });
- const profile = await user.fetchProfile();
+ const user = ndk.getUser({ pubkey: hexstring });
+ const profile = await user.fetchProfile({
+ cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
+ });
- if (!profile)
- throw new Error(
- `Cannot get metadata for ${pubkey}, will be retry after 10 seconds`
- );
- return profile;
+ if (!profile)
+ throw new Error(
+ `Cannot get metadata for ${pubkey}, will be retry after 10 seconds`
+ );
+
+ return profile;
+ } catch (e) {
+ throw new Error(e);
+ }
},
- initialData: () => queryClient.getQueryData(['user', pubkey]) as NDKUserProfile,
+ refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
retry: 2,
});
- return { status, user, error };
+ return { isLoading, isError, user };
}