2024-03-22 14:15:35 +01:00
|
|
|
import { useMemo } from 'react';
|
2026-03-09 17:01:35 +08:00
|
|
|
import { useClientsStates, useSubplebbit, useSubplebbitsStates } from '@bitsocialnet/bitsocial-react-hooks';
|
2026-02-18 15:31:01 +08:00
|
|
|
import debounce from 'lodash/debounce';
|
2026-03-09 19:29:35 +08:00
|
|
|
import getShortAddress from '../lib/get-short-address';
|
2024-03-22 14:15:35 +01:00
|
|
|
|
|
|
|
|
interface CommentOrSubplebbit {
|
|
|
|
|
state?: string;
|
|
|
|
|
publishingState?: string;
|
|
|
|
|
updatingState?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface States {
|
|
|
|
|
[key: string]: string[];
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-09 19:29:35 +08:00
|
|
|
const friendlyStateNames: Record<string, string> = {
|
|
|
|
|
'fetching-ipns': 'downloading board',
|
|
|
|
|
'fetching-ipfs': 'downloading thread',
|
|
|
|
|
'fetching-subplebbit-ipns': 'downloading board',
|
|
|
|
|
'fetching-subplebbit-ipfs': 'downloading board',
|
|
|
|
|
'fetching-update-ipfs': 'downloading update',
|
|
|
|
|
'resolving-address': 'resolving address',
|
|
|
|
|
'resolving-subplebbit-address': 'resolving board address',
|
|
|
|
|
'resolving-author-address': 'resolving author address',
|
2024-03-22 14:15:35 +01:00
|
|
|
};
|
|
|
|
|
|
2026-03-09 19:29:35 +08:00
|
|
|
const getFriendlyStateName = (state: string): string => friendlyStateNames[state] || state.replaceAll('-', ' ');
|
|
|
|
|
|
2026-02-20 14:51:39 +08:00
|
|
|
const sanitizeSingleFeedLoadingState = (stateString?: string): string | undefined => {
|
|
|
|
|
if (!stateString) {
|
|
|
|
|
return stateString;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stateString
|
|
|
|
|
.replace(/\bDownloading thread\b/g, 'Downloading board')
|
|
|
|
|
.replace(/\bdownloading thread\b/g, 'downloading board')
|
|
|
|
|
.replace(/\bLoading thread\b/g, 'Loading board')
|
|
|
|
|
.replace(/\bloading thread\b/g, 'loading board');
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-22 14:15:35 +01:00
|
|
|
const useStateString = (commentOrSubplebbit: CommentOrSubplebbit): string | undefined => {
|
2025-02-20 13:29:24 +01:00
|
|
|
const { states: rawStates } = useClientsStates({ comment: commentOrSubplebbit }) as { states: States };
|
|
|
|
|
|
|
|
|
|
const debouncedStates = useMemo(() => {
|
|
|
|
|
const debouncedValue = debounce((value: States) => value, 300);
|
|
|
|
|
return debouncedValue(rawStates);
|
|
|
|
|
}, [rawStates]);
|
|
|
|
|
|
2024-03-22 14:15:35 +01:00
|
|
|
return useMemo(() => {
|
|
|
|
|
let stateString: string | undefined = '';
|
2026-03-09 19:29:35 +08:00
|
|
|
const resolvingParts: string[] = [];
|
|
|
|
|
const downloadingParts: string[] = [];
|
2024-03-22 14:15:35 +01:00
|
|
|
|
2025-02-20 13:29:24 +01:00
|
|
|
for (const state in debouncedStates) {
|
2026-03-09 19:29:35 +08:00
|
|
|
if (debouncedStates[state].length === 0) continue;
|
|
|
|
|
const friendlyName = getFriendlyStateName(state);
|
|
|
|
|
if (state.includes('resolving')) {
|
|
|
|
|
resolvingParts.push(friendlyName);
|
|
|
|
|
} else {
|
|
|
|
|
downloadingParts.push(friendlyName);
|
2024-03-22 14:15:35 +01:00
|
|
|
}
|
2026-03-09 19:29:35 +08:00
|
|
|
}
|
2024-03-22 14:15:35 +01:00
|
|
|
|
2026-03-09 19:29:35 +08:00
|
|
|
if (resolvingParts.length) {
|
|
|
|
|
stateString = resolvingParts.join(', ');
|
|
|
|
|
}
|
|
|
|
|
if (downloadingParts.length) {
|
|
|
|
|
if (stateString) stateString += ', ';
|
|
|
|
|
stateString += downloadingParts.join(', ') + ' via IPFS';
|
2024-03-22 14:15:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!stateString && commentOrSubplebbit?.state !== 'succeeded') {
|
|
|
|
|
if (commentOrSubplebbit?.publishingState && commentOrSubplebbit?.publishingState !== 'stopped' && commentOrSubplebbit?.publishingState !== 'succeeded') {
|
|
|
|
|
stateString = commentOrSubplebbit.publishingState;
|
|
|
|
|
} else if (commentOrSubplebbit?.updatingState !== 'stopped' && commentOrSubplebbit?.updatingState !== 'succeeded') {
|
2026-03-08 16:30:02 +08:00
|
|
|
stateString = commentOrSubplebbit?.updatingState;
|
2024-03-22 14:15:35 +01:00
|
|
|
}
|
|
|
|
|
if (stateString) {
|
2026-03-09 19:29:35 +08:00
|
|
|
const isIpfsRelated = stateString.includes('ipfs') || stateString.includes('ipns');
|
2025-02-20 13:29:24 +01:00
|
|
|
stateString = stateString
|
|
|
|
|
.replaceAll('-', ' ')
|
2025-02-24 22:40:05 +01:00
|
|
|
.replace('ipfs', 'thread')
|
2025-02-20 13:29:24 +01:00
|
|
|
.replace('ipns', 'subplebbit')
|
2025-02-24 16:18:31 +01:00
|
|
|
.replace('fetching', 'downloading')
|
2025-02-20 13:29:24 +01:00
|
|
|
.replace('subplebbit subplebbit', 'board')
|
2025-02-24 16:18:31 +01:00
|
|
|
.replace('downloading subplebbit', 'downloading board');
|
2026-03-09 19:29:35 +08:00
|
|
|
if (isIpfsRelated) {
|
|
|
|
|
stateString += ' via IPFS';
|
|
|
|
|
}
|
2024-03-22 14:15:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stateString) {
|
|
|
|
|
stateString = stateString.charAt(0).toUpperCase() + stateString.slice(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stateString === '' ? undefined : stateString;
|
2025-02-20 13:29:24 +01:00
|
|
|
}, [debouncedStates, commentOrSubplebbit]);
|
2024-03-22 14:15:35 +01:00
|
|
|
};
|
|
|
|
|
|
2025-02-28 23:36:33 +01:00
|
|
|
export const useFeedStateString = (subplebbitAddresses?: string[]): string | undefined => {
|
|
|
|
|
// single subplebbit feed state string
|
|
|
|
|
const subplebbitAddress = subplebbitAddresses?.length === 1 ? subplebbitAddresses[0] : undefined;
|
|
|
|
|
const subplebbit = useSubplebbit({ subplebbitAddress });
|
2026-02-20 14:51:39 +08:00
|
|
|
const singleSubplebbitFeedStateString = sanitizeSingleFeedLoadingState(useStateString(subplebbit));
|
2025-02-28 23:36:33 +01:00
|
|
|
|
|
|
|
|
// multiple subplebbit feed state string
|
|
|
|
|
const { states } = useSubplebbitsStates({ subplebbitAddresses });
|
|
|
|
|
|
|
|
|
|
const multipleSubplebbitsFeedStateString = useMemo(() => {
|
|
|
|
|
if (subplebbitAddress) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let stateString = '';
|
|
|
|
|
|
|
|
|
|
if (states['resolving-address']) {
|
|
|
|
|
const { subplebbitAddresses, clientUrls } = states['resolving-address'];
|
|
|
|
|
if (subplebbitAddresses.length && clientUrls.length) {
|
2026-03-09 19:29:35 +08:00
|
|
|
const count = subplebbitAddresses.length;
|
|
|
|
|
stateString += `resolving ${count} board ${count === 1 ? 'address' : 'addresses'}`;
|
2025-02-28 23:36:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-09 19:29:35 +08:00
|
|
|
const pagesStatesSubplebbitAddresses = new Set<string>();
|
2025-02-28 23:36:33 +01:00
|
|
|
for (const state in states) {
|
|
|
|
|
if (state.match('page')) {
|
2026-03-09 19:29:35 +08:00
|
|
|
states[state].subplebbitAddresses.forEach((subplebbitAddress: string) => pagesStatesSubplebbitAddresses.add(subplebbitAddress));
|
2025-02-28 23:36:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (states['fetching-ipns'] || states['fetching-ipfs'] || pagesStatesSubplebbitAddresses.size) {
|
2026-03-09 19:29:35 +08:00
|
|
|
if (stateString) stateString += ', ';
|
|
|
|
|
stateString += 'downloading ';
|
|
|
|
|
if (states['fetching-ipns']) {
|
|
|
|
|
const count = states['fetching-ipns'].subplebbitAddresses.length;
|
|
|
|
|
stateString += `${count} ${count === 1 ? 'board' : 'boards'}`;
|
|
|
|
|
if (count <= 5) {
|
|
|
|
|
stateString += ` (${states['fetching-ipns'].subplebbitAddresses.map((a: string) => getShortAddress(a) || a).join(', ')})`;
|
|
|
|
|
}
|
2025-02-28 23:36:33 +01:00
|
|
|
}
|
2026-03-09 19:29:35 +08:00
|
|
|
if (states['fetching-ipfs']) {
|
|
|
|
|
if (states['fetching-ipns']) stateString += ', ';
|
|
|
|
|
const count = states['fetching-ipfs'].subplebbitAddresses.length;
|
|
|
|
|
stateString += `${count} ${count === 1 ? 'thread' : 'threads'}`;
|
2025-02-28 23:36:33 +01:00
|
|
|
}
|
2026-03-09 19:29:35 +08:00
|
|
|
if (pagesStatesSubplebbitAddresses.size) {
|
|
|
|
|
if (states['fetching-ipns'] || states['fetching-ipfs']) stateString += ', ';
|
|
|
|
|
const count = pagesStatesSubplebbitAddresses.size;
|
|
|
|
|
stateString += `${count} ${count === 1 ? 'page' : 'pages'}`;
|
|
|
|
|
}
|
|
|
|
|
stateString += ' via IPFS';
|
2025-02-28 23:36:33 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-08 17:36:55 +08:00
|
|
|
if (!stateString && subplebbitAddresses?.length) {
|
2026-03-09 19:29:35 +08:00
|
|
|
const count = subplebbitAddresses.length;
|
|
|
|
|
stateString = `downloading ${count} ${count === 1 ? 'board' : 'boards'}`;
|
|
|
|
|
if (count <= 5) {
|
|
|
|
|
stateString += ` (${subplebbitAddresses.map((a) => getShortAddress(a) || a).join(', ')})`;
|
|
|
|
|
}
|
2026-03-08 17:36:55 +08:00
|
|
|
}
|
|
|
|
|
|
2025-02-28 23:36:33 +01:00
|
|
|
// capitalize first letter
|
|
|
|
|
stateString = stateString.charAt(0).toUpperCase() + stateString.slice(1);
|
|
|
|
|
|
|
|
|
|
// if string is empty, return undefined instead
|
|
|
|
|
return stateString === '' ? undefined : stateString;
|
2026-03-08 17:36:55 +08:00
|
|
|
}, [states, subplebbitAddress, subplebbitAddresses]);
|
2025-02-28 23:36:33 +01:00
|
|
|
|
|
|
|
|
if (singleSubplebbitFeedStateString) {
|
|
|
|
|
return singleSubplebbitFeedStateString;
|
|
|
|
|
}
|
|
|
|
|
return multipleSubplebbitsFeedStateString;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-22 14:15:35 +01:00
|
|
|
export default useStateString;
|