refactor all widgets

This commit is contained in:
2023-11-01 08:07:49 +07:00
parent e7738fb128
commit fd5ecc18a9
37 changed files with 1096 additions and 1271 deletions

View File

@@ -1,4 +1,5 @@
import { useCallback, useEffect, useRef } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useCallback, useRef, useState } from 'react';
import { VList, VListHandle } from 'virtua';
import { ToggleWidgetList } from '@app/space/components/toggle';
@@ -11,99 +12,134 @@ import {
GlobalArticlesWidget,
GlobalFilesWidget,
GlobalHashtagWidget,
LearnNostrWidget,
LocalArticlesWidget,
LocalFeedsWidget,
LocalFilesWidget,
LocalFollowsWidget,
LocalNotificationWidget,
LocalThreadWidget,
LocalUserWidget,
NewsfeedWidget,
NotificationWidget,
TrendingAccountsWidget,
TrendingNotesWidget,
XfeedsWidget,
XhashtagWidget,
} from '@shared/widgets';
import { WidgetKinds, useWidgets } from '@stores/widgets';
import { WidgetKinds } from '@stores/constants';
import { Widget } from '@utils/types';
export function SpaceScreen() {
const ref = useRef<VListHandle>(null);
const [selectedIndex, setSelectedIndex] = useState(-1);
const { db } = useStorage();
const vlistRef = useRef<VListHandle>(null);
const { status, data } = useQuery({
queryKey: ['widgets'],
queryFn: async () => {
const dbWidgets = await db.getWidgets();
const defaultWidgets = [
{
id: '9998',
title: 'Notification',
content: '',
kind: WidgetKinds.local.notification,
},
{
id: '9999',
title: 'Newsfeed',
content: '',
kind: WidgetKinds.local.network,
},
];
const [widgets, fetchWidgets] = useWidgets((state) => [
state.widgets,
state.fetchWidgets,
]);
const renderItem = useCallback(
(widget: Widget) => {
if (!widget) return;
switch (widget.kind) {
case WidgetKinds.local.network:
return <NewsfeedWidget key={widget.id} />;
case WidgetKinds.local.follows:
return <LocalFollowsWidget key={widget.id} params={widget} />;
case WidgetKinds.local.feeds:
return <LocalFeedsWidget key={widget.id} params={widget} />;
case WidgetKinds.local.files:
return <LocalFilesWidget key={widget.id} params={widget} />;
case WidgetKinds.local.articles:
return <LocalArticlesWidget key={widget.id} params={widget} />;
case WidgetKinds.local.user:
return <LocalUserWidget key={widget.id} params={widget} />;
case WidgetKinds.local.thread:
return <LocalThreadWidget key={widget.id} params={widget} />;
case WidgetKinds.global.hashtag:
return <GlobalHashtagWidget key={widget.id} params={widget} />;
case WidgetKinds.global.articles:
return <GlobalArticlesWidget key={widget.id} params={widget} />;
case WidgetKinds.global.files:
return <GlobalFilesWidget key={widget.id} params={widget} />;
case WidgetKinds.nostrBand.trendingAccounts:
return <TrendingAccountsWidget key={widget.id} params={widget} />;
case WidgetKinds.nostrBand.trendingNotes:
return <TrendingNotesWidget key={widget.id} params={widget} />;
case WidgetKinds.tmp.xfeed:
return <XfeedsWidget key={widget.id} params={widget} />;
case WidgetKinds.tmp.xhashtag:
return <XhashtagWidget key={widget.id} params={widget} />;
case WidgetKinds.tmp.list:
return <WidgetList key={widget.id} params={widget} />;
case WidgetKinds.other.learnNostr:
return <LearnNostrWidget key={widget.id} params={widget} />;
case WidgetKinds.local.notification:
return <LocalNotificationWidget key={widget.id} params={widget} />;
default:
return null;
}
return [...defaultWidgets, ...dbWidgets];
},
[widgets]
);
refetchOnMount: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
staleTime: Infinity,
});
useEffect(() => {
fetchWidgets(db);
const renderItem = useCallback((widget: Widget) => {
switch (widget.kind) {
case WidgetKinds.local.feeds:
return <LocalFeedsWidget key={widget.id} params={widget} />;
case WidgetKinds.local.files:
return <LocalFilesWidget key={widget.id} params={widget} />;
case WidgetKinds.local.articles:
return <LocalArticlesWidget key={widget.id} params={widget} />;
case WidgetKinds.local.user:
return <LocalUserWidget key={widget.id} params={widget} />;
case WidgetKinds.local.thread:
return <LocalThreadWidget key={widget.id} params={widget} />;
case WidgetKinds.global.hashtag:
return <GlobalHashtagWidget key={widget.id} params={widget} />;
case WidgetKinds.global.articles:
return <GlobalArticlesWidget key={widget.id} params={widget} />;
case WidgetKinds.global.files:
return <GlobalFilesWidget key={widget.id} params={widget} />;
case WidgetKinds.nostrBand.trendingAccounts:
return <TrendingAccountsWidget key={widget.id} params={widget} />;
case WidgetKinds.nostrBand.trendingNotes:
return <TrendingNotesWidget key={widget.id} params={widget} />;
case WidgetKinds.tmp.xfeed:
return <XfeedsWidget key={widget.id} params={widget} />;
case WidgetKinds.tmp.xhashtag:
return <XhashtagWidget key={widget.id} params={widget} />;
case WidgetKinds.tmp.list:
return <WidgetList key={widget.id} params={widget} />;
case WidgetKinds.local.notification:
return <NotificationWidget key={widget.id} />;
case WidgetKinds.local.network:
return <NewsfeedWidget key={widget.id} />;
default:
return null;
}
}, []);
if (status === 'pending') {
return (
<div className="flex h-full w-full items-center justify-center">
<LoaderIcon className="h-5 w-5 animate-spin" />
</div>
);
}
return (
<VList
className="h-full w-full flex-nowrap overflow-x-auto !overflow-y-hidden scrollbar-none focus:outline-none"
horizontal
ref={vlistRef}
ref={ref}
initialItemSize={420}
aria-current="step"
tabIndex={0}
onKeyDown={(e) => {
if (!ref.current) return;
switch (e.code) {
case 'ArrowLeft': {
e.preventDefault();
const prevIndex = Math.max(selectedIndex - 1, 0);
setSelectedIndex(prevIndex);
ref.current.scrollToIndex(prevIndex, {
align: 'center',
smooth: true,
});
break;
}
case 'ArrowRight': {
e.preventDefault();
const nextIndex = Math.min(selectedIndex + 1, data.length - 1);
setSelectedIndex(nextIndex);
ref.current.scrollToIndex(nextIndex, {
align: 'center',
smooth: true,
});
break;
}
}
}}
>
{!widgets ? (
<div className="flex h-full w-[420px] flex-col items-center justify-center">
<LoaderIcon className="h-5 w-5 animate-spin text-neutral-900 dark:text-neutral-100" />
</div>
) : (
widgets.map((widget) => renderItem(widget))
)}
{data.map((widget) => renderItem(widget))}
<ToggleWidgetList />
</VList>
);