diff --git a/src/components/note/atoms/user.tsx b/src/components/note/atoms/user.tsx
index 6fe5e87b..2fe94ff3 100644
--- a/src/components/note/atoms/user.tsx
+++ b/src/components/note/atoms/user.tsx
@@ -14,7 +14,7 @@ import Database from 'tauri-plugin-sql-api';
const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null;
export const User = memo(function User({ pubkey, time }: { pubkey: string; time: any }) {
- const [profile, setProfile] = useState({ picture: null, name: null });
+ const [profile, setProfile] = useState({ picture: null, name: null, username: null });
const { onEvent } = useNostrEvents({
filter: {
diff --git a/src/components/note/atoms/userWithUsername.tsx b/src/components/note/atoms/userWithUsername.tsx
new file mode 100644
index 00000000..30b87ff0
--- /dev/null
+++ b/src/components/note/atoms/userWithUsername.tsx
@@ -0,0 +1,97 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { ImageWithFallback } from '@components/imageWithFallback';
+
+import { truncate } from '@utils/truncate';
+
+import MoreIcon from '@assets/icons/More';
+
+import Avatar from 'boring-avatars';
+import { useNostrEvents } from 'nostr-react';
+import { memo, useEffect, useState } from 'react';
+import Database from 'tauri-plugin-sql-api';
+
+const db = typeof window !== 'undefined' ? await Database.load('sqlite:lume.db') : null;
+
+export const UserWithUsername = memo(function UserWithUsername({ pubkey }: { pubkey: string }) {
+ const [profile, setProfile] = useState({ picture: null, name: null, username: null });
+
+ const { onEvent } = useNostrEvents({
+ filter: {
+ authors: [pubkey],
+ kinds: [0],
+ },
+ });
+
+ onEvent(async (rawMetadata) => {
+ try {
+ const metadata: any = JSON.parse(rawMetadata.content);
+ if (profile.picture === null || profile.name === null) {
+ setProfile(metadata);
+ await db.execute(
+ `INSERT OR IGNORE INTO cache_profiles (pubkey, metadata) VALUES ("${pubkey}", '${JSON.stringify(
+ metadata
+ )}')`
+ );
+ } else {
+ return;
+ }
+ } catch (err) {
+ console.error(err, rawMetadata);
+ }
+ });
+
+ useEffect(() => {
+ const initialProfile = async () => {
+ const result: any = await db.select(
+ `SELECT metadata FROM cache_profiles WHERE pubkey = "${pubkey}"`
+ );
+ db.close;
+ return result;
+ };
+
+ initialProfile()
+ .then((res) => {
+ if (res[0] !== undefined) {
+ setProfile(JSON.parse(res[0].metadata));
+ }
+ })
+ .catch(console.error);
+ }, [pubkey]);
+
+ return (
+
+
+ {profile.picture ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ {profile.name ? profile.name : truncate(pubkey, 16, ' .... ')}
+
+
+ {profile.username ? profile.username : truncate(pubkey, 16, ' .... ')}
+
+
+
+
+
+
+
+
+ );
+});
diff --git a/src/components/note/modal/index.tsx b/src/components/note/modal/index.tsx
new file mode 100644
index 00000000..31d3a05c
--- /dev/null
+++ b/src/components/note/modal/index.tsx
@@ -0,0 +1,41 @@
+import { UserWithUsername } from '@components/note/atoms/userWithUsername';
+import Content from '@components/note/content';
+import NoteReply from '@components/note/modal/noteReply';
+
+import { useNostrEvents } from 'nostr-react';
+import { memo } from 'react';
+
+/* eslint-disable @typescript-eslint/no-explicit-any */
+const Modal = ({ event }: { event: any }) => {
+ const { events } = useNostrEvents({
+ filter: {
+ '#e': [event.id],
+ since: event.created_at,
+ kinds: [1],
+ limit: 100,
+ },
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {events.map((item) => (
+
+ ))}
+
+
+
+
+
+ );
+};
+
+export default memo(Modal);
diff --git a/src/components/note/modal/noteReply.tsx b/src/components/note/modal/noteReply.tsx
new file mode 100644
index 00000000..9bf934c2
--- /dev/null
+++ b/src/components/note/modal/noteReply.tsx
@@ -0,0 +1,18 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { User } from '@components/note/atoms/user';
+import Content from '@components/note/content';
+
+export default function NoteReply({ event }: { event: any }) {
+ return (
+
+ );
+}
diff --git a/src/components/note/single.tsx b/src/components/note/single.tsx
index c7227065..c5bad333 100644
--- a/src/components/note/single.tsx
+++ b/src/components/note/single.tsx
@@ -4,33 +4,41 @@ import Reply from '@components/note/atoms/reply';
import { User } from '@components/note/atoms/user';
import Content from '@components/note/content';
-import { useRouter } from 'next/router';
+import * as Dialog from '@radix-ui/react-dialog';
+import dynamic from 'next/dynamic';
import { memo } from 'react';
+const Modal = dynamic(() => import('@components/note/modal'), {
+ ssr: false,
+ loading: () => <>>,
+});
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const Single = memo(function Single({ event }: { event: any }) {
- const router = useRouter();
-
- const openThread = (id: string) => {
- router.push(`/feed/${id}`);
- };
-
return (
- openThread(event.id)}
- className="flex h-min min-h-min w-full cursor-pointer select-text flex-col border-b border-zinc-800 py-4 px-6 hover:bg-zinc-800">
-