use-feed-state-string.ts
1 import { useMemo } from 'react'; 2 import useStateString from './use-state-string'; 3 import { useSubplebbit, useSubplebbitsStates } from '@plebbit/plebbit-react-hooks'; 4 5 const clientHosts: { [key: string]: string } = {}; 6 7 const getClientHost = (clientUrl: string): string => { 8 if (!clientHosts[clientUrl]) { 9 try { 10 clientHosts[clientUrl] = new URL(clientUrl).hostname || clientUrl; 11 } catch (e) { 12 clientHosts[clientUrl] = clientUrl; 13 } 14 } 15 return clientHosts[clientUrl]; 16 }; 17 18 const useFeedStateString = (subplebbitAddresses?: string[]): string | undefined => { 19 // single subplebbit feed state string 20 const subplebbitAddress = subplebbitAddresses?.length === 1 ? subplebbitAddresses[0] : undefined; 21 const subplebbit = useSubplebbit({ subplebbitAddress }); 22 const singleSubplebbitFeedStateString = useStateString(subplebbit); 23 24 // multiple subplebbit feed state string 25 const { states } = useSubplebbitsStates({ subplebbitAddresses }); 26 27 const multipleSubplebbitsFeedStateString = useMemo(() => { 28 if (subplebbitAddress) { 29 return; 30 } 31 32 // e.g. Resolving 2 addresses from infura.io, fetching 2 IPNS, 1 IPFS from cloudflare-ipfs.com, ipfs.io 33 let stateString = ''; 34 35 if (states['resolving-address']) { 36 const { subplebbitAddresses, clientUrls } = states['resolving-address']; 37 if (subplebbitAddresses.length && clientUrls.length) { 38 stateString += `resolving ${subplebbitAddresses.length} ${subplebbitAddresses.length === 1 ? 'address' : 'addresses'} from ${clientUrls 39 .map(getClientHost) 40 .join(', ')}`; 41 } 42 } 43 44 // find all page client and sub addresses 45 const pagesStatesClientHosts = new Set(); 46 const pagesStatesSubplebbitAddresses = new Set(); 47 for (const state in states) { 48 if (state.match('page')) { 49 states[state].clientUrls.forEach((clientUrl) => pagesStatesClientHosts.add(getClientHost(clientUrl))); 50 states[state].subplebbitAddresses.forEach((subplebbitAddress) => pagesStatesSubplebbitAddresses.add(subplebbitAddress)); 51 } 52 } 53 54 if (states['fetching-ipns'] || states['fetching-ipfs'] || pagesStatesSubplebbitAddresses.size) { 55 // separate 2 different states using ', ' 56 if (stateString) { 57 stateString += ', '; 58 } 59 60 // find all client urls 61 const clientHosts = new Set([...pagesStatesClientHosts]); 62 states['fetching-ipns']?.clientUrls.forEach((clientUrl) => clientHosts.add(getClientHost(clientUrl))); 63 states['fetching-ipfs']?.clientUrls.forEach((clientUrl) => clientHosts.add(getClientHost(clientUrl))); 64 65 if (clientHosts.size) { 66 stateString += 'fetching '; 67 if (states['fetching-ipns']) { 68 stateString += `${states['fetching-ipns'].subplebbitAddresses.length} IPNS`; 69 } 70 if (states['fetching-ipfs']) { 71 if (states['fetching-ipns']) { 72 stateString += ', '; 73 } 74 stateString += `${states['fetching-ipfs'].subplebbitAddresses.length} IPFS`; 75 } 76 if (pagesStatesSubplebbitAddresses.size) { 77 if (states['fetching-ipns'] || states['fetching-ipfs']) { 78 stateString += ', '; 79 } 80 stateString += `${pagesStatesSubplebbitAddresses.size} ${pagesStatesSubplebbitAddresses.size === 1 ? 'page' : 'pages'}`; 81 } 82 stateString += ` from ${[...clientHosts].join(', ')}`; 83 } 84 } 85 86 // capitalize first letter 87 stateString = stateString.charAt(0).toUpperCase() + stateString.slice(1); 88 89 // if string is empty, return undefined instead 90 return stateString === '' ? undefined : stateString; 91 }, [states, subplebbitAddress]); 92 93 if (singleSubplebbitFeedStateString) { 94 return singleSubplebbitFeedStateString; 95 } 96 return multipleSubplebbitsFeedStateString; 97 }; 98 99 export default useFeedStateString;