wip: rework widget
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
|
||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
||||
import { FetchFilter } from 'nostr-fetch';
|
||||
import { useMemo } from 'react';
|
||||
import { VList } from 'virtua';
|
||||
|
||||
@@ -15,12 +16,12 @@ import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function LocalArticlesWidget({ params }: { params: Widget }) {
|
||||
export function ArticleWidget({ widget }: { widget: Widget }) {
|
||||
const { db } = useStorage();
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['local-articles'],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
@@ -29,15 +30,24 @@ export function LocalArticlesWidget({ params }: { params: Widget }) {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
const events = await fetcher.fetchLatestEvents(
|
||||
relayUrls,
|
||||
{
|
||||
let filter: FetchFilter;
|
||||
const content = JSON.parse(widget.content);
|
||||
|
||||
if (content.global) {
|
||||
filter = {
|
||||
kinds: [NDKKind.Article],
|
||||
};
|
||||
} else {
|
||||
filter = {
|
||||
kinds: [NDKKind.Article],
|
||||
authors: db.account.circles,
|
||||
},
|
||||
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);
|
||||
@@ -61,7 +71,7 @@ export function LocalArticlesWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<TitleBar id={widget.id} title={widget.title} />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
||||
import { FetchFilter } from 'nostr-fetch';
|
||||
import { useMemo } from 'react';
|
||||
import { VList } from 'virtua';
|
||||
|
||||
@@ -15,12 +16,12 @@ import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function LocalFilesWidget({ params }: { params: Widget }) {
|
||||
export function FileWidget({ widget }: { widget: Widget }) {
|
||||
const { db } = useStorage();
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['local-files'],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
@@ -29,15 +30,24 @@ export function LocalFilesWidget({ params }: { params: Widget }) {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
const events = await fetcher.fetchLatestEvents(
|
||||
relayUrls,
|
||||
{
|
||||
let filter: FetchFilter;
|
||||
const content = JSON.parse(widget.content);
|
||||
|
||||
if (content.global) {
|
||||
filter = {
|
||||
kinds: [1063],
|
||||
};
|
||||
} else {
|
||||
filter = {
|
||||
kinds: [1063],
|
||||
authors: db.account.circles,
|
||||
},
|
||||
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);
|
||||
@@ -61,7 +71,7 @@ export function LocalFilesWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<TitleBar id={widget.id} title={widget.title} />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
@@ -1,106 +0,0 @@
|
||||
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
|
||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
import { VList } from 'virtua';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
|
||||
import { ArrowRightCircleIcon, LoaderIcon } from '@shared/icons';
|
||||
import { MemoizedArticleNote } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function GlobalArticlesWidget({ params }: { params: Widget }) {
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['global-articles'],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
pageParam,
|
||||
}: {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
const events = await fetcher.fetchLatestEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [NDKKind.Article],
|
||||
},
|
||||
FETCH_LIMIT,
|
||||
{ asOf: pageParam === 0 ? undefined : pageParam, abortSignal: signal }
|
||||
);
|
||||
|
||||
const ndkEvents = events.map((event) => {
|
||||
return new NDKEvent(ndk, event);
|
||||
});
|
||||
|
||||
return ndkEvents.sort((a, b) => b.created_at - a.created_at);
|
||||
},
|
||||
getNextPageParam: (lastPage) => {
|
||||
const lastEvent = lastPage.at(-1);
|
||||
if (!lastEvent) return;
|
||||
return lastEvent.created_at - 1;
|
||||
},
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
});
|
||||
|
||||
const allEvents = useMemo(
|
||||
() => (data ? data.pages.flatMap((page) => page) : []),
|
||||
[data]
|
||||
);
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<LoaderIcon className="h-5 w-5 animate-spin" />
|
||||
</div>
|
||||
) : allEvents.length === 0 ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center px-3">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<img src="/ghost.png" alt="empty feeds" className="h-16 w-16" />
|
||||
<div className="text-center">
|
||||
<h3 className="font-semibold leading-tight text-neutral-900 dark:text-neutral-100">
|
||||
Oops, it looks like there are no articles.
|
||||
</h3>
|
||||
<p className="text-neutral-500 dark:text-neutral-400">
|
||||
You can close this widget
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
allEvents.map((item) => <MemoizedArticleNote key={item.id} event={item} />)
|
||||
)}
|
||||
<div className="flex h-16 items-center justify-center px-3 pb-3">
|
||||
{hasNextPage ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => fetchNextPage()}
|
||||
disabled={!hasNextPage || isFetchingNextPage}
|
||||
className="inline-flex h-10 w-max items-center justify-center gap-2 rounded-full bg-blue-500 px-6 font-medium text-white hover:bg-blue-600 focus:outline-none"
|
||||
>
|
||||
{isFetchingNextPage ? (
|
||||
<LoaderIcon className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
<ArrowRightCircleIcon className="h-5 w-5" />
|
||||
Load more
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</VList>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { useInfiniteQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
import { VList } from 'virtua';
|
||||
|
||||
import { useNDK } from '@libs/ndk/provider';
|
||||
|
||||
import { ArrowRightCircleIcon, LoaderIcon } from '@shared/icons';
|
||||
import { MemoizedFileNote } from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function GlobalFilesWidget({ params }: { params: Widget }) {
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['global-files'],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
pageParam,
|
||||
}: {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
const events = await fetcher.fetchLatestEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [1063],
|
||||
},
|
||||
FETCH_LIMIT,
|
||||
{ asOf: pageParam === 0 ? undefined : pageParam, abortSignal: signal }
|
||||
);
|
||||
|
||||
const ndkEvents = events.map((event) => {
|
||||
return new NDKEvent(ndk, event);
|
||||
});
|
||||
|
||||
return ndkEvents.sort((a, b) => b.created_at - a.created_at);
|
||||
},
|
||||
getNextPageParam: (lastPage) => {
|
||||
const lastEvent = lastPage.at(-1);
|
||||
if (!lastEvent) return;
|
||||
return lastEvent.created_at - 1;
|
||||
},
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
});
|
||||
|
||||
const allEvents = useMemo(
|
||||
() => (data ? data.pages.flatMap((page) => page) : []),
|
||||
[data]
|
||||
);
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<LoaderIcon className="h-5 w-5 animate-spin" />
|
||||
</div>
|
||||
) : allEvents.length === 0 ? (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center px-3">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<img src="/ghost.png" alt="empty feeds" className="h-16 w-16" />
|
||||
<div className="text-center">
|
||||
<h3 className="font-semibold leading-tight text-neutral-900 dark:text-neutral-100">
|
||||
Oops, it looks like there are no files.
|
||||
</h3>
|
||||
<p className="text-neutral-500 dark:text-neutral-400">
|
||||
You can close this widget
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
allEvents.map((item) => <MemoizedFileNote key={item.id} event={item} />)
|
||||
)}
|
||||
<div className="flex h-16 items-center justify-center px-3 pb-3">
|
||||
{hasNextPage ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => fetchNextPage()}
|
||||
disabled={!hasNextPage || isFetchingNextPage}
|
||||
className="inline-flex h-10 w-max items-center justify-center gap-2 rounded-full bg-blue-500 px-6 font-medium text-white hover:bg-blue-600 focus:outline-none"
|
||||
>
|
||||
{isFetchingNextPage ? (
|
||||
<LoaderIcon className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<>
|
||||
<ArrowRightCircleIcon className="h-5 w-5" />
|
||||
Load more
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</VList>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
@@ -19,11 +19,11 @@ import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function LocalFeedsWidget({ params }: { params: Widget }) {
|
||||
export function GroupWidget({ widget }: { widget: Widget }) {
|
||||
const { relayUrls, ndk, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['group-feeds-' + params.id],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
@@ -32,11 +32,12 @@ export function LocalFeedsWidget({ params }: { params: Widget }) {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
const authors = JSON.parse(widget.content);
|
||||
const events = await fetcher.fetchLatestEvents(
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [NDKKind.Text, NDKKind.Repost],
|
||||
authors: JSON.parse(params.content),
|
||||
authors: authors,
|
||||
},
|
||||
FETCH_LIMIT,
|
||||
{ asOf: pageParam === 0 ? undefined : pageParam, abortSignal: signal }
|
||||
@@ -78,7 +79,7 @@ export function LocalFeedsWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<TitleBar id={widget.id} title={widget.title} />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="px-3 py-1.5">
|
||||
@@ -14,11 +14,11 @@ import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function GlobalHashtagWidget({ params }: { params: Widget }) {
|
||||
export function HashtagWidget({ widget }: { widget: Widget }) {
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: ['hashtag-' + params.title],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
@@ -31,7 +31,7 @@ export function GlobalHashtagWidget({ params }: { params: Widget }) {
|
||||
relayUrls,
|
||||
{
|
||||
kinds: [NDKKind.Text, NDKKind.Repost],
|
||||
'#t': [params.content],
|
||||
'#t': [widget.content],
|
||||
},
|
||||
FETCH_LIMIT,
|
||||
{ asOf: pageParam === 0 ? undefined : pageParam, abortSignal: signal }
|
||||
@@ -74,7 +74,7 @@ export function GlobalHashtagWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<TitleBar id={widget.id} title={widget.title} />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
@@ -86,7 +86,7 @@ export function GlobalHashtagWidget({ params }: { params: Widget }) {
|
||||
<img src="/ghost.png" alt="empty feeds" className="h-16 w-16" />
|
||||
<div className="text-center">
|
||||
<h3 className="font-semibold leading-tight text-neutral-900 dark:text-neutral-100">
|
||||
Oops, it looks like there are no events related to {params.title}.
|
||||
Oops, it looks like there are no events related to {widget.content}.
|
||||
</h3>
|
||||
<p className="text-neutral-500 dark:text-neutral-400">
|
||||
You can close this widget
|
||||
@@ -1,17 +1,15 @@
|
||||
export * from './wrapper';
|
||||
export * from './local/feeds';
|
||||
export * from './local/user';
|
||||
export * from './local/thread';
|
||||
export * from './local/files';
|
||||
export * from './local/articles';
|
||||
export * from './global/articles';
|
||||
export * from './global/files';
|
||||
export * from './global/hashtag';
|
||||
export * from './nostrBand/trendingNotes';
|
||||
export * from './nostrBand/trendingAccounts';
|
||||
export * from './tmp/feeds';
|
||||
export * from './tmp/hashtag';
|
||||
export * from './newsfeed';
|
||||
export * from './notification';
|
||||
export * from './liveUpdater';
|
||||
export * from './topic';
|
||||
export * from './user';
|
||||
export * from './article';
|
||||
export * from './file';
|
||||
export * from './hashtag';
|
||||
export * from './thread';
|
||||
export * from './group';
|
||||
export * from './nostrBand/trendingAccounts';
|
||||
export * from './nostrBand/trendingNotes';
|
||||
export * from './other/wrapper';
|
||||
export * from './other/liveUpdater';
|
||||
export * from './other/toggleWidgetList';
|
||||
export * from './other/widgetList';
|
||||
|
||||
@@ -14,8 +14,7 @@ import {
|
||||
UnknownNote,
|
||||
} from '@shared/notes';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
import { LiveUpdater } from '@shared/widgets';
|
||||
import { LiveUpdater, WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { FETCH_LIMIT } from '@stores/constants';
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ import { VList } from 'virtua';
|
||||
import { LoaderIcon } from '@shared/icons';
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
import { NostrBandUserProfile, type Profile } from '@shared/widgets/nostrBandUserProfile';
|
||||
import {
|
||||
NostrBandUserProfile,
|
||||
type Profile,
|
||||
} from '@shared/widgets/other/nostrBandUserProfile';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ interface Response {
|
||||
notes: Array<{ event: NDKEvent }>;
|
||||
}
|
||||
|
||||
export function TrendingNotesWidget({ params }: { params: Widget }) {
|
||||
export function TrendingNotesWidget({ widget }: { widget: Widget }) {
|
||||
const { status, data } = useQuery({
|
||||
queryKey: ['trending-notes-widget'],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
queryFn: async () => {
|
||||
const res = await fetch('https://api.nostr.band/v0/trending/notes');
|
||||
if (!res.ok) {
|
||||
@@ -33,7 +33,7 @@ export function TrendingNotesWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title="Trending Notes" />
|
||||
<TitleBar id={widget.id} title="Trending Notes" />
|
||||
<VList className="flex-1">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-full w-full items-center justify-center ">
|
||||
|
||||
27
src/shared/widgets/other/toggleWidgetList.tsx
Normal file
27
src/shared/widgets/other/toggleWidgetList.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { PlusIcon } from '@shared/icons';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { WIDGET_KIND } from '@stores/constants';
|
||||
|
||||
import { useWidget } from '@utils/hooks/useWidget';
|
||||
|
||||
export function ToggleWidgetList() {
|
||||
const { addWidget } = useWidget();
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<div className="relative flex h-full w-full flex-col items-center justify-center">
|
||||
<button
|
||||
type="button"
|
||||
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"
|
||||
>
|
||||
<PlusIcon className="h-4 w-4 text-neutral-900 dark:text-zinc-100" />
|
||||
<p className="text-sm font-semibold leading-none">Add widget</p>
|
||||
</button>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
30
src/shared/widgets/other/widgetList.tsx
Normal file
30
src/shared/widgets/other/widgetList.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { TitleBar } from '@shared/titleBar';
|
||||
import { WidgetWrapper } from '@shared/widgets';
|
||||
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function WidgetList({ widget }: { widget: Widget }) {
|
||||
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>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
);
|
||||
}
|
||||
@@ -18,8 +18,8 @@ import { WidgetWrapper } from '@shared/widgets';
|
||||
import { useEvent } from '@utils/hooks/useEvent';
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function LocalThreadWidget({ params }: { params: Widget }) {
|
||||
const { status, data } = useEvent(params.content);
|
||||
export function ThreadWidget({ widget }: { widget: Widget }) {
|
||||
const { status, data } = useEvent(widget.content);
|
||||
|
||||
const renderKind = useCallback(
|
||||
(event: NDKEvent) => {
|
||||
@@ -39,7 +39,7 @@ export function LocalThreadWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<TitleBar id={widget.id} title={widget.title} />
|
||||
<WVList className="flex-1 overflow-y-auto px-3 pb-5">
|
||||
{status === 'pending' ? (
|
||||
<div className="flex h-16 items-center justify-center rounded-xl bg-neutral-50 px-3 py-3 dark:bg-neutral-950">
|
||||
@@ -52,7 +52,7 @@ export function LocalThreadWidget({ params }: { params: Widget }) {
|
||||
{renderKind(data)}
|
||||
<NoteActions id={data.id} pubkey={data.pubkey} />
|
||||
</div>
|
||||
<NoteReplyForm eventId={params.content} />
|
||||
<NoteReplyForm eventId={widget.content} />
|
||||
<ReplyList eventId={data.id} />
|
||||
</>
|
||||
)}
|
||||
@@ -28,7 +28,7 @@ export function XfeedsWidget({ params }: { params: Widget }) {
|
||||
|
||||
const submit = async () => {
|
||||
addWidget.mutate({
|
||||
kind: WIDGET_KIND.local.feeds,
|
||||
kind: WIDGET_KIND.group,
|
||||
title: title || 'Group',
|
||||
content: JSON.stringify(groups),
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ export function XhashtagWidget({ params }: { params: Widget }) {
|
||||
const onSubmit = async (data: FormValues) => {
|
||||
try {
|
||||
addWidget.mutate({
|
||||
kind: WIDGET_KIND.global.hashtag,
|
||||
kind: WIDGET_KIND.hashtag,
|
||||
title: data.hashtag,
|
||||
content: data.hashtag.replace('#', ''),
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ export function TopicWidget({ widget }: { widget: Widget }) {
|
||||
const { relayUrls, ndk, fetcher } = useNDK();
|
||||
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
|
||||
useInfiniteQuery({
|
||||
queryKey: [widget.title],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
|
||||
@@ -18,17 +18,17 @@ import { WidgetWrapper } from '@shared/widgets';
|
||||
import { nHoursAgo } from '@utils/date';
|
||||
import { Widget } from '@utils/types';
|
||||
|
||||
export function LocalUserWidget({ params }: { params: Widget }) {
|
||||
export function UserWidget({ widget }: { widget: Widget }) {
|
||||
const { ndk } = useNDK();
|
||||
const { status, data } = useQuery({
|
||||
queryKey: ['user-posts', params.content],
|
||||
queryKey: ['widget-' + widget.id],
|
||||
queryFn: async () => {
|
||||
const rootIds = new Set();
|
||||
const dedupQueue = new Set();
|
||||
|
||||
const events = await ndk.fetchEvents({
|
||||
kinds: [NDKKind.Text, NDKKind.Repost],
|
||||
authors: [params.content],
|
||||
authors: [widget.content],
|
||||
since: nHoursAgo(24),
|
||||
});
|
||||
|
||||
@@ -70,10 +70,10 @@ export function LocalUserWidget({ params }: { params: Widget }) {
|
||||
|
||||
return (
|
||||
<WidgetWrapper>
|
||||
<TitleBar id={params.id} title={params.title} />
|
||||
<TitleBar id={widget.id} title={widget.title} />
|
||||
<WVList className="flex-1 overflow-y-auto">
|
||||
<div className="px-3 pt-1.5">
|
||||
<UserProfile pubkey={params.content} />
|
||||
<UserProfile pubkey={widget.content} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="mb-3 mt-4 px-3 text-lg font-semibold text-neutral-900 dark:text-neutral-100">
|
||||
Reference in New Issue
Block a user