2023-09-12 06:27:54 +03:00
|
|
|
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;
|
2023-09-12 13:00:19 +03:00
|
|
|
setAccounts([]);
|
2023-09-12 06:27:54 +03:00
|
|
|
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);
|
|
|
|
}
|
2023-09-12 13:00:19 +03:00
|
|
|
}, [staticAccounts, fetchAccounts]);
|
2023-09-12 06:27:54 +03:00
|
|
|
|
|
|
|
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>
|
|
|
|
);
|
|
|
|
}
|