From 3e6056121467594fedc99683c24ad2cbf37d4808 Mon Sep 17 00:00:00 2001 From: mdrbohlav Date: Fri, 7 Apr 2023 16:58:52 +0200 Subject: [PATCH] allow async prepareData function --- src/SocialPreview.tsx | 75 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/src/SocialPreview.tsx b/src/SocialPreview.tsx index ceee57f..9f2f77b 100644 --- a/src/SocialPreview.tsx +++ b/src/SocialPreview.tsx @@ -1,5 +1,5 @@ import { Flex, Spinner } from '@sanity/ui' -import React, { useCallback, useState } from 'react' +import React, { useCallback, useState, useEffect } from 'react' import styled from 'styled-components' import FacebookLogo from './components/Facebook/FacebookLogo' @@ -15,7 +15,6 @@ import { BasePreviewProps, DocumentView, Network, - PrepareFunction, SocialPreviewProps, } from './types' @@ -66,6 +65,11 @@ const NETWORKS: Record< linkedin: { icon: LinkedinLogo, component: LinkedinSharePreview }, } +async function asyncCall(this: unknown, item: unknown, ...args: unknown[]): Promise { + // eslint-disable-next-line no-return-await + return await (typeof item === 'function' ? item.apply(this, args) : item) +} + const SocialPreview = ({ prepareData = fallbackPrepareData, google, @@ -74,15 +78,63 @@ const SocialPreview = ({ facebook, }: SocialPreviewProps = {}) => { return function SocialPreviewComponent({ document }: DocumentView) { - const previewProps = prepareData(document?.displayed) + const [loading, setLoading] = useState(undefined) const [chosenNetwork, setChosenNetwork] = useState('google') + const [networkProps, setNetworkProps] = useState>({}) const chooseNetwork = useCallback( (network: Network) => () => setChosenNetwork(network), [setChosenNetwork], ) - if (!previewProps || !document?.displayed || Object.keys(document.displayed).length <= 2) { + const availableNetworks: Record = { + google: google === false ? undefined : true, + twitter: twitter === false ? undefined : true, + linkedin: linkedin === false ? undefined : true, + facebook: facebook === false ? undefined : true, + } + const networkKeys = Object.keys(NETWORKS) as Network[] + + useEffect(() => { + const loadProps = () => { + setLoading(true) + + Promise.all([ + asyncCall(prepareData, document?.displayed) as Promise, + asyncCall(google, document?.displayed) as Promise, + asyncCall(twitter, document?.displayed) as Promise, + asyncCall(linkedin, document?.displayed) as Promise, + asyncCall(facebook, document?.displayed) as Promise, + ]).then(([data, googleData, twitterData, linkedinData, facebookData]) => { + const newNetworkProps = { ...networkProps } + + if (availableNetworks.google) { + newNetworkProps.google = googleData || data + } + + if (availableNetworks.twitter) { + newNetworkProps.twitter = twitterData || data + } + + if (availableNetworks.linkedin) { + newNetworkProps.linkedin = linkedinData || data + } + + if (availableNetworks.facebook) { + newNetworkProps.facebook = facebookData || data + } + + setNetworkProps(newNetworkProps) + setLoading(false) + }) + } + + if (loading === undefined) { + loadProps() + } + }, [loading, setLoading]) + + if (loading !== false) { return ( @@ -90,19 +142,11 @@ const SocialPreview = ({ ) } - const networkProps: Record> = { - google: google === false ? undefined : (google || prepareData)(document?.displayed), - twitter: twitter === false ? undefined : (twitter || prepareData)(document?.displayed), - linkedin: linkedin === false ? undefined : (linkedin || prepareData)(document?.displayed), - facebook: facebook === false ? undefined : (facebook || prepareData)(document?.displayed), - } - const networkKeys = Object.keys(NETWORKS) as Network[] - return (
{networkKeys.map((network) => { - if (!networkProps[network]) return null + if (!availableNetworks[network]) return null const { icon: Icon } = NETWORKS[network] return ( @@ -118,11 +162,10 @@ const SocialPreview = ({ })}
{networkKeys.map((network) => { - const props = networkProps[network] - if (!props || network !== chosenNetwork) return null + if (!availableNetworks[network] || network !== chosenNetwork) return null const { component: Component } = NETWORKS[network] - return + return })}
)