wip: update widget list

This commit is contained in:
2023-11-10 16:05:20 +07:00
parent 0cdf199cb5
commit 0710996a0d
15 changed files with 283 additions and 157 deletions

View File

@@ -15,7 +15,7 @@ interface Response {
profiles: Array<{ pubkey: string }>;
}
export function TrendingAccountsWidget({ params }: { params: Widget }) {
export function TrendingAccountsWidget({ widget }: { widget: Widget }) {
const { status, data } = useQuery({
queryKey: ['trending-profiles-widget'],
queryFn: async () => {
@@ -35,7 +35,7 @@ export function TrendingAccountsWidget({ params }: { params: Widget }) {
return (
<WidgetWrapper>
<TitleBar id={params.id} title="Trending Accounts" />
<TitleBar id={widget.id} title="Trending Accounts" />
<div className="flex-1">
{status === 'pending' ? (
<div className="flex h-full w-full items-center justify-center ">

View File

@@ -16,7 +16,7 @@ export function ToggleWidgetList() {
onClick={() =>
addWidget.mutate({ kind: WIDGET_KIND.list, title: '', content: '' })
}
className="inline-flex h-9 items-center gap-2 rounded-full bg-neutral-200 px-3 text-neutral-900 hover:bg-neutral-300 dark:bg-neutral-800 dark:text-neutral-100 dark:hover:bg-neutral-700"
className="inline-flex h-9 items-center gap-2 rounded-full bg-neutral-100 px-3 text-neutral-900 hover:bg-neutral-200 dark:bg-neutral-900 dark:text-neutral-100 dark:hover:bg-neutral-800"
>
<PlusIcon className="h-4 w-4 text-neutral-900 dark:text-zinc-100" />
<p className="text-sm font-semibold leading-none">Add widget</p>

View File

@@ -1,27 +1,196 @@
import {
ArticleIcon,
BellIcon,
GroupFeedsIcon,
HashtagIcon,
MediaIcon,
PlusIcon,
TrendingIcon,
} from '@shared/icons';
import { TitleBar } from '@shared/titleBar';
import { WidgetWrapper } from '@shared/widgets';
import { TOPICS, WIDGET_KIND } from '@stores/constants';
import { useWidget } from '@utils/hooks/useWidget';
import { Widget } from '@utils/types';
export function WidgetList({ widget }: { widget: Widget }) {
const { replaceWidget } = useWidget();
return (
<WidgetWrapper>
<TitleBar id={widget.id} title="Add widgets" />
<div className="flex-1 overflow-y-auto pb-10 scrollbar-none">
<div className="flex flex-col gap-6 px-3">
<div className="border-t border-neutral-200 pt-6 dark:border-neutral-800">
<button
type="button"
disabled
className="inline-flex h-14 w-full items-center justify-center gap-2.5 rounded-xl bg-neutral-50 text-sm font-medium text-neutral-900 dark:bg-neutral-950 dark:text-neutral-100"
>
Build your own widget{' '}
<div className="-rotate-3 transform-gpu rounded-md border border-neutral-200 bg-neutral-100 px-1.5 py-1 dark:border-neutral-800 dark:bg-neutral-900">
<span className="bg-gradient-to-r from-blue-400 via-red-400 to-orange-500 bg-clip-text text-xs text-transparent dark:from-blue-200 dark:via-red-200 dark:to-orange-300">
Coming soon
</span>
<div className="rounded-xl bg-neutral-100 p-3 dark:bg-neutral-900">
<h3 className="mb-2.5 text-sm font-semibold uppercase text-neutral-700 dark:text-neutral-300">
Topics
</h3>
<div className="flex flex-col gap-3">
{TOPICS.sort((a, b) => a.title.localeCompare(b.title)).map(
(topic, index) => (
<div
key={index}
className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50"
>
<div className="inline-flex items-center gap-2.5">
<div className="h-9 w-9 shrink-0 rounded-md">
<img
src={`/${topic.title.toLowerCase()}.jpg`}
alt={topic.title}
className="h-9 w-9 rounded-md"
/>
</div>
<p className="font-medium">{topic.title}</p>
</div>
<button
type="button"
onClick={() =>
replaceWidget.mutate({
currentId: widget.id,
widget: {
kind: WIDGET_KIND.topic,
title: topic.title,
content: JSON.stringify(topic.content),
},
})
}
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
)
)}
</div>
</div>
<div className="rounded-xl bg-neutral-100 p-3 dark:bg-neutral-900">
<h3 className="mb-2.5 text-sm font-semibold uppercase text-neutral-700 dark:text-neutral-300">
Newsfeed
</h3>
<div className="flex flex-col gap-3">
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<ArticleIcon className="h-4 w-4" />
</div>
<p className="font-medium">Article</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
</button>
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<MediaIcon className="h-4 w-4" />
</div>
<p className="font-medium">Media</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<GroupFeedsIcon className="h-4 w-4" />
</div>
<p className="font-medium">Group feeds</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<HashtagIcon className="h-4 w-4" />
</div>
<p className="font-medium">Hashtag</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
</div>
</div>
<div className="rounded-xl bg-neutral-100 p-3 dark:bg-neutral-900">
<h3 className="mb-2.5 text-sm font-semibold uppercase text-neutral-700 dark:text-neutral-300">
Nostr Band
</h3>
<div className="flex flex-col gap-3">
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<TrendingIcon className="h-4 w-4" />
</div>
<p className="font-medium">Trending posts</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<TrendingIcon className="h-4 w-4" />
</div>
<p className="font-medium">Trending users</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
</div>
</div>
<div className="rounded-xl bg-neutral-100 p-3 dark:bg-neutral-900">
<h3 className="mb-2.5 text-sm font-semibold uppercase text-neutral-700 dark:text-neutral-300">
Other
</h3>
<div className="flex flex-col gap-3">
<div className="inline-flex h-14 w-full items-center justify-between rounded-lg bg-white px-3 hover:shadow-md hover:shadow-neutral-200/50 dark:hover:shadow-neutral-800/50">
<div className="inline-flex items-center gap-2.5">
<div className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-neutral-100">
<BellIcon className="h-4 w-4" />
</div>
<p className="font-medium">Notification</p>
</div>
<button
type="button"
className="inline-flex h-6 items-center gap-1 rounded-md bg-neutral-100 pl-1.5 pr-2.5 text-sm font-medium hover:bg-blue-500 hover:text-white dark:bg-neutral-900"
>
<PlusIcon className="h-3 w-3" />
Add
</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,5 +1,6 @@
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
import { useInfiniteQuery } from '@tanstack/react-query';
import { FetchFilter } from 'nostr-fetch';
import { useCallback, useMemo } from 'react';
import { VList } from 'virtua';
@@ -33,18 +34,18 @@ export function TopicWidget({ widget }: { widget: Widget }) {
pageParam: number;
}) => {
const hashtags: string[] = JSON.parse(widget.content as string);
const filter: FetchFilter = {
kinds: [NDKKind.Text, NDKKind.Repost],
'#t': hashtags.map((tag) => tag.replace('#', '')),
};
const rootIds = new Set();
const dedupQueue = new Set();
const events = await fetcher.fetchLatestEvents(
relayUrls,
{
kinds: [NDKKind.Text, NDKKind.Repost],
'#t': hashtags,
},
FETCH_LIMIT,
{ asOf: pageParam === 0 ? undefined : pageParam, abortSignal: signal }
);
const events = await fetcher.fetchLatestEvents(relayUrls, filter, FETCH_LIMIT, {
asOf: pageParam === 0 ? undefined : pageParam,
abortSignal: signal,
});
const ndkEvents = events.map((event) => {
return new NDKEvent(ndk, event);