| 43 | }; |
| 44 | |
| 45 | export const useGetShortUrl = ({ |
| 46 | query, |
| 47 | }: UseGetShortUrl = {}): UseGetShortUrlResult => { |
| 48 | const { user, isAuthReady } = useAuthContext(); |
| 49 | const queryClient = useQueryClient(); |
| 50 | const getProps = useCallback( |
| 51 | (url: string, cid?: ReferralCampaignKey) => |
| 52 | getShortLinkProps(url, cid, user), |
| 53 | [user], |
| 54 | ); |
| 55 | |
| 56 | const queryShortUrl = async (url: string) => { |
| 57 | const res = await gqlClient.request(GET_SHORT_URL_QUERY, { url }); |
| 58 | return res.getShortUrl; |
| 59 | }; |
| 60 | |
| 61 | const getShortUrl = useCallback( |
| 62 | async (url: string, cid?: ReferralCampaignKey) => { |
| 63 | if (!url || !isAuthReady || !user) { |
| 64 | return url; |
| 65 | } |
| 66 | |
| 67 | const { trackedUrl, queryKey } = getProps(url, cid); |
| 68 | |
| 69 | // Caught here, or a rejection after the deadline wins the race below has |
| 70 | // no handler left. |
| 71 | const shortening = queryClient |
| 72 | .fetchQuery({ |
| 73 | queryKey, |
| 74 | queryFn: () => queryShortUrl(trackedUrl), |
| 75 | staleTime: Infinity, |
| 76 | // One attempt: retry with backoff holds the press for seconds when the |
| 77 | // shortener is down. Not always honoured, though: if the `useQuery` |
| 78 | // branch below is already fetching this key, query-core returns the |
| 79 | // in-flight retryer before applying these options, and only the |
| 80 | // deadline bounds the wait. |
| 81 | retry: false, |
| 82 | }) |
| 83 | .catch(() => null); |
| 84 | |
| 85 | // Every share waits here before anything reaches the clipboard, and a |
| 86 | // request that never answers would hold the press indefinitely. |
| 87 | let deadline: ReturnType<typeof setTimeout> | undefined; |
| 88 | const shortened = await Promise.race([ |
| 89 | shortening, |
| 90 | new Promise<null>((settle) => { |
| 91 | deadline = setTimeout(() => settle(null), shortUrlDeadline); |
| 92 | }), |
| 93 | ]); |
| 94 | |
| 95 | clearTimeout(deadline); |
| 96 | |
| 97 | return shortened ?? trackedUrl; |
| 98 | }, |
| 99 | [isAuthReady, user, getProps, queryClient], |
| 100 | ); |
| 101 | |
| 102 | const getTrackedUrl = useCallback( |