wip: clean up & refactor
This commit is contained in:
@@ -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),
|
||||
});
|
||||
|
||||
@@ -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('#', ''),
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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];
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user