improve notification and performance
This commit is contained in:
@@ -7,14 +7,14 @@ export function TextKind({ content, textmode }: { content: string; textmode?: bo
|
||||
|
||||
if (textmode) {
|
||||
return (
|
||||
<div className="break-p line-clamp-3 select-text leading-normal text-neutral-900 dark:text-neutral-100">
|
||||
<div className="line-clamp-3 select-text leading-normal text-neutral-900 dark:text-neutral-100">
|
||||
{parsedContent}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={'min-w-0 px-3'}>
|
||||
<div className="min-w-0 px-3">
|
||||
<div className="break-p select-text leading-normal text-neutral-900 dark:text-neutral-100">
|
||||
{parsedContent}
|
||||
</div>
|
||||
|
||||
@@ -1,109 +1,158 @@
|
||||
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { ShareIcon } from '@shared/icons';
|
||||
import {
|
||||
MemoizedArticleKind,
|
||||
MemoizedFileKind,
|
||||
MemoizedTextKind,
|
||||
NoteSkeleton,
|
||||
} from '@shared/notes';
|
||||
import { ReplyIcon, RepostIcon } from '@shared/icons';
|
||||
import { ChildNote, TextKind } from '@shared/notes';
|
||||
import { User } from '@shared/user';
|
||||
|
||||
import { WIDGET_KIND } from '@stores/constants';
|
||||
|
||||
import { formatCreatedAt } from '@utils/createdAt';
|
||||
import { useEvent } from '@utils/hooks/useEvent';
|
||||
import { useNostr } from '@utils/hooks/useNostr';
|
||||
import { useWidget } from '@utils/hooks/useWidget';
|
||||
|
||||
export function NotifyNote({ event }: { event: NDKEvent }) {
|
||||
const createdAt = formatCreatedAt(event.created_at, false);
|
||||
const rootEventId = event.tags.find((el) => el[0] === 'e')?.[1];
|
||||
|
||||
const { status, data } = useEvent(rootEventId);
|
||||
const { getEventThread } = useNostr();
|
||||
const { addWidget } = useWidget();
|
||||
|
||||
const renderKind = (event: NDKEvent) => {
|
||||
switch (event.kind) {
|
||||
case NDKKind.Text:
|
||||
return <MemoizedTextKind key={event.id} content={event.content} textmode />;
|
||||
case NDKKind.Article:
|
||||
return <MemoizedArticleKind key={event.id} id={event.id} tags={event.tags} />;
|
||||
case 1063:
|
||||
return <MemoizedFileKind key={event.id} tags={event.tags} />;
|
||||
default:
|
||||
return (
|
||||
<div className="break-p line-clamp-3 select-text leading-normal text-neutral-900 dark:text-neutral-100">
|
||||
{event.content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
const thread = getEventThread(event.tags);
|
||||
const createdAt = formatCreatedAt(event.created_at, false);
|
||||
|
||||
const renderText = (kind: number) => {
|
||||
switch (kind) {
|
||||
case NDKKind.Text:
|
||||
return 'replied';
|
||||
case NDKKind.Reaction: {
|
||||
return `reacted your post`;
|
||||
}
|
||||
case NDKKind.Repost:
|
||||
return 'reposted your post';
|
||||
case NDKKind.Zap:
|
||||
return 'zapped your post';
|
||||
default:
|
||||
return 'unknown';
|
||||
}
|
||||
};
|
||||
|
||||
if (status === 'pending') {
|
||||
if (event.kind === NDKKind.Reaction) {
|
||||
return (
|
||||
<div className="h-min w-full px-3 pb-3">
|
||||
<div className="relative overflow-hidden rounded-xl bg-white/10 px-3 py-3 backdrop-blur-xl">
|
||||
<NoteSkeleton />
|
||||
<div className="mb-3 h-min w-full px-3">
|
||||
<div className="flex flex-col gap-2 rounded-xl bg-neutral-50 p-3 dark:bg-neutral-950">
|
||||
<div className="flex h-10 items-center justify-between">
|
||||
<div className="relative flex w-full items-center gap-2 px-3 pt-2">
|
||||
<div className="absolute -left-0.5 -top-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-blue-100 text-xs ring-2 ring-neutral-50 dark:bg-blue-900 dark:ring-neutral-950">
|
||||
{event.content === '+' ? '👍' : event.content}
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="inline-flex items-center gap-1.5">
|
||||
<User pubkey={event.pubkey} variant="notify" />
|
||||
<p className="text-neutral-700 dark:text-neutral-300">reacted</p>
|
||||
</div>
|
||||
<div className="text-neutral-500 dark:text-neutral-400">{createdAt}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="w-full px-3">
|
||||
<div className="flex h-min w-full flex-col gap-3 rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
||||
{thread.rootEventId ? <ChildNote id={thread.rootEventId} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
addWidget.mutate({
|
||||
kind: WIDGET_KIND.thread,
|
||||
title: 'Thread',
|
||||
content: thread.rootEventId,
|
||||
})
|
||||
}
|
||||
className="self-start text-blue-500 hover:text-blue-600"
|
||||
>
|
||||
Show original post
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mb-3 h-min w-full px-3">
|
||||
<div className="flex flex-col gap-2 rounded-xl bg-neutral-50 p-3 dark:bg-neutral-950">
|
||||
<div className="flex h-10 items-center justify-between">
|
||||
<div className="relative flex w-full items-center gap-2 px-3 pt-2">
|
||||
<div className="absolute -left-0.5 -top-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-blue-100 text-xs ring-2 ring-neutral-50 dark:bg-blue-900 dark:ring-neutral-950">
|
||||
{event.kind === 7 ? (event.content === '+' ? '👍' : event.content) : '⚡️'}
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="inline-flex items-center gap-1.5">
|
||||
<User pubkey={event.pubkey} variant="notify" />
|
||||
<p className="text-neutral-900 dark:text-neutral-100">
|
||||
{renderText(event.kind)}
|
||||
</p>
|
||||
if (event.kind === NDKKind.Repost) {
|
||||
return (
|
||||
<div className="mb-3 h-min w-full px-3">
|
||||
<div className="flex flex-col gap-2 rounded-xl bg-neutral-50 p-3 dark:bg-neutral-950">
|
||||
<div className="flex h-10 items-center justify-between">
|
||||
<div className="relative flex w-full items-center gap-2 px-3 pt-2">
|
||||
<div className="absolute -left-0.5 -top-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-teal-500 text-xs ring-2 ring-neutral-50 dark:ring-neutral-950">
|
||||
<RepostIcon className="h-4 w-4 text-white" />
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="inline-flex items-center gap-1.5">
|
||||
<User pubkey={event.pubkey} variant="notify" />
|
||||
<p className="text-neutral-700 dark:text-neutral-300">reposted</p>
|
||||
</div>
|
||||
<div className="text-neutral-500 dark:text-neutral-400">{createdAt}</div>
|
||||
</div>
|
||||
<div className="text-neutral-500 dark:text-neutral-400">{createdAt}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">{data ? renderKind(data) : <p>Loading...</p>}</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
addWidget.mutate({
|
||||
kind: WIDGET_KIND.thread,
|
||||
title: 'Thread',
|
||||
content: data.id,
|
||||
})
|
||||
}
|
||||
className="inline-flex min-h-full w-10 shrink-0 items-center justify-center rounded-lg text-neutral-600 hover:text-blue-500 dark:text-neutral-400"
|
||||
>
|
||||
<ShareIcon className="h-5 w-5" />
|
||||
</button>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="w-full px-3">
|
||||
<div className="flex h-min w-full flex-col gap-3 rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
||||
{thread.rootEventId ? <ChildNote id={thread.rootEventId} /> : null}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
addWidget.mutate({
|
||||
kind: WIDGET_KIND.thread,
|
||||
title: 'Thread',
|
||||
content: thread.rootEventId,
|
||||
})
|
||||
}
|
||||
className="self-start text-blue-500 hover:text-blue-600"
|
||||
>
|
||||
Show original post
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if (event.kind === NDKKind.Text) {
|
||||
return (
|
||||
<div className="mb-3 h-min w-full px-3">
|
||||
<div className="flex flex-col gap-2 rounded-xl bg-neutral-50 p-3 dark:bg-neutral-950">
|
||||
<div className="flex h-10 items-center justify-between">
|
||||
<div className="relative flex w-full items-center gap-2 px-3 pt-2">
|
||||
<div className="absolute -left-0.5 -top-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-blue-500 text-xs ring-2 ring-neutral-50 dark:ring-neutral-950">
|
||||
<ReplyIcon className="h-4 w-4 text-white" />
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-between">
|
||||
<div className="inline-flex items-center gap-1.5">
|
||||
<User pubkey={event.pubkey} variant="notify" />
|
||||
<p className="text-neutral-700 dark:text-neutral-300">replied</p>
|
||||
</div>
|
||||
<div className="text-neutral-500 dark:text-neutral-400">{createdAt}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="w-full px-3">
|
||||
<div className="flex h-min w-full flex-col gap-3 rounded-lg bg-neutral-100 p-3 dark:bg-neutral-900">
|
||||
{thread.replyEventId ? (
|
||||
<ChildNote id={thread.replyEventId} />
|
||||
) : thread.rootEventId ? (
|
||||
<ChildNote id={thread.rootEventId} isRoot />
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
addWidget.mutate({
|
||||
kind: WIDGET_KIND.thread,
|
||||
title: 'Thread',
|
||||
content: thread.replyEventId
|
||||
? thread.replyEventId
|
||||
: thread.rootEventId,
|
||||
})
|
||||
}
|
||||
className="self-start text-blue-500 hover:text-blue-600"
|
||||
>
|
||||
Show full thread
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<TextKind content={event.content} textmode />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const MemoizedNotifyNote = memo(NotifyNote);
|
||||
|
||||
@@ -50,7 +50,7 @@ export function NoteReplyForm({ rootEvent }: { rootEvent: NDKEvent }) {
|
||||
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"
|
||||
className="h-28 w-full resize-none rounded-t-xl border-transparent bg-neutral-100 px-5 py-4 text-neutral-900 !outline-none placeholder:text-neutral-600 focus:border-blue-500 focus:ring focus:ring-blue-200 dark:bg-neutral-900 dark:text-neutral-100 dark:placeholder:text-neutral-400 dark:focus:ring-blue-800"
|
||||
spellCheck={false}
|
||||
/>
|
||||
<div className="inline-flex items-center justify-end gap-2 rounded-b-xl p-2">
|
||||
|
||||
Reference in New Issue
Block a user