import './generic-accounts.css'; import { useEffect, useState } from 'preact/hooks'; import { InView } from 'react-intersection-observer'; import { useSnapshot } from 'valtio'; import states from '../utils/states'; import AccountBlock from './account-block'; import Icon from './icon'; import Loader from './loader'; export default function GenericAccounts({ onClose = () => {} }) { const snapStates = useSnapshot(states); const [uiState, setUIState] = useState('default'); const [accounts, setAccounts] = useState([]); const [showMore, setShowMore] = useState(false); if (!snapStates.showGenericAccounts) { return null; } const { heading, fetchAccounts, accounts: staticAccounts, showReactions, } = snapStates.showGenericAccounts; const loadAccounts = (firstLoad) => { if (!fetchAccounts) return; if (firstLoad) setAccounts([]); setUIState('loading'); (async () => { try { const { done, value } = await fetchAccounts(firstLoad); if (Array.isArray(value)) { if (firstLoad) { setAccounts(value); } else { setAccounts((prev) => [...prev, ...value]); } setShowMore(!done); } else { setShowMore(false); } setUIState('default'); } catch (e) { console.error(e); setUIState('error'); } })(); }; useEffect(() => { if (staticAccounts?.length > 0) { setAccounts(staticAccounts); } else { loadAccounts(true); } }, [staticAccounts, fetchAccounts]); return ( <div id="generic-accounts-container" class="sheet" tabindex="-1"> <button type="button" class="sheet-close" onClick={onClose}> <Icon icon="x" /> </button> <header> <h2>{heading || 'Accounts'}</h2> </header> <main> {accounts.length > 0 ? ( <> <ul class="accounts-list"> {accounts.map((account) => ( <li key={account.id}> {showReactions && account._types?.length > 0 && ( <div class="reactions-block"> {account._types.map((type) => ( <Icon icon={ { reblog: 'rocket', favourite: 'heart', }[type] } class={`${type}-icon`} /> ))} </div> )} <AccountBlock account={account} /> </li> ))} </ul> {uiState === 'default' ? ( showMore ? ( <InView onChange={(inView) => { if (inView) { loadAccounts(); } }} > <button type="button" class="plain block" onClick={() => loadAccounts()} > Show more… </button> </InView> ) : ( <p class="ui-state insignificant">The end.</p> ) ) : ( uiState === 'loading' && ( <p class="ui-state"> <Loader abrupt /> </p> ) )} </> ) : uiState === 'loading' ? ( <p class="ui-state"> <Loader abrupt /> </p> ) : uiState === 'error' ? ( <p class="ui-state">Error loading accounts</p> ) : ( <p class="ui-state insignificant">Nothing to show</p> )} </main> </div> ); }