wip: clean up & refactor

This commit is contained in:
Ren Amamiya
2023-08-16 20:52:09 +07:00
parent c05bb54976
commit ab61bfb2cd
79 changed files with 183 additions and 2618 deletions

View File

@@ -10,7 +10,7 @@ import { useStorage } from '@libs/storage/provider';
import { CancelIcon, CheckCircleIcon, CommandIcon, LoaderIcon } from '@shared/icons';
import { BLOCK_KINDS, DEFAULT_AVATAR } from '@stores/constants';
import { DEFAULT_AVATAR, widgetKinds } from '@stores/constants';
import { useWidgets } from '@stores/widgets';
export function FeedModal() {
@@ -40,7 +40,7 @@ export function FeedModal() {
// update state
setWidget(db, {
kind: BLOCK_KINDS.feed,
kind: widgetKinds.feed,
title: data.title,
content: JSON.stringify(selected),
});

View File

@@ -6,7 +6,7 @@ import { useStorage } from '@libs/storage/provider';
import { CancelIcon, CommandIcon, LoaderIcon } from '@shared/icons';
import { BLOCK_KINDS } from '@stores/constants';
import { widgetKinds } from '@stores/constants';
import { useWidgets } from '@stores/widgets';
export function HashtagModal() {
@@ -28,7 +28,7 @@ export function HashtagModal() {
// update state
setWidget(db, {
kind: BLOCK_KINDS.hashtag,
kind: widgetKinds.hashtag,
title: data.hashtag,
content: data.hashtag.replace('#', ''),
});

View File

@@ -7,7 +7,7 @@ import { useStorage } from '@libs/storage/provider';
import { CancelIcon, CommandIcon, LoaderIcon } from '@shared/icons';
import { Image } from '@shared/image';
import { BLOCK_KINDS, DEFAULT_AVATAR } from '@stores/constants';
import { DEFAULT_AVATAR, widgetKinds } from '@stores/constants';
import { useWidgets } from '@stores/widgets';
import { useImageUploader } from '@utils/hooks/useUploader';
@@ -40,7 +40,7 @@ export function ImageModal() {
setLoading(true);
// mutate
setWidget(db, { kind: BLOCK_KINDS.image, title: data.title, content: data.content });
setWidget(db, { kind: widgetKinds.image, title: data.title, content: data.content });
setLoading(false);
// reset form

View File

@@ -2,8 +2,6 @@ import { useInfiniteQuery } from '@tanstack/react-query';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useCallback, useEffect, useRef } from 'react';
import { getNotesByAuthors } from '@libs/storage';
import { NoteKind_1, NoteKind_1063, NoteThread, Repost } from '@shared/notes';
import { NoteKindUnsupport } from '@shared/notes/kinds/unsupport';
import { NoteSkeleton } from '@shared/notes/skeleton';
@@ -11,14 +9,12 @@ import { TitleBar } from '@shared/titleBar';
import { LumeEvent, Widget } from '@utils/types';
const ITEM_PER_PAGE = 10;
export function FeedBlock({ params }: { params: Widget }) {
const { status, data, fetchNextPage, hasNextPage, isFetchingNextPage } =
useInfiniteQuery({
queryKey: ['newsfeed', params.content],
queryFn: async ({ pageParam = 0 }) => {
return await getNotesByAuthors(params.content, ITEM_PER_PAGE, pageParam);
queryFn: async () => {
return { data: [], nextCursor: 0 };
},
getNextPageParam: (lastPage) => lastPage.nextCursor,
});

View File

@@ -1,36 +0,0 @@
import { CancelIcon } from '@shared/icons';
import { Image } from '@shared/image';
import { DEFAULT_AVATAR } from '@stores/constants';
import { useWidgets } from '@stores/widgets';
import { Widget } from '@utils/types';
export function ImageBlock({ params }: { params: Widget }) {
const remove = useWidgets((state) => state.removeWidget);
return (
<div className="flex h-full w-[400px] shrink-0 flex-col justify-between">
<div className="relative h-full w-full flex-1 overflow-hidden p-3">
<div className="absolute left-0 top-3 h-16 w-full px-3">
<div className="flex h-16 items-center justify-between overflow-hidden rounded-t-xl px-5">
<h3 className="font-medium text-white drop-shadow-lg">{params.title}</h3>
<button
type="button"
onClick={() => remove(params.id)}
className="inline-flex h-7 w-7 items-center justify-center rounded-md bg-white/30 backdrop-blur-lg"
>
<CancelIcon width={16} height={16} className="text-white" />
</button>
</div>
</div>
<Image
src={params.content}
fallback={DEFAULT_AVATAR}
alt={params.title}
className="h-full w-full rounded-xl object-cover"
/>
</div>
</div>
);
}

View File

@@ -1,9 +1,11 @@
import { NDKFilter } from '@nostr-dev-kit/ndk';
import { useInfiniteQuery } from '@tanstack/react-query';
import { useVirtualizer } from '@tanstack/react-virtual';
import { NostrEvent } from 'nostr-fetch';
import { useCallback, useMemo, useRef } from 'react';
import { useCallback, useEffect, useMemo, useRef } from 'react';
import { Link } from 'react-router-dom';
import { useStorage } from '@libs/storage/provider';
import { NoteKind_1, NoteKind_1063, NoteThread, Repost } from '@shared/notes';
import { NoteKindUnsupport } from '@shared/notes/kinds/unsupport';
import { NoteSkeleton } from '@shared/notes/skeleton';
@@ -13,11 +15,12 @@ import { useNostr } from '@utils/hooks/useNostr';
import { LumeEvent } from '@utils/types';
export function NetworkBlock() {
const { fetchNotes } = useNostr();
const { db } = useStorage();
const { sub, fetchNotes } = useNostr();
const { status, data, hasNextPage, isFetchingNextPage } = useInfiniteQuery({
queryKey: ['network-widget'],
queryFn: async ({ pageParam = 24 }) => {
return await fetchNotes(pageParam);
return { data: [], nextCursor: 0 };
},
getNextPageParam: (lastPage) => lastPage.nextCursor,
refetchOnWindowFocus: false,
@@ -26,8 +29,7 @@ export function NetworkBlock() {
const parentRef = useRef();
const notes = useMemo(
// @ts-expect-error, todo
() => (data ? data.pages.flatMap((d: { data: NostrEvent[] }) => d.data) : []),
() => (data ? data.pages.flatMap((d: { data: LumeEvent[] }) => d.data) : []),
[data]
);
@@ -37,10 +39,20 @@ export function NetworkBlock() {
estimateSize: () => 500,
overscan: 2,
});
const itemsVirtualizer = rowVirtualizer.getVirtualItems();
const totalSize = rowVirtualizer.getTotalSize();
useEffect(() => {
const since = Math.floor(Date.now() / 1000);
const filter: NDKFilter = {
kinds: [1, 6],
authors: db.account.network,
since: since,
};
sub(filter, (event) => console.log('[network] event received: ', event));
}, []);
const renderItem = useCallback(
(index: string | number) => {
const note: LumeEvent = notes[index];

View File

@@ -1,48 +0,0 @@
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useEffect, useRef } from 'react';
import { useNDK } from '@libs/ndk/provider';
import { createReplyNote } from '@libs/storage';
export function useLiveThread(id: string) {
const queryClient = useQueryClient();
const now = useRef(Math.floor(Date.now() / 1000));
const { ndk } = useNDK();
const thread = useMutation({
mutationFn: (data: NDKEvent) => {
return createReplyNote(
id,
data.id,
data.pubkey,
data.kind,
data.tags,
data.content,
data.created_at
);
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['replies', id] });
},
});
useEffect(() => {
const filter: NDKFilter = {
kinds: [1],
'#e': [id],
since: now.current,
};
const sub = ndk.subscribe(filter, { closeOnEose: false });
sub.addListener('event', (event: NDKEvent) => {
thread.mutate(event);
});
return () => {
sub.stop();
};
}, []);
}

View File

@@ -1,45 +0,0 @@
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk';
import { useEffect, useRef } from 'react';
import { useNDK } from '@libs/ndk/provider';
import { createNote } from '@libs/storage';
import { useAccount } from '@utils/hooks/useAccount';
export function useNewsfeed() {
const sub = useRef(null);
const now = useRef(Math.floor(Date.now() / 1000));
const { ndk } = useNDK();
const { status, account } = useAccount();
useEffect(() => {
if (status === 'success' && account) {
const filter: NDKFilter = {
kinds: [1, 6],
authors: account.follows,
since: now.current,
};
sub.current = ndk.subscribe(filter, { closeOnEose: false });
sub.current.addListener('event', (event: NDKEvent) => {
// add to db
createNote(
event.id,
event.pubkey,
event.kind,
event.tags,
event.content,
event.created_at
);
});
}
return () => {
if (sub.current) {
sub.current.stop();
}
};
}, [status]);
}

View File

@@ -5,7 +5,6 @@ import { HashtagModal } from '@app/space/components/modals/hashtag';
import { ImageModal } from '@app/space/components/modals/image';
import { FeedBlock } from '@app/space/components/widgets/feed';
import { HashtagBlock } from '@app/space/components/widgets/hashtag';
import { ImageBlock } from '@app/space/components/widgets/image';
import { NetworkBlock } from '@app/space/components/widgets/network';
import { ThreadBlock } from '@app/space/components/widgets/thread';
import { UserBlock } from '@app/space/components/widgets/user';
@@ -19,18 +18,16 @@ import { useWidgets } from '@stores/widgets';
import { Widget } from '@utils/types';
export function SpaceScreen() {
const { db } = useStorage();
const [widgets, fetchWidgets] = useWidgets((state) => [
state.widgets,
state.fetchWidgets,
]);
const { db } = useStorage();
const renderItem = useCallback(
(widget: Widget) => {
switch (widget.kind) {
case 0:
return <ImageBlock key={widget.id} params={widget} />;
case 1:
return <FeedBlock key={widget.id} params={widget} />;
case 2:
@@ -39,6 +36,8 @@ export function SpaceScreen() {
return <HashtagBlock key={widget.id} params={widget} />;
case 5:
return <UserBlock key={widget.id} params={widget} />;
case 9999:
return <NetworkBlock key={widget.id} />;
default:
break;
}
@@ -52,7 +51,6 @@ export function SpaceScreen() {
return (
<div className="scrollbar-hide flex h-full w-full flex-nowrap divide-x divide-white/5 overflow-x-auto overflow-y-hidden">
<NetworkBlock />
{!widgets ? (
<div className="flex w-[350px] shrink-0 flex-col">
<div className="flex w-full flex-1 items-center justify-center p-3">