fix: lost contacts

This commit is contained in:
Shusui MOYATANI
2023-06-18 01:10:25 +09:00
parent 6ba622328b
commit c97dcc94e3
3 changed files with 46 additions and 51 deletions

View File

@@ -24,6 +24,7 @@ import useVerification from '@/nostr/useVerification';
import ensureNonNull from '@/utils/ensureNonNull'; import ensureNonNull from '@/utils/ensureNonNull';
import epoch from '@/utils/epoch'; import epoch from '@/utils/epoch';
import npubEncodeFallback from '@/utils/npubEncodeFallback'; import npubEncodeFallback from '@/utils/npubEncodeFallback';
import sleep from '@/utils/sleep';
import timeout from '@/utils/timeout'; import timeout from '@/utils/timeout';
export type ProfileDisplayProps = { export type ProfileDisplayProps = {
@@ -47,6 +48,7 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
const npub = createMemo(() => npubEncodeFallback(props.pubkey)); const npub = createMemo(() => npubEncodeFallback(props.pubkey));
const [updatingContacts, setUpdatingContacts] = createSignal(false);
const [hoverFollowButton, setHoverFollowButton] = createSignal(false); const [hoverFollowButton, setHoverFollowButton] = createSignal(false);
const [showFollowers, setShowFollowers] = createSignal(false); const [showFollowers, setShowFollowers] = createSignal(false);
@@ -117,48 +119,42 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
}, },
}); });
const handlePromise = const updateContacts = async (update: (current: string[]) => string[]) => {
<Params extends any[], T>(f: (...params: Params) => Promise<T>) => try {
(onError: (err: any) => void) => const p = myPubkey();
(...params: Params) => { if (p == null) return;
f(...params).catch((err) => { setUpdatingContacts(true);
onError(err);
await refetchMyFollowing();
await sleep(3000);
const current = myFollowingPubkeys();
console.debug('current pubkeys', current);
await updateContactsMutation.mutateAsync({
relayUrls: config().relayUrls,
pubkey: p,
content: myFollowingQuery.data?.content ?? '',
followingPubkeys: uniq(update(current)),
}); });
}; } finally {
setUpdatingContacts(false);
}
};
const follow = handlePromise(async () => { const follow = () => {
const p = myPubkey(); updateContacts((current) => [...current, props.pubkey]).catch((err) => {
if (p == null) return; console.log('failed to follow', err);
if (!myFollowingQuery.isFetched) return;
await refetchMyFollowing();
updateContactsMutation.mutate({
relayUrls: config().relayUrls,
pubkey: p,
content: myFollowingQuery.data?.content ?? '',
followingPubkeys: uniq([...myFollowingPubkeys(), props.pubkey]),
}); });
})((err) => { };
console.log('failed to follow', err);
});
const unfollow = handlePromise(async () => {
const p = myPubkey();
if (p == null) return;
if (!myFollowingQuery.isFetched) return;
const unfollow = () => {
if (!window.confirm('本当にフォロー解除しますか?')) return; if (!window.confirm('本当にフォロー解除しますか?')) return;
await refetchMyFollowing(); updateContacts((current) => current.filter((k) => k !== props.pubkey)).catch((err) => {
updateContactsMutation.mutate({ console.log('failed to unfollow', err);
relayUrls: config().relayUrls,
pubkey: p,
content: myFollowingQuery.data?.content ?? '',
followingPubkeys: myFollowingPubkeys().filter((k) => k !== props.pubkey),
}); });
})((err) => { };
console.log('failed to unfollow', err);
});
const menu: MenuItem[] = [ const menu: MenuItem[] = [
/* /*
@@ -247,16 +243,16 @@ const ProfileDisplay: Component<ProfileDisplayProps> = (props) => {
</button> </button>
</Match> </Match>
<Match when={updateContactsMutation.isLoading || updatingContacts()}>
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
</span>
</Match>
<Match when={myFollowingQuery.isLoading || myFollowingQuery.isFetching}> <Match when={myFollowingQuery.isLoading || myFollowingQuery.isFetching}>
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base"> <span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
</span> </span>
</Match> </Match>
<Match when={updateContactsMutation.isLoading}>
<span class="rounded-full border border-primary px-4 py-2 text-primary sm:text-base">
</span>
</Match>
<Match when={following()}> <Match when={following()}>
<button <button
class="rounded-full border border-primary bg-primary px-4 py-2 class="rounded-full border border-primary bg-primary px-4 py-2

View File

@@ -56,7 +56,7 @@ const useFollowings = (propsProvider: () => UseFollowingsProps | null): UseFollo
{ {
staleTime: 5 * 60 * 1000, // 5 min staleTime: 5 * 60 * 1000, // 5 min
cacheTime: 24 * 60 * 60 * 1000, // 24 hour cacheTime: 24 * 60 * 60 * 1000, // 24 hour
refetchOnMount: false, refetchOnMount: true,
refetchOnWindowFocus: false, refetchOnWindowFocus: false,
refetchOnReconnect: false, refetchOnReconnect: false,
refetchInterval: 0, refetchInterval: 0,

View File

@@ -33,14 +33,6 @@ export type UseProfiles = {
type UseProfileQueryKey = readonly ['useProfile', UseProfileProps | null]; type UseProfileQueryKey = readonly ['useProfile', UseProfileProps | null];
const queryOptions = {
// 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: 24 * 60 * 60 * 1000, // 1 day
refetchInterval: 5 * 60 * 1000, // 5 min
};
const getProfile = ({ const getProfile = ({
queryKey, queryKey,
signal, signal,
@@ -71,7 +63,7 @@ const getProfile = ({
return latestEvent(); return latestEvent();
}); });
// TODO timeoutと同時にsignalでキャンセルするようにしたい // TODO timeoutと同時にsignalでキャンセルするようにしたい
return timeout(15000, `useProfile: ${pubkey}`)(promise); return timeout(3000, `useProfile: ${pubkey}`)(promise);
}; };
const useProfile = (propsProvider: () => UseProfileProps | null): UseProfile => { const useProfile = (propsProvider: () => UseProfileProps | null): UseProfile => {
@@ -82,7 +74,14 @@ const useProfile = (propsProvider: () => UseProfileProps | null): UseProfile =>
const query = createQuery( const query = createQuery(
genQueryKey, genQueryKey,
({ queryKey, signal }) => getProfile({ queryKey, signal, queryClient }), ({ queryKey, signal }) => getProfile({ queryKey, signal, queryClient }),
queryOptions, {
// 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: 24 * 60 * 60 * 1000, // 1 day
refetchInterval: 5 * 60 * 1000, // 5 min
refetchOnWindowFocus: false,
},
); );
const profile = createMemo((): Profile | null => { const profile = createMemo((): Profile | null => {