update replies

This commit is contained in:
Ren Amamiya
2023-07-17 13:37:01 +07:00
parent b3b790588a
commit 5606dcb32f
11 changed files with 193 additions and 56 deletions

View File

@@ -15,6 +15,7 @@ export * from './kinds/kind1063';
export * from './metadata';
export * from './users/mini';
export * from './users/repost';
export * from './users/thread';
export * from './kinds/thread';
export * from './kinds/repost';
export * from './kinds/sub';
@@ -22,3 +23,4 @@ export * from './skeleton';
export * from './actions';
export * from './content';
export * from './hashtag';
export * from './stats';

View File

@@ -9,7 +9,7 @@ export function MentionUser({ pubkey }: { pubkey: string }) {
type="button"
className="break-words rounded bg-zinc-800 px-2 py-px text-sm font-normal text-blue-400 no-underline hover:bg-zinc-700 hover:text-blue-500"
>
@{user?.name || user?.displayName || shortenKey(pubkey)}
{'@' + user?.name || user?.displayName || shortenKey(pubkey)}
</button>
);
}

View File

@@ -1,17 +1,25 @@
import { NoteMetadata } from '@shared/notes/metadata';
import { NoteActions, NoteContent } from '@shared/notes';
import { User } from '@shared/user';
import { parser } from '@utils/parser';
import { LumeEvent } from '@utils/types';
export function Reply({ data }: { data: any }) {
export function Reply({ data }: { data: LumeEvent }) {
const content = parser(data);
return (
<div className="mb-3 flex h-min min-h-min w-full select-text flex-col rounded-md bg-zinc-900 px-3 pt-5">
<div className="flex flex-col">
<User pubkey={data.pubkey} time={data.created_at} />
<div className="-mt-[20px] pl-[50px]">
<NoteMetadata id={data.event_id} eventPubkey={data.pubkey} />
<div className="h-min w-full py-1.5">
<div className="relative overflow-hidden rounded-xl border-t border-zinc-800/50 bg-zinc-900 px-3 pt-3">
<div className="relative flex flex-col">
<User pubkey={data.pubkey} time={data.created_at} />
<div className="relative z-20 -mt-6 flex items-start gap-3">
<div className="w-11 shrink-0" />
<div className="flex-1">
<NoteContent content={content} />
<NoteActions id={data.event_id || data.id} pubkey={data.pubkey} />
</div>
</div>
<div className="pb-3" />
</div>
</div>
</div>

View File

@@ -1,17 +1,25 @@
import { NDKEvent } from '@nostr-dev-kit/ndk';
import { useQuery } from '@tanstack/react-query';
import { getReplies } from '@libs/storage';
import { useNDK } from '@libs/ndk/provider';
import { Reply } from '@shared/notes/replies/item';
export function RepliesList({ parent_id }: { parent_id: string }) {
const { status, data } = useQuery(['replies', parent_id], async () => {
return await getReplies(parent_id);
import { LumeEvent } from '@utils/types';
export function RepliesList({ id }: { id: string }) {
const { relayUrls, fetcher } = useNDK();
const { status, data } = useQuery(['thread', id], async () => {
const events = (await fetcher.fetchAllEvents(
relayUrls,
{ kinds: [1], '#e': [id] },
{ since: 0 }
)) as unknown as LumeEvent[];
return events;
});
return (
<div className="mt-5">
<div className="mt-3">
<div className="mb-2">
<h5 className="text-lg font-semibold text-zinc-300">Replies</h5>
</div>
@@ -28,7 +36,7 @@ export function RepliesList({ parent_id }: { parent_id: string }) {
</div>
) : data.length === 0 ? (
<div className="px=3">
<div className="flex w-full items-center justify-center rounded-md bg-zinc-900">
<div className="flex w-full items-center justify-center rounded-xl bg-zinc-900">
<div className="flex flex-col items-center justify-center gap-2 py-6">
<h3 className="text-3xl">👋</h3>
<p className="leading-none text-zinc-400">Share your thought on it...</p>

View File

@@ -0,0 +1,76 @@
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
import { useQuery } from '@tanstack/react-query';
import { decode } from 'light-bolt11-decoder';
import { useNDK } from '@libs/ndk/provider';
import { LoaderIcon } from '@shared/icons';
export function NoteStats({ id }: { id: string }) {
const { ndk } = useNDK();
const { status, data } = useQuery(
['note-stats', id],
async () => {
let reactions = 0;
let reposts = 0;
let zaps = 0;
const filter: NDKFilter = {
'#e': [id],
kinds: [6, 7, 9735],
};
const events = await ndk.fetchEvents(filter);
events.forEach((event: NDKEvent) => {
switch (event.kind) {
case 6:
reposts += 1;
break;
case 7:
reactions += 1;
break;
case 9735: {
const bolt11 = event.tags.find((tag) => tag[0] === 'bolt11')[1];
if (bolt11) {
const decoded = decode(bolt11);
const amount = decoded.sections.find((item) => item.name === 'amount');
const sats = amount.value / 1000;
zaps += sats;
}
break;
}
default:
break;
}
});
return { reposts, reactions, zaps };
},
{ refetchOnWindowFocus: false, refetchOnReconnect: false }
);
if (status === 'loading') {
return (
<div className="flex h-11 items-center">
<LoaderIcon className="h-4 w-4 animate-spin text-zinc-100" />
</div>
);
}
return (
<div className="flex h-11 items-center gap-3">
<p className="inline-flex h-6 items-center justify-center gap-1 rounded bg-zinc-800 px-2 text-sm">
{data.reactions}
<span className="text-zinc-400">reactions</span>
</p>
<p className="inline-flex h-6 items-center justify-center gap-1 rounded bg-zinc-800 px-2 text-sm">
{data.reposts}
<span className="text-zinc-400">reposts</span>
</p>
<p className="inline-flex h-6 items-center justify-center gap-1 rounded bg-zinc-800 px-2 text-sm">
{data.zaps}
<span className="text-zinc-400">zaps</span>
</p>
</div>
);
}

View File

@@ -0,0 +1,46 @@
import { VerticalDotsIcon } from '@shared/icons';
import { Image } from '@shared/image';
import { DEFAULT_AVATAR } from '@stores/constants';
import { formatCreatedAt } from '@utils/createdAt';
import { useProfile } from '@utils/hooks/useProfile';
import { displayNpub } from '@utils/shortenKey';
export function ThreadUser({ pubkey, time }: { pubkey: string; time: number }) {
const { status, user } = useProfile(pubkey);
const createdAt = formatCreatedAt(time);
if (status === 'loading') {
return <div className="h-4 w-4 animate-pulse rounded bg-zinc-700"></div>;
}
return (
<div className="flex items-center gap-3">
<Image
src={user?.picture || user?.image || DEFAULT_AVATAR}
fallback={DEFAULT_AVATAR}
alt={pubkey}
className="relative z-20 inline-block h-11 w-11 rounded-lg"
/>
<div className="lex flex-1 items-baseline justify-between">
<div className="inline-flex w-full items-center justify-between">
<h5 className="truncate font-semibold leading-none text-zinc-100">
{user?.nip05?.toLowerCase() || user?.name || user?.display_name}
</h5>
<button
type="button"
className="inline-flex h-5 w-max items-center justify-center rounded px-1 hover:bg-zinc-800"
>
<VerticalDotsIcon className="h-4 w-4 rotate-90 transform text-zinc-200" />
</button>
</div>
<div className="inline-flex items-center gap-2">
<span className="leading-none text-zinc-500">{createdAt}</span>
<span className="leading-none text-zinc-500">·</span>
<span className="leading-none text-zinc-500">{displayNpub(pubkey, 16)}</span>
</div>
</div>
</div>
);
}