perf improve

This commit is contained in:
Ren Amamiya
2023-09-27 08:32:19 +07:00
parent 1d93f8cf6a
commit b339e842ca
28 changed files with 521 additions and 942 deletions

View File

@@ -26,7 +26,7 @@ export function UserLatestPosts({ pubkey }: { pubkey: string }) {
case NDKKind.Text:
return (
<NoteWrapper key={event.id} event={event}>
<TextNote content={event.content} />
<TextNote />
</NoteWrapper>
);
case NDKKind.Repost:
@@ -34,19 +34,19 @@ export function UserLatestPosts({ pubkey }: { pubkey: string }) {
case 1063:
return (
<NoteWrapper key={event.id} event={event}>
<FileNote event={event} />
<FileNote />
</NoteWrapper>
);
case NDKKind.Article:
return (
<NoteWrapper key={event.id} event={event}>
<ArticleNote event={event} />
<ArticleNote />
</NoteWrapper>
);
default:
return (
<NoteWrapper key={event.id} event={event}>
<UnknownNote event={event} />
<UnknownNote />
</NoteWrapper>
);
}

View File

@@ -60,7 +60,7 @@ export const UserWithDrawer = memo(function UserWithDrawer({
</button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Content className="fixed right-0 top-0 z-50 flex h-full w-[400px] items-center justify-center px-4 pb-4 pt-16">
<Dialog.Content className="fixed right-0 top-0 z-50 flex h-full w-[400px] animate-slideRightAndFade items-center justify-center px-4 pb-4 pt-16 transition-all">
<div className="h-full w-full overflow-y-auto rounded-lg border-t border-white/10 bg-white/20 py-3 backdrop-blur-3xl">
{status === 'loading' ? (
<div>

View File

@@ -13,7 +13,7 @@ export function BrowseScreen() {
to="/browse/"
className={({ isActive }) =>
twMerge(
'inline-flex h-8 w-20 items-center justify-center rounded-full text-sm font-semibold',
'inline-flex h-7 w-20 items-center justify-center rounded-full text-sm font-semibold',
isActive ? 'bg-white/10 hover:bg-white/20' : ' hover:bg-white/5'
)
}
@@ -24,7 +24,7 @@ export function BrowseScreen() {
to="/browse/relays"
className={({ isActive }) =>
twMerge(
'inline-flex h-8 w-20 items-center justify-center rounded-full text-sm font-semibold',
'inline-flex h-7 w-20 items-center justify-center rounded-full text-sm font-semibold',
isActive ? 'bg-white/10 hover:bg-white/20' : ' hover:bg-white/5'
)
}

View File

@@ -1,7 +1,12 @@
export function BrowseRelaysScreen() {
return (
<div className="h-full w-full">
<p>TODO</p>
<div className="grid h-full w-full grid-cols-3">
<div className="col-span-2 border-r border-white/5 pt-16">
<p>Content</p>
</div>
<div className="col-span-1 px-3 pt-6">
<h3 className="font-semibold text-white">Your relays</h3>
</div>
</div>
);
}

View File

@@ -7,6 +7,8 @@ import { UnknownsModal } from '@app/chats/components/unknowns';
import { useStorage } from '@libs/storage/provider';
import { LoaderIcon } from '@shared/icons';
import { useNostr } from '@utils/hooks/useNostr';
export function ChatsList() {
@@ -33,8 +35,10 @@ export function ChatsList() {
return (
<div className="flex flex-col">
<div className="inline-flex h-10 items-center gap-2.5 border-l-2 border-transparent pl-4">
<div className="relative h-7 w-7 shrink-0 animate-pulse rounded bg-white/10 backdrop-blur-xl" />
<div className="h-4 w-full animate-pulse rounded bg-white/10 backdrop-blur-xl" />
<div className="relative inline-flex h-7 w-7 shrink-0 items-center justify-center">
<LoaderIcon className="h-4 w-4 animate-spin text-white" />
</div>
<h5 className="text-white/50">Loading messages...</h5>
</div>
</div>
);

View File

@@ -2,6 +2,7 @@ import { NDKEvent } from '@nostr-dev-kit/ndk';
import { useDecryptMessage } from '@app/chats/hooks/useDecryptMessage';
import { TextNote } from '@shared/notes';
import { User } from '@shared/user';
export function ChatMessageItem({
@@ -20,13 +21,12 @@ export function ChatMessageItem({
}
return (
<div className="flex h-min min-h-min w-full select-text flex-col px-5 py-3 backdrop-blur-xl hover:bg-white/10">
<div className="flex h-min min-h-min w-full select-text flex-col px-5 py-3 hover:bg-white/10">
<div className="flex flex-col">
<User pubkey={message.pubkey} time={message.created_at} variant="chat" />
<div className="-mt-[20px] pl-[49px]">
<p className="select-text whitespace-pre-line break-words text-base text-white">
{message.content}
</p>
<div className="-mt-5 flex items-start gap-3">
<div className="w-10 shrink-0" />
<TextNote content={message.content} />
</div>
</div>
</div>

View File

@@ -1,8 +1,8 @@
import { NDKSubscription } from '@nostr-dev-kit/ndk';
import { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk';
import { useQuery } from '@tanstack/react-query';
import { useCallback, useEffect, useRef } from 'react';
import { useParams } from 'react-router-dom';
import { Virtuoso } from 'react-virtuoso';
import { VList, VListHandle } from 'virtua';
import { ChatMessageForm } from '@app/chats/components/messages/form';
import { ChatMessageItem } from '@app/chats/components/messages/item';
@@ -18,7 +18,7 @@ import { useStronghold } from '@stores/stronghold';
import { useNostr } from '@utils/hooks/useNostr';
export function ChatScreen() {
const virtuosoRef = useRef(null);
const listRef = useRef<VListHandle>(null);
const userPrivkey = useStronghold((state) => state.privkey);
const { db } = useStorage();
@@ -29,10 +29,8 @@ export function ChatScreen() {
return await fetchNIP04Messages(pubkey);
});
const itemContent = useCallback(
(index: string | number) => {
const message = data[index];
if (!message) return;
const renderItem = useCallback(
(message: NDKEvent) => {
return (
<ChatMessageItem
message={message}
@@ -44,12 +42,9 @@ export function ChatScreen() {
[data]
);
const computeItemKey = useCallback(
(index: string | number) => {
return data[index].id;
},
[data]
);
useEffect(() => {
if (data.length > 0) listRef.current?.scrollToIndex(data.length);
}, [data]);
useEffect(() => {
const sub: NDKSubscription = ndk.subscribe(
@@ -86,22 +81,17 @@ export function ChatScreen() {
<p className="text-sm font-medium text-white/50">Loading messages</p>
</div>
</div>
) : data.length === 0 ? (
<div className="absolute left-1/2 top-1/2 flex w-full -translate-x-1/2 -translate-y-1/2 transform flex-col gap-1 text-center">
<h3 className="mb-2 text-4xl">🙌</h3>
<p className="leading-none text-white/50">
You two didn&apos;t talk yet, let&apos;s send first message
</p>
</div>
) : (
<Virtuoso
ref={virtuosoRef}
data={data}
itemContent={itemContent}
computeItemKey={computeItemKey}
initialTopMostItemIndex={data.length - 1}
alignToBottom={true}
followOutput={true}
overscan={50}
increaseViewportBy={{ top: 200, bottom: 200 }}
className="scrollbar-hide relative overflow-y-auto"
components={{
EmptyPlaceholder: () => Empty,
}}
/>
<VList ref={listRef} className="scrollbar-hide h-full" mode="reverse">
{data.map((message) => renderItem(message))}
</VList>
)}
</div>
<div className="z-50 shrink-0 rounded-b-xl border-t border-white/5 bg-white/10 p-3 px-5 backdrop-blur-xl">
@@ -120,12 +110,3 @@ export function ChatScreen() {
</div>
);
}
const Empty = (
<div className="absolute left-1/2 top-1/2 flex w-full -translate-x-1/2 -translate-y-1/2 transform flex-col gap-1 text-center">
<h3 className="mb-2 text-4xl">🙌</h3>
<p className="leading-none text-white/50">
You two didn&apos;t talk yet, let&apos;s send first message
</p>
</div>
);

View File

@@ -1,8 +1,8 @@
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
import { useQuery } from '@tanstack/react-query';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useCallback, useRef } from 'react';
import { useCallback } from 'react';
import { useParams } from 'react-router-dom';
import { VList } from 'virtua';
import { UserProfile } from '@app/users/components/profile';
@@ -32,79 +32,35 @@ export function UserScreen() {
return [...events] as unknown as NDKEvent[];
});
const parentRef = useRef();
const virtualizer = useVirtualizer({
count: data ? data.length : 0,
getScrollElement: () => parentRef.current,
estimateSize: () => 650,
overscan: 4,
});
const items = virtualizer.getVirtualItems();
// render event match event kind
const renderItem = useCallback(
(index: string | number) => {
const event: NDKEvent = data[index];
if (!event) return;
(event: NDKEvent) => {
switch (event.kind) {
case NDKKind.Text:
return (
<div
key={event.id + index}
data-index={index}
ref={virtualizer.measureElement}
>
<NoteWrapper event={event}>
<TextNote content={event.content} />
</NoteWrapper>
</div>
<NoteWrapper key={event.id} event={event}>
<TextNote />
</NoteWrapper>
);
case NDKKind.Repost:
return (
<div
key={event.id + index}
data-index={index}
ref={virtualizer.measureElement}
>
<Repost key={event.id} event={event} />
</div>
);
return <Repost key={event.id} event={event} />;
case 1063:
return (
<div
key={event.id + index}
data-index={index}
ref={virtualizer.measureElement}
>
<NoteWrapper event={event}>
<FileNote event={event} />
</NoteWrapper>
</div>
<NoteWrapper key={event.id} event={event}>
<FileNote />
</NoteWrapper>
);
case NDKKind.Article:
return (
<div
key={event.id + index}
data-index={index}
ref={virtualizer.measureElement}
>
<NoteWrapper event={event}>
<ArticleNote event={event} />
</NoteWrapper>
</div>
<NoteWrapper key={event.id} event={event}>
<ArticleNote />
</NoteWrapper>
);
default:
return (
<div
key={event.id + index}
data-index={index}
ref={virtualizer.measureElement}
>
<NoteWrapper event={event}>
<UnknownNote event={event} />
</NoteWrapper>
</div>
<NoteWrapper key={event.id} event={event}>
<UnknownNote />
</NoteWrapper>
);
}
},
@@ -112,10 +68,7 @@ export function UserScreen() {
);
return (
<div
ref={parentRef}
className="scrollbar-hide relative h-full w-full overflow-y-auto bg-white/10 backdrop-blur-xl"
>
<div className="scrollbar-hide relative h-full w-full overflow-y-auto bg-white/10 backdrop-blur-xl">
<div data-tauri-drag-region className="absolute left-0 top-0 h-11 w-full" />
<UserProfile pubkey={pubkey} />
<div className="mt-6 h-full w-full border-t border-white/5 px-1.5">
@@ -129,7 +82,7 @@ export function UserScreen() {
<NoteSkeleton />
</div>
</div>
) : items.length === 0 ? (
) : data.length === 0 ? (
<div className="px-3 py-1.5">
<div className="rounded-xl bg-white/10 px-3 py-6 backdrop-blur-xl">
<div className="flex flex-col items-center gap-4">
@@ -140,22 +93,10 @@ export function UserScreen() {
</div>
</div>
) : (
<div
style={{
position: 'relative',
width: '100%',
height: `${virtualizer.getTotalSize()}px`,
}}
>
<div
className="absolute left-0 top-0 w-full"
style={{
transform: `translateY(${items[0].start}px)`,
}}
>
{items.map((item) => renderItem(item.index))}
</div>
</div>
<VList className="scrollbar-hide h-full">
{data.map((item) => renderItem(item))}
<div className="h-16" />
</VList>
)}
</div>
</div>