wip
This commit is contained in:
@@ -3,19 +3,15 @@ import { useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
import { useStorage } from '@libs/storage/provider';
|
||||
|
||||
import { ReplyMediaUploader } from '@shared/notes';
|
||||
import { User } from '@shared/user';
|
||||
|
||||
export function NoteReplyForm({ id }: { id: string }) {
|
||||
const { db } = useStorage();
|
||||
export function NoteReplyForm({ eventId }: { eventId: string }) {
|
||||
const { ndk, relayUrls } = useNDK();
|
||||
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
const submit = async () => {
|
||||
const tags = [['e', id, relayUrls[0], 'root']];
|
||||
const tags = [['e', eventId, relayUrls[0], 'root']];
|
||||
|
||||
// publish event
|
||||
const event = new NDKEvent(ndk);
|
||||
@@ -31,26 +27,23 @@ export function NoteReplyForm({ id }: { id: string }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mt-3 flex gap-3">
|
||||
<User pubkey={db.account.pubkey} variant="miniavatar" />
|
||||
<div className="relative flex flex-1 flex-col rounded-xl bg-neutral-100 dark:bg-neutral-900">
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
placeholder="Reply to this thread..."
|
||||
className="relative h-36 w-full resize-none bg-transparent px-5 py-4 text-neutral-900 !outline-none placeholder:text-neutral-600 dark:text-neutral-100 dark:placeholder:text-neutral-400"
|
||||
spellCheck={false}
|
||||
/>
|
||||
<div className="inline-flex items-center justify-end gap-2 rounded-b-xl border-t border-neutral-200 p-2 dark:border-neutral-800">
|
||||
<ReplyMediaUploader setValue={setValue} />
|
||||
<button
|
||||
onClick={() => submit()}
|
||||
disabled={value.length === 0 ? true : false}
|
||||
className="h-9 w-20 rounded-lg bg-blue-500 text-white hover:bg-blue-600 disabled:opacity-50"
|
||||
>
|
||||
Reply
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-3 flex flex-col rounded-xl bg-neutral-50 dark:bg-neutral-950">
|
||||
<textarea
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
placeholder="Reply to this post..."
|
||||
className="h-28 w-full resize-none rounded-t-xl bg-neutral-100 px-5 py-4 text-neutral-900 !outline-none placeholder:text-neutral-600 dark:bg-neutral-900 dark:text-neutral-100 dark:placeholder:text-neutral-400"
|
||||
spellCheck={false}
|
||||
/>
|
||||
<div className="inline-flex items-center justify-end gap-2 rounded-b-xl p-2">
|
||||
<ReplyMediaUploader setValue={setValue} />
|
||||
<button
|
||||
onClick={() => submit()}
|
||||
disabled={value.length === 0 ? true : false}
|
||||
className="h-9 w-20 rounded-lg bg-blue-500 text-white hover:bg-blue-600 disabled:opacity-50"
|
||||
>
|
||||
Reply
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useState } from 'react';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
import { NavArrowDownIcon } from '@shared/icons';
|
||||
import { MemoizedTextNote, NoteActions, SubReply } from '@shared/notes';
|
||||
import { MemoizedTextKind, NoteActions, SubReply } from '@shared/notes';
|
||||
import { User } from '@shared/user';
|
||||
|
||||
import { NDKEventWithReplies } from '@utils/types';
|
||||
@@ -12,23 +12,20 @@ export function Reply({ event, root }: { event: NDKEventWithReplies; root?: stri
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="relative flex flex-col">
|
||||
<div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<User pubkey={event.pubkey} time={event.created_at} eventId={event.id} />
|
||||
<div className="-mt-4 flex items-start gap-3">
|
||||
<div className="w-10 shrink-0" />
|
||||
<div className="relative z-10 flex-1">
|
||||
<MemoizedTextNote content={event.content} />
|
||||
<NoteActions
|
||||
id={event.id}
|
||||
pubkey={event.pubkey}
|
||||
root={root}
|
||||
extraButtons={false}
|
||||
/>
|
||||
</div>
|
||||
<MemoizedTextKind content={event.content} />
|
||||
<div className="-ml-1">
|
||||
<NoteActions
|
||||
id={event.id}
|
||||
pubkey={event.pubkey}
|
||||
root={root}
|
||||
extraButtons={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pl-[48px]">
|
||||
<div className="pl-4">
|
||||
<Collapsible.Root open={open} onOpenChange={setOpen}>
|
||||
{event.replies?.length > 0 ? (
|
||||
<div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Reply } from '@shared/notes';
|
||||
import { useNostr } from '@utils/hooks/useNostr';
|
||||
import { NDKEventWithReplies } from '@utils/types';
|
||||
|
||||
export function ReplyList({ id }: { id: string }) {
|
||||
export function ReplyList({ eventId }: { eventId: string }) {
|
||||
const { fetchAllReplies, sub } = useNostr();
|
||||
const [data, setData] = useState<null | NDKEventWithReplies[]>(null);
|
||||
|
||||
@@ -14,31 +14,32 @@ export function ReplyList({ id }: { id: string }) {
|
||||
let isCancelled = false;
|
||||
|
||||
async function fetchRepliesAndSub() {
|
||||
const events = await fetchAllReplies(id);
|
||||
const events = await fetchAllReplies(eventId);
|
||||
if (!isCancelled) {
|
||||
setData(events);
|
||||
}
|
||||
// subscribe for new replies
|
||||
sub(
|
||||
{
|
||||
'#e': [id],
|
||||
'#e': [eventId],
|
||||
since: Math.floor(Date.now() / 1000),
|
||||
},
|
||||
(event: NDKEventWithReplies) => setData((prev) => [event, ...prev]),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
fetchRepliesAndSub();
|
||||
|
||||
return () => {
|
||||
isCancelled = true;
|
||||
};
|
||||
}, [id]);
|
||||
}, [eventId]);
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<div className="mt-3">
|
||||
<div className="flex h-16 items-center justify-center rounded-xl bg-neutral-100 px-3 py-3 dark:bg-neutral-900">
|
||||
<div className="flex h-16 items-center justify-center rounded-xl bg-neutral-50 p-3 dark:bg-neutral-950">
|
||||
<LoaderIcon className="h-5 w-5 animate-spin" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,12 +53,12 @@ export function ReplyList({ id }: { id: string }) {
|
||||
<div className="flex flex-col items-center justify-center gap-2 py-6">
|
||||
<h3 className="text-3xl">👋</h3>
|
||||
<p className="leading-none text-neutral-600 dark:text-neutral-400">
|
||||
Share your thought on it...
|
||||
Be the first to Reply!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
data.map((event) => <Reply key={event.id} event={event} root={id} />)
|
||||
data.map((event) => <Reply key={event.id} event={event} root={eventId} />)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
|
||||
import { MemoizedTextNote, NoteActions } from '@shared/notes';
|
||||
import { MemoizedTextKind, NoteActions } from '@shared/notes';
|
||||
import { User } from '@shared/user';
|
||||
|
||||
export function SubReply({ event }: { event: NDKEvent }) {
|
||||
return (
|
||||
<div className="mb-3 flex flex-col">
|
||||
<div className="flex flex-col gap-2">
|
||||
<User pubkey={event.pubkey} time={event.created_at} eventId={event.id} />
|
||||
<div className="-mt-4 flex items-start gap-3">
|
||||
<div className="w-10 shrink-0" />
|
||||
<div className="flex-1">
|
||||
<MemoizedTextNote content={event.content} />
|
||||
<NoteActions id={event.id} pubkey={event.pubkey} extraButtons={false} />
|
||||
</div>
|
||||
<MemoizedTextKind content={event.content} />
|
||||
<div className="-ml-1">
|
||||
<NoteActions id={event.id} pubkey={event.pubkey} extraButtons={false} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user