chore: update libraries

This commit is contained in:
Shusui MOYATANI
2023-12-21 00:49:11 +09:00
parent 0eb7a554b4
commit 4df42cea0a
19 changed files with 3861 additions and 2063 deletions

5576
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,51 +26,51 @@
},
"devDependencies": {
"@types/jsdom": "^21.1.6",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.51.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-no-relative-import-paths": "^1.5.2",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-no-relative-import-paths": "^1.5.3",
"eslint-plugin-solid": "^0.13.0",
"eslint-plugin-tailwindcss": "^3.13.0",
"husky": "^8.0.3",
"jsdom": "^23.0.0",
"jsdom": "^23.0.1",
"license-checker": "^25.0.1",
"lint-staged": "^14.0.1",
"postcss": "^8.4.31",
"prettier": "^3.0.3",
"typescript": "^5.2.2",
"lint-staged": "^15.2.0",
"postcss": "^8.4.32",
"prettier": "^3.1.1",
"typescript": "^5.3.3",
"vite": "^4.4.11",
"vite-plugin-solid": "^2.7.0",
"vite-plugin-solid-svg": "^0.6.4",
"vitest": "^0.34.6"
"vite-plugin-solid": "^2.8.0",
"vite-plugin-solid-svg": "^0.7.0",
"vitest": "^1.1.0"
},
"dependencies": {
"@solidjs/meta": "^0.28.6",
"@solidjs/router": "^0.8.3",
"@tailwindcss/forms": "^0.5.6",
"@tanstack/query-async-storage-persister": "^4.36.1",
"@tanstack/query-persist-client-core": "^4.36.1",
"@tanstack/solid-query": "^4.36.1",
"@tanstack/solid-virtual": "^3.0.0-beta.6",
"@textcomplete/core": "^0.1.12",
"@textcomplete/textarea": "^0.1.12",
"@thisbeyond/solid-dnd": "^0.7.4",
"@types/lodash": "^4.14.199",
"@solidjs/meta": "^0.29.3",
"@solidjs/router": "^0.10.5",
"@tailwindcss/forms": "^0.5.7",
"@tanstack/query-async-storage-persister": "^5.14.2",
"@tanstack/query-persist-client-core": "^5.14.2",
"@tanstack/solid-query": "^5.14.2",
"@tanstack/solid-virtual": "^3.0.1",
"@textcomplete/core": "^0.1.13",
"@textcomplete/textarea": "^0.1.13",
"@thisbeyond/solid-dnd": "^0.7.5",
"@types/lodash": "^4.14.202",
"emoji-mart": "^5.5.2",
"heroicons": "^2.0.18",
"i18next": "^23.5.1",
"i18next-browser-languagedetector": "^7.1.0",
"heroicons": "^2.1.1",
"i18next": "^23.7.11",
"i18next-browser-languagedetector": "^7.2.0",
"idb-keyval": "^6.2.1",
"lodash": "^4.17.21",
"nostr-tools": "^1.16.0",
"solid-js": "^1.7.12",
"tailwindcss": "^3.3.3",
"solid-js": "^1.8.7",
"tailwindcss": "^3.4.0",
"zod": "^3.22.4"
},
"lint-staged": {

View File

@@ -1,6 +1,6 @@
import { createEffect, onCleanup, lazy, type Component } from 'solid-js';
import { Routes, Route } from '@solidjs/router';
import { HashRouter, Route } from '@solidjs/router';
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister';
import { persistQueryClient } from '@tanstack/query-persist-client-core';
import { QueryClient, QueryClientProvider } from '@tanstack/solid-query';
@@ -50,12 +50,12 @@ const App: Component = () => {
return (
<I18NextProvider i18next={i18next}>
<QueryClientProvider client={queryClient}>
<Routes>
<Route path="/hello" element={<Hello />} />
<Route path="/" element={<Home />} />
<Route path="/:id" element={<Permalink />} />
<Route path="/*" element={<NotFound />} />
</Routes>
<HashRouter>
<Route path="/hello" component={() => <Hello />} />
<Route path="/" component={() => <Home />} />
<Route path="/:id" component={() => <Permalink />} />
<Route path="/*" component={() => <NotFound />} />
</HashRouter>
</QueryClientProvider>
</I18NextProvider>
);

View File

@@ -117,13 +117,13 @@ const ReactionAction = (props: { event: NostrEvent }) => {
'text-zinc-400': !isReactedByMe() || isReactedByMeWithEmoji(),
'hover:text-rose-400': !isReactedByMe() || isReactedByMeWithEmoji(),
'text-rose-400':
(isReactedByMe() && !isReactedByMeWithEmoji()) || publishReactionMutation.isLoading,
(isReactedByMe() && !isReactedByMeWithEmoji()) || publishReactionMutation.isPending,
}}
>
<button
class="h-4 w-4"
onClick={handleReaction}
disabled={publishReactionMutation.isLoading}
disabled={publishReactionMutation.isPending}
>
<Show when={isReactedByMe() && !isReactedByMeWithEmoji()} fallback={<HeartOutlined />}>
<HeartSolid />
@@ -140,7 +140,7 @@ const ReactionAction = (props: { event: NostrEvent }) => {
'text-zinc-400': !isReactedByMe() || !isReactedByMeWithEmoji(),
'hover:text-rose-400': !isReactedByMe() || !isReactedByMeWithEmoji(),
'text-rose-400':
(isReactedByMe() && isReactedByMeWithEmoji()) || publishReactionMutation.isLoading,
(isReactedByMe() && isReactedByMeWithEmoji()) || publishReactionMutation.isPending,
}}
>
<EmojiPicker onEmojiSelect={handleEmojiSelect}>
@@ -199,10 +199,10 @@ const RepostAction = (props: { event: NostrEvent }) => {
classList={{
'text-zinc-400': !isRepostedByMe(),
'hover:text-green-400': !isRepostedByMe(),
'text-green-400': isRepostedByMe() || publishRepostMutation.isLoading,
'text-green-400': isRepostedByMe() || publishRepostMutation.isPending,
}}
>
<button class="h-4 w-4" onClick={handleRepost} disabled={publishRepostMutation.isLoading}>
<button class="h-4 w-4" onClick={handleRepost} disabled={publishRepostMutation.isPending}>
<ArrowPathRoundedSquare />
</button>
<Show when={!config().hideCount && reposts().length > 0}>
@@ -327,7 +327,7 @@ const Actions: Component<ActionProps> = (props) => {
const closeModal = () => setModal(null);
const deleteMutation = createMutation({
const deleteMutation = createMutation(() => ({
mutationKey: ['deleteEvent', props.event.id],
mutationFn: (...params: Parameters<typeof commands.deleteEvent>) =>
commands
@@ -348,7 +348,7 @@ const Actions: Component<ActionProps> = (props) => {
onError: (err) => {
console.error('failed to delete', err);
},
});
}));
const menu: MenuItem[] = [
{

View File

@@ -122,8 +122,8 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
const replyTo = () => props.replyTo && textNote(props.replyTo);
const mode = () => props.mode ?? 'normal';
const publishTextNoteMutation = createMutation({
mutationKey: ['publishTextNote'],
const publishTextNoteMutation = createMutation(() => ({
mutationKey: ['publishTextNote'] as const,
mutationFn: commands.publishTextNote.bind(commands),
onSuccess: () => {
console.log('succeeded to post');
@@ -133,7 +133,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
onError: (err) => {
console.error('error', err);
},
});
}));
const resizeTextArea = () => {
if (textAreaRef == null) return;
@@ -141,8 +141,8 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
textAreaRef.style.height = `${textAreaRef.scrollHeight}px`;
};
const uploadFilesMutation = createMutation({
mutationKey: ['uploadFiles'],
const uploadFilesMutation = createMutation(() => ({
mutationKey: ['uploadFiles'] as const,
mutationFn: async (files: File[]) => {
const uploadResults = await uploadFiles(uploadNostrBuild)(files);
const failed: File[] = [];
@@ -161,7 +161,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
window.alert(i18n()('posting.failedToUploadFile', { filenames }));
}
},
});
}));
const taggedPubkeysWithoutMe = createMemo(() => {
const p = getPubkey();
@@ -197,7 +197,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
const submit = () => {
if (text().length === 0) return;
if (publishTextNoteMutation.isLoading) return;
if (publishTextNoteMutation.isPending) return;
if (/nsec1[0-9a-zA-Z]+/.test(text())) {
window.alert(i18n()('posting.forbiddenToIncludeNsec'));
@@ -290,7 +290,7 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
*/
const handleChangeFile: JSX.EventHandler<HTMLInputElement, Event> = (ev) => {
ev.preventDefault();
if (uploadFilesMutation.isLoading) return;
if (uploadFilesMutation.isPending) return;
// if (!ensureUploaderAgreement()) return;
const files = [...(ev.currentTarget.files ?? [])];
@@ -301,14 +301,14 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
const handleDrop: JSX.EventHandler<HTMLTextAreaElement, DragEvent> = (ev) => {
ev.preventDefault();
if (uploadFilesMutation.isLoading) return;
if (uploadFilesMutation.isPending) return;
// if (!ensureUploaderAgreement()) return;
const files = [...(ev?.dataTransfer?.files ?? [])];
uploadFilesMutation.mutate(files);
};
const handlePaste: JSX.EventHandler<HTMLTextAreaElement, ClipboardEvent> = (ev) => {
if (uploadFilesMutation.isLoading) return;
if (uploadFilesMutation.isPending) return;
const items = [...(ev?.clipboardData?.items ?? [])];
@@ -333,10 +333,10 @@ const NotePostForm: Component<NotePostFormProps> = (props) => {
const submitDisabled = () =>
text().trim().length === 0 ||
publishTextNoteMutation.isLoading ||
uploadFilesMutation.isLoading;
publishTextNoteMutation.isPending ||
uploadFilesMutation.isPending;
const fileUploadDisabled = () => uploadFilesMutation.isLoading;
const fileUploadDisabled = () => uploadFilesMutation.isPending;
onMount(() => {
setTimeout(() => {

View File

@@ -112,7 +112,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
return p != null && userFollowingPubkeys().includes(p);
};
const updateContactsMutation = createMutation({
const updateContactsMutation = createMutation(() => ({
mutationKey: ['updateContacts'],
mutationFn: (...params: Parameters<typeof commands.updateContacts>) =>
commands
@@ -139,7 +139,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
.then(() => myFollowingQuery.refetch())
.catch((err) => console.error('failed to refetch contacts', err));
},
});
}));
const updateContacts = async (op: 'follow' | 'unfollow', pubkey: string) => {
try {
@@ -312,12 +312,12 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
{i18n()('profile.editProfile')}
</button>
</Match>
<Match when={updateContactsMutation.isLoading || updatingContacts()}>
<Match when={updateContactsMutation.isPending || updatingContacts()}>
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
{i18n()('general.updating')}
</span>
</Match>
<Match when={myFollowingQuery.isLoading || myFollowingQuery.isFetching}>
<Match when={myFollowingQuery.isPending || myFollowingQuery.isFetching}>
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
{i18n()('general.loading')}
</span>
@@ -329,7 +329,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
onMouseEnter={() => setHoverFollowButton(true)}
onMouseLeave={() => setHoverFollowButton(false)}
onClick={() => unfollow()}
disabled={updateContactsMutation.isLoading}
disabled={updateContactsMutation.isPending}
>
<Show when={!hoverFollowButton()} fallback={i18n()('profile.unfollow')}>
{i18n()('profile.followingCurrently')}
@@ -341,7 +341,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
class="w-28 rounded-full border border-primary px-4 py-2 text-primary
hover:border-rose-400 hover:text-rose-400"
onClick={() => follow()}
disabled={updateContactsMutation.isLoading}
disabled={updateContactsMutation.isPending}
>
{i18n()('profile.follow')}
</button>
@@ -357,7 +357,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
</ContextMenu>
</div>
<Switch>
<Match when={userFollowingQuery.isLoading}>
<Match when={userFollowingQuery.isPending}>
<div class="shrink-0 text-xs">{i18n()('general.loading')}</div>
</Match>
<Match when={followed()}>
@@ -369,7 +369,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
</div>
<div class="flex items-start px-4 pt-2">
<div class="h-16 shrink overflow-hidden">
<Show when={profileQuery.isLoading}>{i18n()('general.loading')}</Show>
<Show when={profileQuery.isPending}>{i18n()('general.loading')}</Show>
<Show when={(profile()?.display_name?.length ?? 0) > 0}>
<div class="truncate text-xl font-bold">{profile()?.display_name}</div>
</Show>
@@ -387,7 +387,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
</span>
}
>
<Match when={verificationQuery.isLoading}>
<Match when={verificationQuery.isPending}>
<span class="inline-block h-3 w-3">
<ArrowPath />
</span>

View File

@@ -50,7 +50,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
);
const { updateProfile } = useCommands();
const mutation = createMutation({
const mutation = createMutation(() => ({
mutationKey: ['updateProfile'],
mutationFn: (...params: Parameters<typeof updateProfile>) =>
updateProfile(...params).then((promeses) => Promise.allSettled(promeses.map(timeout(10000)))),
@@ -73,12 +73,12 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
onError: (err) => {
console.error('failed to delete', err);
},
});
}));
const loading = () => query.isLoading || mutation.isLoading;
const loading = () => query.isPending || mutation.isPending;
const disabled = () => loading();
setInterval(() => console.log(query.isLoading, mutation.isLoading), 1000);
setInterval(() => console.log(query.isPending, mutation.isPending), 1000);
const otherProperties = () =>
omit(profile(), [
@@ -313,7 +313,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
<button
type="submit"
class="rounded bg-rose-300 p-2 font-bold text-white hover:bg-rose-400"
disabled={mutation.isLoading}
disabled={mutation.isPending}
>
{i18n()('profile.edit.save')}
</button>
@@ -325,7 +325,7 @@ const ProfileEdit: Component<ProfileEditProps> = (props) => {
{i18n()('profile.edit.cancel')}
</button>
</div>
<Show when={mutation.isLoading}>{i18n()('profile.edit.updating')}</Show>
<Show when={mutation.isPending}>{i18n()('profile.edit.updating')}</Show>
</form>
</div>
</BasicModal>

View File

@@ -1,15 +1,7 @@
/* @refresh reload */
import { Router, hashIntegration } from '@solidjs/router';
import { render } from 'solid-js/web';
import '@/index.css';
import App from '@/App';
render(
() => (
<Router source={hashIntegration()}>
<App />
</Router>
),
document.getElementById('root') as HTMLElement,
);
render(() => <App />, document.getElementById('root') as HTMLElement);

View File

@@ -16,7 +16,7 @@ const useReactionMutation = (propsProvider: () => UseReactionMutationProps) => {
const commands = useCommands();
const mutation = createMutation({
const mutation = createMutation(() => ({
mutationKey: ['useReactionMutation', props().eventId] as const,
mutationFn: (...params: Parameters<typeof commands.publishReaction>) =>
commands
@@ -43,7 +43,7 @@ const useReactionMutation = (propsProvider: () => UseReactionMutationProps) => {
.then(() => queryClient.invalidateQueries({ queryKey }))
.catch((err) => console.error('failed to refetch reactions', err));
},
});
}));
return mutation;
};

View File

@@ -16,7 +16,7 @@ const useRepostMutation = (propsProvider: () => UseRepostMutationProps) => {
const commands = useCommands();
const mutation = createMutation({
const mutation = createMutation(() => ({
mutationKey: ['useRepostMutation', props().eventId] as const,
mutationFn: (...params: Parameters<typeof commands.publishRepost>) =>
commands
@@ -43,7 +43,7 @@ const useRepostMutation = (propsProvider: () => UseRepostMutationProps) => {
.then(() => queryClient.invalidateQueries({ queryKey }))
.catch((err) => console.error('failed to refetch repost', err));
},
});
}));
return mutation;
};

View File

@@ -15,7 +15,6 @@ export const latestEventQuery =
queryClient: QueryClient;
}) =>
({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise<NostrEvent | null> => {
const prev = queryClient.getQueryData(queryKey, { stale: true }) as NostrEvent;
const task = taskProvider(queryKey);
if (task == null) return Promise.resolve(null);
const promise = task.firstEventPromise().catch(() => {
@@ -23,9 +22,12 @@ export const latestEventQuery =
});
task.onUpdate((events) => {
const latest = pickLatestEvent(events);
if (prev == null || (latest != null && compareEvents(latest, prev) >= 0)) {
queryClient.setQueryData(queryKey, latest);
queryClient.setQueriesData<NostrEvent>({ queryKey, stale: true }, (prev) => {
if (latest != null && (prev == null || compareEvents(latest, prev) >= 0)) {
return latest;
}
return undefined;
});
});
registerTask({ task, signal });
return timeout(15000, `${JSON.stringify(queryKey)}`)(promise);
@@ -40,13 +42,12 @@ export const eventsQuery =
queryClient: QueryClient;
}) =>
({ queryKey, signal }: { queryKey: K; signal?: AbortSignal }): Promise<NostrEvent[]> => {
const prev = queryClient.getQueryData(queryKey, { stale: true }) as NostrEvent[];
const task = taskProvider(queryKey);
if (task == null) return Promise.resolve([]);
const promise = task.toUpdatePromise().catch(() => []);
task.onUpdate((events) => {
// TODO consider kind:5 deletion
queryClient.setQueryData(queryKey, () => {
queryClient.setQueriesData<NostrEvent[]>({ queryKey, stale: true }, (prev) => {
if (prev == null) return events;
const deduped = uniqBy([...prev, ...events], (e) => e.id);
return sortEvents(deduped);

View File

@@ -18,9 +18,9 @@ export type UseEvent = {
const useEvent = (propsProvider: () => UseEventProps | null): UseEvent => {
const props = createMemo(propsProvider);
const query = createQuery(
() => ['useEvent', props()] as const,
({ queryKey, signal }) => {
const query = createQuery(() => ({
queryKey: ['useEvent', props()] as const,
queryFn: ({ queryKey, signal }) => {
const [, currentProps] = queryKey;
if (currentProps == null) return null;
const { eventId } = currentProps;
@@ -31,15 +31,13 @@ const useEvent = (propsProvider: () => UseEventProps | null): UseEvent => {
registerTask({ task, signal });
return timeout(15000, `useEvent: ${eventId}`)(promise);
},
{
// Text notes never change, so they can be stored for a long time.
// However, events tend to be unreferenced as time passes.
staleTime: 4 * 60 * 60 * 1000, // 4 hour
cacheTime: 4 * 60 * 60 * 1000, // 4 hour
refetchOnWindowFocus: false,
refetchOnMount: false,
},
);
}));
const event = () => query.data ?? null;

View File

@@ -68,9 +68,9 @@ const useFollowings = (propsProvider: () => UseFollowingsProps | null): UseFollo
const props = createMemo(propsProvider);
const genQueryKey = () => ['useFollowings', props()] as const;
const query = createQuery(
genQueryKey,
latestEventQuery({
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: latestEventQuery<ReturnType<typeof genQueryKey>>({
taskProvider: ([, currentProps]) => {
if (currentProps == null) return null;
const { pubkey } = currentProps;
@@ -78,17 +78,16 @@ const useFollowings = (propsProvider: () => UseFollowingsProps | null): UseFollo
},
queryClient,
}),
{
staleTime: 5 * 60 * 1000, // 5 min
cacheTime: 3 * 24 * 60 * 60 * 1000, // 3 days
refetchOnMount: true,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchInterval: 0,
},
);
}));
const invalidateFollowings = (): Promise<void> => queryClient.invalidateQueries(genQueryKey());
const invalidateFollowings = (): Promise<void> =>
queryClient.invalidateQueries({ queryKey: genQueryKey() });
return { ...buildMethods(() => query.data), invalidateFollowings, query };
};

View File

@@ -30,9 +30,9 @@ const useParameterizedReplaceableEvent = (
const props = createMemo(propsProvider);
const genQueryKey = () => ['useFollowings', props()] as const;
const query = createQuery(
genQueryKey,
({ queryKey, signal }) => {
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: ({ queryKey, signal }) => {
console.debug('useFollowings');
const [, currentProps] = queryKey;
if (currentProps == null) return Promise.resolve(null);
@@ -59,11 +59,9 @@ const useParameterizedReplaceableEvent = (
`useParameterizedReplaceableEvent: ${kind}:${author}:${identifier}`,
)(promise);
},
{
staleTime: 5 * 60 * 1000, // 5 min
cacheTime: 4 * 60 * 60 * 1000, // 4 hour
},
);
}));
const event = () => query.data ?? null;

View File

@@ -27,16 +27,14 @@ export type UseProfiles = {
queries: CreateQueryResult<NostrEvent | null>[];
};
type UseProfileQueryKey = readonly ['useProfile', UseProfileProps | null];
const useProfile = (propsProvider: () => UseProfileProps | null): UseProfile => {
const queryClient = useQueryClient();
const props = createMemo(propsProvider);
const genQueryKey = createMemo((): UseProfileQueryKey => ['useProfile', props()] as const);
const genQueryKey = createMemo(() => ['useProfile', props()] as const);
const query = createQuery(
genQueryKey,
latestEventQuery({
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: latestEventQuery<ReturnType<typeof genQueryKey>>({
taskProvider: ([, currentProps]) => {
if (currentProps == null) return null;
const { pubkey } = currentProps;
@@ -44,15 +42,13 @@ const useProfile = (propsProvider: () => UseProfileProps | null): UseProfile =>
},
queryClient,
}),
{
// Profiles are updated occasionally, so a short staleTime is used here.
// cacheTime is long so that the user see profiles instantly.
staleTime: 5 * 60 * 1000, // 5 min
cacheTime: 3 * 24 * 60 * 60 * 1000, // 3 days
refetchInterval: 5 * 60 * 1000, // 5 min
refetchOnWindowFocus: false,
},
);
}));
const event = () => query.data;
@@ -62,7 +58,8 @@ const useProfile = (propsProvider: () => UseProfileProps | null): UseProfile =>
return safeParseProfile(content);
});
const invalidateProfile = (): Promise<void> => queryClient.invalidateQueries(genQueryKey());
const invalidateProfile = (): Promise<void> =>
queryClient.invalidateQueries({ queryKey: genQueryKey() });
return { profile, event, invalidateProfile, query };
};

View File

@@ -30,9 +30,9 @@ const useReactions = (propsProvider: () => UseReactionsProps | null): UseReactio
const queryClient = useQueryClient();
const genQueryKey = createMemo(() => queryKeyUseReactions(propsProvider()));
const query = createQuery(
genQueryKey,
eventsQuery({
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: eventsQuery<ReturnType<typeof queryKeyUseReactions>>({
taskProvider: ([, currentProps]) => {
if (currentProps == null) return null;
const { eventId: mentionedEventId } = currentProps;
@@ -40,12 +40,10 @@ const useReactions = (propsProvider: () => UseReactionsProps | null): UseReactio
},
queryClient,
}),
{
staleTime: 1 * 60 * 1000, // 1 min
cacheTime: 4 * 60 * 60 * 1000, // 4 hour
refetchInterval: 1 * 60 * 1000, // 1 min
},
);
}));
const reactions = () => {
const data = query.data ?? [];

View File

@@ -25,9 +25,9 @@ const useReposts = (propsProvider: () => UseRepostsProps): UseReposts => {
const props = createMemo(propsProvider);
const genQueryKey = createMemo(() => queryKeyUseReposts(props()));
const query = createQuery(
genQueryKey,
eventsQuery({
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: eventsQuery<ReturnType<typeof genQueryKey>>({
taskProvider: ([, currentProps]) => {
if (currentProps == null) return null;
const { eventId: mentionedEventId } = currentProps;
@@ -35,12 +35,10 @@ const useReposts = (propsProvider: () => UseRepostsProps): UseReposts => {
},
queryClient,
}),
{
staleTime: 1 * 60 * 1000, // 1 min
cacheTime: 4 * 60 * 60 * 1000, // 4 hour
refetchInterval: 1 * 60 * 1000, // 1 min
},
);
}));
const reposts = () => {
const data = query.data ?? [];

View File

@@ -14,19 +14,19 @@ export type UseVerification = {
const useVerification = (propsProvider: () => UseVerificationProps | null): UseVerification => {
const props = createMemo(propsProvider);
const query = createQuery(
() => ['useVerification', props()] as const,
({ queryKey }) => {
const genQueryKey = () => ['useVerification', props()] as const;
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: ({ queryKey }) => {
const [, currentProps] = queryKey;
if (currentProps == null) return Promise.resolve(null);
const { nip05: nip05string } = currentProps;
return nip05.queryProfile(nip05string);
},
{
staleTime: 30 * 60 * 1000, // 30 min
cacheTime: 24 * 60 * 60 * 1000, // 24 hour
},
);
}));
const verification = () => query?.data ?? null;

View File

@@ -56,12 +56,15 @@ export type UseOgpProps = {
export const useOgp = (propsProvider: () => UseOgpProps) => {
const genQueryKey = () => ['useOgp', propsProvider().url] as const;
const query = createQuery(genQueryKey, ({ queryKey: [, url] }) => fetchOgpContent(url), {
const query = createQuery(() => ({
queryKey: genQueryKey(),
queryFn: ({ queryKey: [, url] }) => fetchOgpContent(url),
staleTime: 4 * 60 * 60 * 1000, // 4 hour
cacheTime: 4 * 60 * 60 * 1000, // 4 hour
refetchOnWindowFocus: false,
refetchOnMount: false,
});
}));
const ogp = () => query.data;