mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-19 11:43:30 +00:00
update widgets
This commit is contained in:
parent
6b030f2902
commit
108ecafab7
@ -6,37 +6,9 @@ import { useStorage } from '@libs/storage/provider';
|
|||||||
|
|
||||||
import { ArrowLeftIcon, CheckCircleIcon, LoaderIcon } from '@shared/icons';
|
import { ArrowLeftIcon, CheckCircleIcon, LoaderIcon } from '@shared/icons';
|
||||||
|
|
||||||
import { WidgetKinds } from '@stores/constants';
|
import { HASHTAGS, WidgetKinds } from '@stores/constants';
|
||||||
import { useOnboarding } from '@stores/onboarding';
|
import { useOnboarding } from '@stores/onboarding';
|
||||||
|
|
||||||
const data = [
|
|
||||||
{ hashtag: '#bitcoin' },
|
|
||||||
{ hashtag: '#nostr' },
|
|
||||||
{ hashtag: '#nostrdesign' },
|
|
||||||
{ hashtag: '#security' },
|
|
||||||
{ hashtag: '#zap' },
|
|
||||||
{ hashtag: '#LFG' },
|
|
||||||
{ hashtag: '#zapchain' },
|
|
||||||
{ hashtag: '#shitcoin' },
|
|
||||||
{ hashtag: '#plebchain' },
|
|
||||||
{ hashtag: '#nodes' },
|
|
||||||
{ hashtag: '#hodl' },
|
|
||||||
{ hashtag: '#stacksats' },
|
|
||||||
{ hashtag: '#nokyc' },
|
|
||||||
{ hashtag: '#meme' },
|
|
||||||
{ hashtag: '#memes' },
|
|
||||||
{ hashtag: '#memestr' },
|
|
||||||
{ hashtag: '#nostriches' },
|
|
||||||
{ hashtag: '#dev' },
|
|
||||||
{ hashtag: '#anime' },
|
|
||||||
{ hashtag: '#waifu' },
|
|
||||||
{ hashtag: '#manga' },
|
|
||||||
{ hashtag: '#lume' },
|
|
||||||
{ hashtag: '#snort' },
|
|
||||||
{ hashtag: '#damus' },
|
|
||||||
{ hashtag: '#primal' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export function OnboardHashtagScreen() {
|
export function OnboardHashtagScreen() {
|
||||||
const { db } = useStorage();
|
const { db } = useStorage();
|
||||||
|
|
||||||
@ -93,7 +65,7 @@ export function OnboardHashtagScreen() {
|
|||||||
</h1>
|
</h1>
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<div className="flex h-[420px] w-full flex-col overflow-y-auto rounded-xl bg-neutral-100 dark:bg-neutral-900">
|
<div className="flex h-[420px] w-full flex-col overflow-y-auto rounded-xl bg-neutral-100 dark:bg-neutral-900">
|
||||||
{data.map((item: { hashtag: string }) => (
|
{HASHTAGS.map((item: { hashtag: string }) => (
|
||||||
<button
|
<button
|
||||||
key={item.hashtag}
|
key={item.hashtag}
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -190,7 +190,7 @@ export const User = memo(function User({
|
|||||||
if (status === 'pending') {
|
if (status === 'pending') {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<div className="h-11 w-11 shrink-0 animate-pulse rounded-lg bg-neutral-300 dark:bg-neutral-700" />
|
<div className="h-10 w-10 shrink-0 animate-pulse rounded-lg bg-neutral-300 dark:bg-neutral-700" />
|
||||||
<div className="flex w-full flex-col items-start gap-1">
|
<div className="flex w-full flex-col items-start gap-1">
|
||||||
<div className="h-4 w-36 animate-pulse rounded bg-neutral-300 dark:bg-neutral-700" />
|
<div className="h-4 w-36 animate-pulse rounded bg-neutral-300 dark:bg-neutral-700" />
|
||||||
<div className="h-4 w-24 animate-pulse rounded bg-neutral-300 dark:bg-neutral-700" />
|
<div className="h-4 w-24 animate-pulse rounded bg-neutral-300 dark:bg-neutral-700" />
|
||||||
@ -201,19 +201,19 @@ export const User = memo(function User({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<Avatar.Root className="shrink-0">
|
<Avatar.Root className="h-10 w-10 shrink-0">
|
||||||
<Avatar.Image
|
<Avatar.Image
|
||||||
src={user?.picture || user?.image}
|
src={user?.picture || user?.image}
|
||||||
alt={pubkey}
|
alt={pubkey}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
className="h-11 w-11 rounded-lg"
|
className="h-10 w-10 rounded-lg object-cover"
|
||||||
/>
|
/>
|
||||||
<Avatar.Fallback delayMs={300}>
|
<Avatar.Fallback delayMs={300}>
|
||||||
<img
|
<img
|
||||||
src={svgURI}
|
src={svgURI}
|
||||||
alt={pubkey}
|
alt={pubkey}
|
||||||
className="h-11 w-11 rounded-lg bg-black dark:bg-white"
|
className="h-10 w-10 rounded-lg bg-black dark:bg-white"
|
||||||
/>
|
/>
|
||||||
</Avatar.Fallback>
|
</Avatar.Fallback>
|
||||||
</Avatar.Root>
|
</Avatar.Root>
|
||||||
|
@ -34,7 +34,7 @@ export function TrendingNotesWidget({ params }: { params: Widget }) {
|
|||||||
return (
|
return (
|
||||||
<WidgetWrapper>
|
<WidgetWrapper>
|
||||||
<TitleBar id={params.id} title="Trending Notes" />
|
<TitleBar id={params.id} title="Trending Notes" />
|
||||||
<div className="flex-1">
|
<VList className="flex-1">
|
||||||
{status === 'pending' ? (
|
{status === 'pending' ? (
|
||||||
<div className="flex h-full w-full items-center justify-center ">
|
<div className="flex h-full w-full items-center justify-center ">
|
||||||
<div className="inline-flex flex-col items-center justify-center gap-2">
|
<div className="inline-flex flex-col items-center justify-center gap-2">
|
||||||
@ -56,14 +56,9 @@ export function TrendingNotesWidget({ params }: { params: Widget }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<VList className="h-full">
|
data.map((item) => <MemoizedTextNote key={item.event.id} event={item.event} />)
|
||||||
{data.map((item) => (
|
|
||||||
<MemoizedTextNote key={item.event.id} event={item.event} />
|
|
||||||
))}
|
|
||||||
<div className="h-16" />
|
|
||||||
</VList>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</VList>
|
||||||
</WidgetWrapper>
|
</WidgetWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,9 @@ import { useState } from 'react';
|
|||||||
|
|
||||||
import { useStorage } from '@libs/storage/provider';
|
import { useStorage } from '@libs/storage/provider';
|
||||||
|
|
||||||
import { ArrowRightCircleIcon, CheckCircleIcon } from '@shared/icons';
|
import { ArrowRightCircleIcon, CancelIcon, CheckCircleIcon } from '@shared/icons';
|
||||||
import { User } from '@shared/user';
|
import { User } from '@shared/user';
|
||||||
|
import { WidgetWrapper } from '@shared/widgets';
|
||||||
|
|
||||||
import { WidgetKinds } from '@stores/constants';
|
import { WidgetKinds } from '@stores/constants';
|
||||||
|
|
||||||
@ -25,10 +26,6 @@ export function XfeedsWidget({ params }: { params: Widget }) {
|
|||||||
setGroups(arr);
|
setGroups(arr);
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancel = () => {
|
|
||||||
removeWidget.mutate(params.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
addWidget.mutate({
|
addWidget.mutate({
|
||||||
kind: WidgetKinds.local.feeds,
|
kind: WidgetKinds.local.feeds,
|
||||||
@ -40,58 +37,60 @@ export function XfeedsWidget({ params }: { params: Widget }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full shrink-0 grow-0 basis-[400px] flex-col items-center justify-center">
|
<WidgetWrapper>
|
||||||
<div className="w-full px-5">
|
<div className="flex h-11 shrink-0 items-center justify-between px-3">
|
||||||
<h3 className="mb-4 text-center font-semibold text-neutral-900 dark:text-neutral-100">
|
<div className="w-6 shrink-0" />
|
||||||
Choose account you want to add to group feeds
|
<h3 className="text-center font-semibold text-neutral-900 dark:text-neutral-100">
|
||||||
|
Adding group feeds
|
||||||
</h3>
|
</h3>
|
||||||
<div className="mb-0 flex flex-col gap-2">
|
<button
|
||||||
<div>
|
type="button"
|
||||||
|
onClick={() => removeWidget.mutate(params.id)}
|
||||||
|
className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded text-neutral-900 backdrop-blur-xl hover:bg-neutral-100 dark:text-neutral-100 dark:hover:bg-neutral-900"
|
||||||
|
>
|
||||||
|
<CancelIcon className="h-3 w-3" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-1 flex-col justify-between">
|
||||||
|
<div className="flex min-h-0 flex-1 flex-col gap-2 px-3 pb-3">
|
||||||
<input
|
<input
|
||||||
value={title}
|
value={title}
|
||||||
onChange={(e) => setTitle(e.target.value)}
|
onChange={(e) => setTitle(e.target.value)}
|
||||||
placeholder="Title"
|
placeholder="Group name"
|
||||||
className="relative h-11 w-full rounded-lg bg-neutral-200 px-3 py-1 text-neutral-900 !outline-none placeholder:text-neutral-500 dark:bg-neutral-800 dark:text-neutral-100 dark:placeholder:text-neutral-300"
|
className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100 dark:placeholder:text-neutral-300"
|
||||||
/>
|
/>
|
||||||
|
<div className="flex-grow-1 flex flex-1 shrink basis-0 flex-col overflow-y-auto rounded-xl bg-neutral-50 dark:bg-neutral-950">
|
||||||
|
<div className="flex h-10 shrink-0 items-center border-b border-neutral-100 px-4 text-sm font-semibold dark:border-neutral-900">
|
||||||
|
Add users {title ? 'to ' + title : ''}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex h-[500px] w-full flex-col overflow-y-auto rounded-lg bg-neutral-200 py-2 scrollbar-none dark:bg-neutral-800">
|
|
||||||
{db.account.circles.map((item: string) => (
|
{db.account.circles.map((item: string) => (
|
||||||
<button
|
<button
|
||||||
key={item}
|
key={item}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => toggleGroup(item)}
|
onClick={() => toggleGroup(item)}
|
||||||
className="inline-flex transform items-center justify-between px-4 py-2 hover:bg-neutral-300 dark:hover:bg-neutral-700"
|
className="inline-flex transform items-center justify-between px-4 py-2 hover:bg-neutral-100 dark:hover:bg-neutral-900"
|
||||||
>
|
>
|
||||||
<User pubkey={item} variant="simple" />
|
<User pubkey={item} variant="simple" />
|
||||||
{groups.includes(item) && (
|
{groups.includes(item) ? (
|
||||||
<div>
|
<CheckCircleIcon className="h-5 w-5 text-teal-500" />
|
||||||
<CheckCircleIcon className="h-4 w-4 text-green-400" />
|
) : null}
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center justify-center gap-2">
|
</div>
|
||||||
|
<div className="flex h-14 shrink-0 gap-2 border-t border-neutral-100 px-3 pt-2.5 dark:border-neutral-900">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={groups.length < 1}
|
disabled={groups.length < 1}
|
||||||
onClick={submit}
|
onClick={submit}
|
||||||
className="inline-flex h-11 w-full items-center justify-between gap-2 rounded-lg bg-blue-500 px-6 font-medium leading-none text-white hover:bg-blue-600 focus:outline-none disabled:opacity-50"
|
className="inline-flex h-9 w-full items-center justify-between gap-2 rounded-lg bg-blue-500 px-6 font-medium text-white hover:bg-blue-600 focus:outline-none disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<span className="w-5" />
|
<span className="w-5" />
|
||||||
<span>Add {groups.length} account to group feed</span>
|
<span>Add {groups.length} user to group feed</span>
|
||||||
<ArrowRightCircleIcon className="h-5 w-5" />
|
<ArrowRightCircleIcon className="h-5 w-5" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={cancel}
|
|
||||||
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg px-6 font-medium leading-none text-neutral-900 hover:bg-neutral-200 focus:outline-none disabled:opacity-50 dark:text-neutral-100 dark:hover:bg-neutral-800"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</WidgetWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Resolver, useForm } from 'react-hook-form';
|
import { Resolver, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
import { ArrowRightCircleIcon } from '@shared/icons';
|
import { ArrowRightCircleIcon, CancelIcon } from '@shared/icons';
|
||||||
|
import { WidgetWrapper } from '@shared/widgets';
|
||||||
|
|
||||||
import { WidgetKinds } from '@stores/constants';
|
import { HASHTAGS, WidgetKinds } from '@stores/constants';
|
||||||
|
|
||||||
import { useWidget } from '@utils/hooks/useWidget';
|
import { useWidget } from '@utils/hooks/useWidget';
|
||||||
import { Widget } from '@utils/types';
|
import { Widget } from '@utils/types';
|
||||||
@ -29,15 +30,12 @@ export function XhashtagWidget({ params }: { params: Widget }) {
|
|||||||
const { addWidget, removeWidget } = useWidget();
|
const { addWidget, removeWidget } = useWidget();
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
|
setValue,
|
||||||
setError,
|
setError,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
formState: { errors, isDirty, isValid },
|
formState: { errors, isDirty, isValid },
|
||||||
} = useForm<FormValues>({ resolver });
|
} = useForm<FormValues>({ resolver });
|
||||||
|
|
||||||
const cancel = () => {
|
|
||||||
removeWidget.mutate(params.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async (data: FormValues) => {
|
const onSubmit = async (data: FormValues) => {
|
||||||
try {
|
try {
|
||||||
addWidget.mutate({
|
addWidget.mutate({
|
||||||
@ -56,42 +54,57 @@ export function XhashtagWidget({ params }: { params: Widget }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full shrink-0 grow-0 basis-[400px] flex-col items-center justify-center">
|
<WidgetWrapper>
|
||||||
<div className="w-full px-5">
|
<div className="flex h-11 shrink-0 items-center justify-between px-3">
|
||||||
<h3 className="mb-4 text-center text-lg font-semibold">
|
<div className="w-6 shrink-0" />
|
||||||
Enter hashtag you want to follow
|
<h3 className="text-center font-semibold text-neutral-900 dark:text-neutral-100">
|
||||||
|
Adding hashtag feeds
|
||||||
</h3>
|
</h3>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => removeWidget.mutate(params.id)}
|
||||||
|
className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded text-neutral-900 backdrop-blur-xl hover:bg-neutral-100 dark:text-neutral-100 dark:hover:bg-neutral-900"
|
||||||
|
>
|
||||||
|
<CancelIcon className="h-3 w-3" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-1 flex-col px-3">
|
||||||
<form onSubmit={handleSubmit(onSubmit)} className="mb-0 flex flex-col gap-2">
|
<form onSubmit={handleSubmit(onSubmit)} className="mb-0 flex flex-col gap-2">
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<input
|
<input
|
||||||
{...register('hashtag', { required: true, minLength: 1 })}
|
{...register('hashtag', { required: true, minLength: 1 })}
|
||||||
placeholder="#bitcoin"
|
placeholder="Enter a hashtag"
|
||||||
className="relative h-12 w-full rounded-lg bg-neutral-200 px-3 py-1 text-neutral-900 !outline-none placeholder:text-neutral-500 dark:bg-neutral-800 dark:text-neutral-100 dark:placeholder:text-neutral-300"
|
className="relative h-11 w-full rounded-lg bg-neutral-100 px-3 py-1 text-neutral-900 !outline-none placeholder:text-neutral-500 dark:bg-neutral-900 dark:text-neutral-100 dark:placeholder:text-neutral-300"
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-red-400">
|
<span className="text-sm text-red-400">
|
||||||
{errors.hashtag && <p>{errors.hashtag.message}</p>}
|
{errors.hashtag && <p>{errors.hashtag.message}</p>}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-center justify-center gap-2">
|
<div className="flex flex-wrap items-center justify-start gap-2">
|
||||||
|
{HASHTAGS.map((item) => (
|
||||||
|
<button
|
||||||
|
key={item.hashtag}
|
||||||
|
type="button"
|
||||||
|
onClick={() => setValue('hashtag', item.hashtag)}
|
||||||
|
className="inline-flex h-6 w-min items-center justify-center rounded-md bg-neutral-100 px-2 text-sm hover:bg-neutral-200 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||||
|
>
|
||||||
|
{item.hashtag}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 flex flex-col items-center justify-center gap-2">
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!isDirty || !isValid}
|
disabled={!isDirty || !isValid}
|
||||||
className="inline-flex h-11 w-full items-center justify-between gap-2 rounded-lg bg-blue-500 px-6 font-medium text-white hover:bg-blue-600 focus:outline-none disabled:opacity-50"
|
className="inline-flex h-9 w-full items-center justify-between gap-2 rounded-lg bg-blue-500 px-6 font-medium text-white hover:bg-blue-600 focus:outline-none disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<span className="w-5" />
|
<span className="w-5" />
|
||||||
<span>Create</span>
|
<span>Add</span>
|
||||||
<ArrowRightCircleIcon className="h-5 w-5" />
|
<ArrowRightCircleIcon className="h-5 w-5" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={cancel}
|
|
||||||
className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-lg px-6 font-medium leading-none text-neutral-900 hover:bg-neutral-200 focus:outline-none disabled:opacity-50 dark:text-neutral-100 dark:hover:bg-neutral-800"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</WidgetWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,37 @@ export const FULL_RELAYS = [
|
|||||||
|
|
||||||
export const FETCH_LIMIT = 20;
|
export const FETCH_LIMIT = 20;
|
||||||
|
|
||||||
|
export const HASHTAGS = [
|
||||||
|
{ hashtag: '#food' },
|
||||||
|
{ hashtag: '#gaming' },
|
||||||
|
{ hashtag: '#nsfw' },
|
||||||
|
{ hashtag: '#bitcoin' },
|
||||||
|
{ hashtag: '#nostr' },
|
||||||
|
{ hashtag: '#nostrdesign' },
|
||||||
|
{ hashtag: '#security' },
|
||||||
|
{ hashtag: '#zap' },
|
||||||
|
{ hashtag: '#LFG' },
|
||||||
|
{ hashtag: '#zapchain' },
|
||||||
|
{ hashtag: '#shitcoin' },
|
||||||
|
{ hashtag: '#plebchain' },
|
||||||
|
{ hashtag: '#nodes' },
|
||||||
|
{ hashtag: '#hodl' },
|
||||||
|
{ hashtag: '#stacksats' },
|
||||||
|
{ hashtag: '#nokyc' },
|
||||||
|
{ hashtag: '#meme' },
|
||||||
|
{ hashtag: '#memes' },
|
||||||
|
{ hashtag: '#memestr' },
|
||||||
|
{ hashtag: '#nostriches' },
|
||||||
|
{ hashtag: '#dev' },
|
||||||
|
{ hashtag: '#anime' },
|
||||||
|
{ hashtag: '#waifu' },
|
||||||
|
{ hashtag: '#manga' },
|
||||||
|
{ hashtag: '#lume' },
|
||||||
|
{ hashtag: '#snort' },
|
||||||
|
{ hashtag: '#damus' },
|
||||||
|
{ hashtag: '#primal' },
|
||||||
|
];
|
||||||
|
|
||||||
export const WidgetKinds = {
|
export const WidgetKinds = {
|
||||||
local: {
|
local: {
|
||||||
network: 100,
|
network: 100,
|
||||||
|
@ -19,9 +19,24 @@ export function useWidget() {
|
|||||||
|
|
||||||
const removeWidget = useMutation({
|
const removeWidget = useMutation({
|
||||||
mutationFn: async (id: string) => {
|
mutationFn: async (id: string) => {
|
||||||
return await db.removeWidget(id);
|
// Cancel any outgoing refetches
|
||||||
|
await queryClient.cancelQueries({ queryKey: ['widgets'] });
|
||||||
|
|
||||||
|
// Snapshot the previous value
|
||||||
|
const prevWidgets = queryClient.getQueryData(['widgets']);
|
||||||
|
|
||||||
|
// Optimistically update to the new value
|
||||||
|
queryClient.setQueryData(['widgets'], (prev: Widget[]) =>
|
||||||
|
prev.filter((t) => t.id !== id)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update in database
|
||||||
|
await db.removeWidget(id);
|
||||||
|
|
||||||
|
// Return a context object with the snapshotted value
|
||||||
|
return { prevWidgets };
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['widgets'] });
|
queryClient.invalidateQueries({ queryKey: ['widgets'] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user