ClaimList: add default page-load indicator | Apply for Search and Following-Manage

Clients can still choose to roll their own way of showing "is fetching", like how ClaimListDiscover displays a whole bunch of placeholder tiles. This just serves as a default.
This commit is contained in:
infinite-persistence 2022-03-02 21:07:35 +08:00 committed by Thomas Zarebczan
parent 06f7cdbe25
commit f839e0c35d
4 changed files with 21 additions and 1 deletions

View file

@ -25,6 +25,7 @@ type Props = {
header: Node | boolean,
headerAltControls: Node,
loading: boolean,
useLoadingSpinner?: boolean, // use built-in spinner when 'loading' is true. Else, roll your own at client-side.
type: string,
activeUri?: string,
empty?: string,
@ -65,6 +66,7 @@ export default function ClaimList(props: Props) {
prefixUris,
headerAltControls,
loading,
useLoadingSpinner,
persistedStorageKey,
empty,
defaultSort,
@ -200,6 +202,7 @@ export default function ClaimList(props: Props) {
swipeLayout={swipeLayout}
/>
))}
{loading && useLoadingSpinner && <ClaimPreviewTile placeholder="loading" swipeLayout={swipeLayout} />}
{!timedOut && urisLength === 0 && !loading && <div className="empty main--empty">{empty || noResultMsg}</div>}
{timedOut && timedOutMessage && <div className="empty main--empty">{timedOutMessage}</div>}
</section>
@ -289,6 +292,11 @@ export default function ClaimList(props: Props) {
{!timedOut && urisLength === 0 && !loading && <div className="empty empty--centered">{empty || noResultMsg}</div>}
{!loading && timedOut && timedOutMessage && <div className="empty empty--centered">{timedOutMessage}</div>}
{loading && useLoadingSpinner && (
<div className="spinnerArea--centered">
<Spinner type="small" />
</div>
)}
</section>
);
}

View file

@ -39,6 +39,7 @@ export default function ChannelsFollowingManage(props: Props) {
// Infinite-scroll handling. 'page' is 0-indexed.
const [page, setPage] = React.useState(-1);
const lastPage = Math.max(0, Math.ceil(uris.length / FOLLOW_PAGE_SIZE) - 1);
const [loadingPage, setLoadingPage] = React.useState(false);
async function resolveUris(uris) {
return doResolveUris(uris, true, false);
@ -52,7 +53,11 @@ export default function ChannelsFollowingManage(props: Props) {
function bumpPage() {
if (page < lastPage) {
resolveNextPage(uris, page).finally(() => setPage(page + 1));
setLoadingPage(true);
resolveNextPage(uris, page).finally(() => {
setLoadingPage(false);
setPage(page + 1);
});
}
}
@ -96,6 +101,8 @@ export default function ChannelsFollowingManage(props: Props) {
onScrollBottom={bumpPage}
page={page + 1}
pageSize={FOLLOW_PAGE_SIZE}
loading={loadingPage}
useLoadingSpinner
/>
)}
</>

View file

@ -90,6 +90,7 @@ export default function SearchPage(props: Props) {
<ClaimList
uris={uris}
loading={isSearching}
useLoadingSpinner
onScrollBottom={loadMore}
// 'page' is 1-indexed; It's not the same as 'from', but it just
// needs to be unique to indicate when a fetch is needed.

View file

@ -52,3 +52,7 @@
width: 3px;
}
}
.spinnerArea--centered {
text-align: center;
}