lbry-desktop/ui/effects/use-resolve-pins.js
infinite-persistence f5034f74ca Batch resolve pin urls in 2 ways
Expanded homepage pins to support 2 types of input (if both are passed in, pinnedUrls take precedence):
  (1) pinnedUrls     --> uses doResolveUris (resolve)
  (2) pinnedClaimIds --> uses doResolveClaimIds (claim_search)

Instead of injecting the pinned URLs directly, we inject from `resolvedPinUris`, which will be blank until the uris are resolved, thus preventing it from being resolved individually from the tiles.

There's additional complexity with the `claim_search` method, as the rest of the code deals with uris instead of IDs. Fortunately, it's all contained with `useResolvePins`, so removal would be easier when the batch `resolve` issue is fixed.
2022-03-31 15:58:10 -04:00

51 lines
2.1 KiB
JavaScript

// @flow
import React from 'react';
import useFetched from 'effects/use-fetched';
type Props = {
pins?: { urls?: Array<string>, claimIds?: Array<string>, onlyPinForOrder?: string },
claimsById: { [string]: Claim },
doResolveClaimIds: (Array<string>) => Promise<any>,
doResolveUris: (Array<string>, boolean) => Promise<any>,
};
export default function useResolvePins(props: Props) {
const { pins, claimsById, doResolveClaimIds, doResolveUris } = props;
const [resolvedPinUris, setResolvedPinUris] = React.useState(pins ? undefined : null);
const [resolvingPinUris, setResolvingPinUris] = React.useState(false);
const hasResolvedPinUris = useFetched(resolvingPinUris);
React.useEffect(() => {
if (resolvedPinUris === undefined && pins && !resolvingPinUris) {
if (pins.urls) {
doResolveUris(pins.urls, true).finally(() => setResolvedPinUris(pins.urls));
} else if (pins.claimIds) {
// setResolvingPinUris is only needed for claim_search.
// doResolveUris uses selectResolvingUris internally to prevent double call.
setResolvingPinUris(true);
// We can't use .then() here to grab the `claim_search` uris directly,
// because we skip those that are already resolved. Instead, we mark a
// flag here, then populate the array in the other effect below in the
// next render cycle (redux would be updated by then). Pretty dumb.
// $FlowFixMe: already checked for null `pins`, but flow can't see it when there's code above it? Wow.
doResolveClaimIds(pins.claimIds).finally(() => setResolvingPinUris(false));
} else {
setResolvedPinUris(null);
}
}
}, [resolvedPinUris, pins, doResolveUris, doResolveClaimIds, resolvingPinUris]);
React.useEffect(() => {
if (hasResolvedPinUris) {
if (pins && pins.claimIds) {
setResolvedPinUris(pins.claimIds.map<string>((id) => claimsById[id]?.canonical_url));
}
}
// Only do this over a false->true->false transition for hasResolvedPinUris.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hasResolvedPinUris]);
return resolvedPinUris;
}