ClaimList: Factor out infinite-scroll and batch-resolve handling into an effect.
It's also possible to move the use of `useClaimListInfiniteScroll` into `claimList` itself, but opted to keep them separate for now so that `claimList` doesn't end up a bloated file like `claimListDiscover`.
This commit is contained in:
parent
a4bb276608
commit
51616956d4
2 changed files with 69 additions and 31 deletions
62
ui/effects/use-claimList-infinite-scroll.js
Normal file
62
ui/effects/use-claimList-infinite-scroll.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// @flow
|
||||||
|
/**
|
||||||
|
* Infinite-scroll and batch-resolving handling for `claimList` instances.
|
||||||
|
*
|
||||||
|
* By default, the list is "locked" during initial mount to have a stable
|
||||||
|
* pagination, but can be disabled through the `disableListLock` parameter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function useClaimListInfiniteScroll(
|
||||||
|
allUris: Array<string>,
|
||||||
|
doResolveUris: (uris: Array<string>, returnCachedClaims: boolean, resolveReposts: boolean) => void,
|
||||||
|
pageSize: number = 30,
|
||||||
|
disableListLock: boolean = false
|
||||||
|
) {
|
||||||
|
// Lock the full set of uris on mount, so we have a stable list for pagination.
|
||||||
|
const [uris, setUris] = React.useState([]);
|
||||||
|
|
||||||
|
// Infinite-scroll handling. 'page' is 0-indexed.
|
||||||
|
const [page, setPage] = React.useState(-1);
|
||||||
|
const lastPage = Math.max(0, Math.ceil(allUris.length / pageSize) - 1);
|
||||||
|
const [isLoadingPage, setIsLoadingPage] = React.useState(true);
|
||||||
|
|
||||||
|
async function resolveUris(uris) {
|
||||||
|
return doResolveUris(uris, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveNextPage(uris, currPage, pageSize) {
|
||||||
|
const nextPage = currPage + 1;
|
||||||
|
const nextUriBatch = uris.slice(nextPage * pageSize, (nextPage + 1) * pageSize);
|
||||||
|
return resolveUris(nextUriBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bumpPage() {
|
||||||
|
if (page < lastPage) {
|
||||||
|
setIsLoadingPage(true);
|
||||||
|
resolveNextPage(uris, page, pageSize).finally(() => {
|
||||||
|
setIsLoadingPage(false);
|
||||||
|
setPage(page + 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Initial mount: lock list and resolve first batch:
|
||||||
|
React.useEffect(() => {
|
||||||
|
setUris(allUris);
|
||||||
|
resolveNextPage(allUris, -1, pageSize).finally(() => {
|
||||||
|
setIsLoadingPage(false);
|
||||||
|
setPage(0);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// -- Optional: remove the locking behavior for whatever reason:
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (disableListLock) {
|
||||||
|
setUris(allUris);
|
||||||
|
}
|
||||||
|
}, [allUris]);
|
||||||
|
|
||||||
|
return { uris, page, isLoadingPage, bumpPage };
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import Page from 'component/page';
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import { SIDEBAR_SUBS_DISPLAYED } from 'constants/subscriptions';
|
import { SIDEBAR_SUBS_DISPLAYED } from 'constants/subscriptions';
|
||||||
|
import useClaimListInfiniteScroll from 'effects/use-claimList-infinite-scroll';
|
||||||
|
|
||||||
function getFilteredUris(uris, filterQuery) {
|
function getFilteredUris(uris, filterQuery) {
|
||||||
if (filterQuery) {
|
if (filterQuery) {
|
||||||
|
@ -34,45 +35,20 @@ type Props = {
|
||||||
|
|
||||||
export default function ChannelsFollowingManage(props: Props) {
|
export default function ChannelsFollowingManage(props: Props) {
|
||||||
const { subscribedChannelUris, lastActiveSubs, doResolveUris, doFetchLastActiveSubs } = props;
|
const { subscribedChannelUris, lastActiveSubs, doResolveUris, doFetchLastActiveSubs } = props;
|
||||||
|
const { uris, page, isLoadingPage, bumpPage } = useClaimListInfiniteScroll(
|
||||||
// The locked-on-mount full set of subscribed uris.
|
subscribedChannelUris,
|
||||||
const [uris, setUris] = React.useState([]);
|
doResolveUris,
|
||||||
|
FOLLOW_PAGE_SIZE
|
||||||
|
);
|
||||||
|
|
||||||
// Filtered query and their uris.
|
// Filtered query and their uris.
|
||||||
const [filterQuery, setFilterQuery] = React.useState('');
|
const [filterQuery, setFilterQuery] = React.useState('');
|
||||||
const [filteredUris, setFilteredUris] = React.useState(null);
|
const [filteredUris, setFilteredUris] = React.useState(null);
|
||||||
|
|
||||||
// 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) {
|
async function resolveUris(uris) {
|
||||||
return doResolveUris(uris, true, false);
|
return doResolveUris(uris, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resolveNextPage(uris, currPage, pageSize = FOLLOW_PAGE_SIZE) {
|
|
||||||
const nextPage = currPage + 1;
|
|
||||||
const nextUriBatch = uris.slice(nextPage * pageSize, (nextPage + 1) * pageSize);
|
|
||||||
return resolveUris(nextUriBatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bumpPage() {
|
|
||||||
if (page < lastPage) {
|
|
||||||
setLoadingPage(true);
|
|
||||||
resolveNextPage(uris, page).finally(() => {
|
|
||||||
setLoadingPage(false);
|
|
||||||
setPage(page + 1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
setUris(subscribedChannelUris);
|
|
||||||
resolveNextPage(subscribedChannelUris, -1).finally(() => setPage(0));
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps, (lock list on mount so it doesn't shift when unfollow)
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const filteredUris = getFilteredUris(uris, filterQuery);
|
const filteredUris = getFilteredUris(uris, filterQuery);
|
||||||
if (filteredUris) {
|
if (filteredUris) {
|
||||||
|
@ -144,7 +120,7 @@ export default function ChannelsFollowingManage(props: Props) {
|
||||||
onScrollBottom={bumpPage}
|
onScrollBottom={bumpPage}
|
||||||
page={page + 1}
|
page={page + 1}
|
||||||
pageSize={FOLLOW_PAGE_SIZE}
|
pageSize={FOLLOW_PAGE_SIZE}
|
||||||
loading={loadingPage}
|
loading={isLoadingPage}
|
||||||
useLoadingSpinner
|
useLoadingSpinner
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in a new issue