+
-
-
+ {metadata.image && (
+
+ )}
+
{metadata.title}
{metadata.summary}
-
{metadata.publishedAt.toString()}
-
+
);
}
diff --git a/src/shared/notes/kinds/articleDetail.tsx b/src/shared/notes/kinds/articleDetail.tsx
new file mode 100644
index 00000000..5309fa19
--- /dev/null
+++ b/src/shared/notes/kinds/articleDetail.tsx
@@ -0,0 +1,37 @@
+import { NDKEvent } from '@nostr-dev-kit/ndk';
+import { useMemo } from 'react';
+import ReactMarkdown from 'react-markdown';
+import { Link } from 'react-router-dom';
+import remarkGfm from 'remark-gfm';
+
+import { Image } from '@shared/image';
+
+export function ArticleDetailNote({ event }: { event: NDKEvent }) {
+ const metadata = useMemo(() => {
+ const title = event.tags.find((tag) => tag[0] === 'title')?.[1];
+ const image = event.tags.find((tag) => tag[0] === 'image')?.[1];
+ const summary = event.tags.find((tag) => tag[0] === 'summary')?.[1];
+
+ let publishedAt: Date | string | number = event.tags.find(
+ (tag) => tag[0] === 'published_at'
+ )?.[1];
+ if (publishedAt) {
+ publishedAt = new Date(parseInt(publishedAt)).toLocaleDateString('en-US');
+ } else {
+ publishedAt = new Date(event.created_at * 1000).toLocaleDateString('en-US');
+ }
+
+ return {
+ title,
+ image,
+ publishedAt,
+ summary,
+ };
+ }, [event.id]);
+
+ return (
+
+ {event.content}
+
+ );
+}
diff --git a/src/shared/notes/kinds/text.tsx b/src/shared/notes/kinds/text.tsx
index 70996a08..76dfe6ea 100644
--- a/src/shared/notes/kinds/text.tsx
+++ b/src/shared/notes/kinds/text.tsx
@@ -26,11 +26,16 @@ export function TextNote({ event }: { event: NDKEvent }) {
del: ({ children }) => {
const key = children[0] as string;
if (typeof key !== 'string') return;
- if (key.startsWith('pub') && key.length > 50 && key.length < 100)
+ if (key.startsWith('pub') && key.length > 50 && key.length < 100) {
return
;
- if (key.startsWith('tag')) return
;
+ }
+ if (key.startsWith('tag')) {
+ return
;
+ }
},
}}
+ disallowedElements={['h1', 'h2', 'h3', 'h4', 'h5', 'h6']}
+ unwrapDisallowed={true}
>
{content?.parsed}
diff --git a/src/shared/notes/preview/image.tsx b/src/shared/notes/preview/image.tsx
index 1ce377f1..38ee59d8 100644
--- a/src/shared/notes/preview/image.tsx
+++ b/src/shared/notes/preview/image.tsx
@@ -12,14 +12,13 @@ export function ImagePreview({ urls, truncate }: { urls: string[]; truncate?: bo
};
return (
-
+
{urls.map((url) => (
-
+
+ {event?.replies?.length > 0 && (
+
+ )}
+
-
+
-
- {event.replies ? (
- event.replies.map((sub) =>
)
- ) : (
-
- )}
-
+ {event.replies ? (
+ event.replies.map((sub) =>
)
+ ) : (
+
+ )}
);
diff --git a/src/shared/notes/replies/list.tsx b/src/shared/notes/replies/list.tsx
index 9543c3fe..3173cce4 100644
--- a/src/shared/notes/replies/list.tsx
+++ b/src/shared/notes/replies/list.tsx
@@ -8,42 +8,51 @@ import { NDKEventWithReplies } from '@utils/types';
export function RepliesList({ id }: { id: string }) {
const { ndk } = useNDK();
- const { status, data } = useQuery(['note-replies', id], async () => {
- const events = await ndk.fetchEvents({
- kinds: [1],
- '#e': [id],
- });
+ const { status, data } = useQuery(
+ ['note-replies', id],
+ async () => {
+ try {
+ const events = await ndk.fetchEvents({
+ kinds: [1],
+ '#e': [id],
+ });
- const array = [...events] as unknown as NDKEventWithReplies[];
+ const array = [...events] as unknown as NDKEventWithReplies[];
- if (array.length > 0) {
- const replies = new Set();
- array.forEach((event) => {
- const tags = event.tags.filter((el) => el[0] === 'e' && el[1] !== id);
- if (tags.length > 0) {
- tags.forEach((tag) => {
- const rootIndex = array.findIndex((el) => el.id === tag[1]);
- if (rootIndex) {
- const rootEvent = array[rootIndex];
- if (rootEvent.replies) {
- rootEvent.replies.push(event);
- } else {
- rootEvent.replies = [event];
- }
- replies.add(event.id);
+ if (array.length > 0) {
+ const replies = new Set();
+ array.forEach((event) => {
+ const tags = event.tags.filter((el) => el[0] === 'e' && el[1] !== id);
+ if (tags.length > 0) {
+ tags.forEach((tag) => {
+ const rootIndex = array.findIndex((el) => el.id === tag[1]);
+ if (rootIndex !== -1) {
+ const rootEvent = array[rootIndex];
+ if (rootEvent && rootEvent.replies) {
+ rootEvent.replies.push(event);
+ } else {
+ rootEvent.replies = [event];
+ }
+ replies.add(event.id);
+ }
+ });
}
});
+ const cleanEvents = array.filter((ev) => !replies.has(ev.id));
+ return cleanEvents;
}
- });
- const cleanEvents = array.filter((ev) => !replies.has(ev.id));
- return cleanEvents;
- }
- return array;
- });
+
+ return array;
+ } catch (e) {
+ throw new Error(e);
+ }
+ },
+ { enabled: !!ndk }
+ );
if (status === 'loading') {
return (
-
+
@@ -53,19 +62,29 @@ export function RepliesList({ id }: { id: string }) {
);
}
- return (
-
-
-
{data?.length || 0} replies
+ if (status === 'error') {
+ return (
+
+
+
+
Error: failed to get replies
+
+
-
+ );
+ }
+
+ return (
+
+
+ {data?.length || 0} replies
+
+
{data?.length === 0 ? (
-
-
-
-
๐
-
Share your thought on it...
-
+
+
+
๐
+
Share your thought on it...
) : (
diff --git a/src/shared/notes/replies/sub.tsx b/src/shared/notes/replies/sub.tsx
index 6c3f31d8..b2633482 100644
--- a/src/shared/notes/replies/sub.tsx
+++ b/src/shared/notes/replies/sub.tsx
@@ -5,9 +5,9 @@ import { User } from '@shared/user';
export function SubReply({ event }: { event: NDKEvent }) {
return (
-
+
-
+
diff --git a/src/shared/notes/users/repost.tsx b/src/shared/notes/users/repost.tsx
index d2029042..abf2e95f 100644
--- a/src/shared/notes/users/repost.tsx
+++ b/src/shared/notes/users/repost.tsx
@@ -19,10 +19,7 @@ export function RepostUser({ pubkey }: { pubkey: string }) {
/>
- {user?.nip05?.toLowerCase() ||
- user?.name ||
- user?.display_name ||
- shortenKey(pubkey)}
+ {user?.nip05 || user?.name || user?.display_name || shortenKey(pubkey)}
reposted
diff --git a/src/shared/notes/users/thread.tsx b/src/shared/notes/users/thread.tsx
index 0411a34f..f12d9a8c 100644
--- a/src/shared/notes/users/thread.tsx
+++ b/src/shared/notes/users/thread.tsx
@@ -1,4 +1,3 @@
-import { VerticalDotsIcon } from '@shared/icons';
import { Image } from '@shared/image';
import { formatCreatedAt } from '@utils/createdAt';
@@ -16,23 +15,15 @@ export function ThreadUser({ pubkey, time }: { pubkey: string; time: number }) {
return (
-
-
-
- {user?.nip05?.toLowerCase() || user?.name || user?.display_name}
-
-
-
-
+
+
+ {user.display_name || user.name}
+
+
{createdAt}
ยท
{displayNpub(pubkey, 16)}
diff --git a/src/shared/user.tsx b/src/shared/user.tsx
index b2821d16..da8f1d7c 100644
--- a/src/shared/user.tsx
+++ b/src/shared/user.tsx
@@ -79,10 +79,7 @@ export function User({
size === 'small' ? 'max-w-[10rem]' : 'max-w-[15rem]'
)}
>
- {user?.nip05?.toLowerCase() ||
- user?.name ||
- user?.display_name ||
- displayNpub(pubkey, 16)}
+ {user?.nip05 || user?.name || user?.display_name || displayNpub(pubkey, 16)}
ยท
{createdAt}
diff --git a/src/shared/userProfile.tsx b/src/shared/userProfile.tsx
index f4024d36..69ebbb3a 100644
--- a/src/shared/userProfile.tsx
+++ b/src/shared/userProfile.tsx
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
-import { UserMetadata } from '@app/users/components/stats';
+import { UserStats } from '@app/users/components/stats';
import { Image } from '@shared/image';
@@ -65,7 +65,7 @@ export function UserProfile({ pubkey }: { pubkey: string }) {
{user?.about}
-
+
{status === 'loading' ? (