add trending notes

This commit is contained in:
Ren Amamiya
2023-06-16 10:01:20 +07:00
parent efea63b0a0
commit f8de44fe9f
38 changed files with 155 additions and 308 deletions

View File

@@ -0,0 +1,80 @@
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { Image } from "@shared/image";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { DEFAULT_AVATAR } from "@stores/constants";
import { dateToUnix } from "@utils/date";
import { useProfile } from "@utils/hooks/useProfile";
import { useContext, useState } from "react";
export function NoteReplyForm({ id }: { id: string }) {
const ndk = useContext(RelayContext);
const account = useActiveAccount((state: any) => state.account);
const { user } = useProfile(account.npub);
const [value, setValue] = useState("");
const submitEvent = () => {
const signer = new NDKPrivateKeySigner(account.privkey);
ndk.signer = signer;
const event = new NDKEvent(ndk);
// build event
event.content = value;
event.kind = 1;
event.created_at = dateToUnix();
event.pubkey = account.pubkey;
event.tags = [["e", id]];
// publish event
event.publish();
// reset form
setValue("");
};
return (
<div className="flex flex-col">
<div className="relative w-full flex-1 overflow-hidden">
<textarea
name="content"
onChange={(e) => setValue(e.target.value)}
placeholder="Reply to this thread..."
className="relative h-20 w-full resize-none rounded-md px-5 py-5 text-base bg-transparent !outline-none placeholder:text-zinc-400 dark:text-white dark:placeholder:text-zinc-500"
spellCheck={false}
/>
</div>
<div className="border-t border-zinc-800 w-full py-3 px-5">
<div className="flex w-full items-center justify-between">
<div className="inline-flex items-center gap-2">
<div className="relative h-8 w-8 shrink-0 rounded">
<Image
src={user?.image || DEFAULT_AVATAR}
alt={account.npub}
className="h-8 w-8 rounded bg-white object-cover"
/>
</div>
<div>
<p className="mb-px leading-none text-sm text-zinc-400">
Reply as
</p>
<p className="leading-none text-sm font-medium text-zinc-100">
{user?.nip05 || user?.name}
</p>
</div>
</div>
<div className="flex items-center gap-2">
<button
type="button"
onClick={() => submitEvent()}
disabled={value.length === 0 ? true : false}
className="inline-flex h-8 w-16 items-center justify-center rounded-md bg-fuchsia-500 px-4 text-base font-medium hover:bg-fuchsia-600 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50"
>
Reply
</button>
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,20 @@
import { Kind1 } from "@shared/notes/kind1";
import { NoteMetadata } from "@shared/notes/metadata";
import { User } from "@shared/user";
import { parser } from "@utils/parser";
export function Reply({ data }: { data: any }) {
const content = parser(data);
return (
<div className="flex h-min min-h-min w-full select-text flex-col px-3 pt-5 mb-3 rounded-md bg-zinc-900">
<div className="flex flex-col">
<User pubkey={data.pubkey} time={data.created_at} />
<div className="-mt-[20px] pl-[47px]">
<Kind1 content={content} />
<NoteMetadata id={data.id} eventPubkey={data.pubkey} />
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,48 @@
import { NDKEvent, NDKFilter } from "@nostr-dev-kit/ndk";
import { Reply } from "@shared/notes/replies/item";
import { RelayContext } from "@shared/relayProvider";
import { useContext } from "react";
import useSWR from "swr";
const fetcher = async ([, ndk, id]) => {
const filter: NDKFilter = {
"#e": [id],
kinds: [1],
};
const events = await ndk.fetchEvents(filter);
return [...events];
};
export function RepliesList({ id }: { id: string }) {
const ndk = useContext(RelayContext);
const { data } = useSWR(["note-replies", ndk, id], fetcher);
return (
<div className="mt-5">
<div className="mb-2">
<h5 className="text-lg font-semibold text-zinc-300">Replies</h5>
</div>
<div className="flex flex-col">
{!data ? (
<div className="flex gap-2 px-3 py-4">
<div className="relative h-9 w-9 shrink animate-pulse rounded-md bg-zinc-800" />
<div className="flex w-full flex-1 flex-col justify-center gap-1">
<div className="flex items-baseline gap-2 text-base">
<div className="h-2.5 w-20 animate-pulse rounded-sm bg-zinc-800" />
</div>
<div className="h-4 w-44 animate-pulse rounded-sm bg-zinc-800" />
</div>
</div>
) : data.length === 0 ? (
<div className="px=3">
<div className="w-full h-24 flex items-center justify-center rounded-md bg-zinc-900">
<p className="text-zinc-300 font-medium">No replies...</p>
</div>
</div>
) : (
data.map((event: NDKEvent) => <Reply key={event.id} data={event} />)
)}
</div>
</div>
);
}