2022-03-01 04:19:20 +01:00
|
|
|
// @flow
|
|
|
|
import React from 'react';
|
|
|
|
import ClaimList from 'component/claimList';
|
|
|
|
import DebouncedInput from 'component/common/debounced-input';
|
|
|
|
import Empty from 'component/common/empty';
|
|
|
|
import Page from 'component/page';
|
|
|
|
import Spinner from 'component/spinner';
|
|
|
|
import * as ICONS from 'constants/icons';
|
|
|
|
|
|
|
|
function getFilteredUris(uris, filterQuery) {
|
|
|
|
if (filterQuery) {
|
|
|
|
const filterQueryLowerCase = filterQuery.toLowerCase();
|
|
|
|
return uris.filter((uri) => uri.toLowerCase().includes(filterQueryLowerCase));
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ****************************************************************************
|
|
|
|
// ChannelsFollowingManage
|
|
|
|
// ****************************************************************************
|
|
|
|
|
2022-03-01 07:40:35 +01:00
|
|
|
const FOLLOW_PAGE_SIZE = 30;
|
|
|
|
|
2022-03-01 04:19:20 +01:00
|
|
|
type Props = {
|
|
|
|
subscribedChannelUris: Array<string>,
|
2022-03-01 07:40:35 +01:00
|
|
|
doResolveUris: (uris: Array<string>, returnCachedClaims: boolean, resolveReposts: boolean) => void,
|
2022-03-01 04:19:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
export default function ChannelsFollowingManage(props: Props) {
|
2022-03-01 07:40:35 +01:00
|
|
|
const { subscribedChannelUris, doResolveUris } = props;
|
|
|
|
|
|
|
|
// The locked-on-mount full set of subscribed uris.
|
2022-03-01 04:19:20 +01:00
|
|
|
const [uris, setUris] = React.useState([]);
|
2022-03-01 07:40:35 +01:00
|
|
|
|
|
|
|
// Filtered query and their uris.
|
2022-03-01 04:19:20 +01:00
|
|
|
const [filterQuery, setFilterQuery] = React.useState('');
|
2022-03-01 07:40:35 +01:00
|
|
|
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);
|
2022-03-02 14:07:35 +01:00
|
|
|
const [loadingPage, setLoadingPage] = React.useState(false);
|
2022-03-01 07:40:35 +01:00
|
|
|
|
|
|
|
async function resolveUris(uris) {
|
|
|
|
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) {
|
2022-03-02 14:07:35 +01:00
|
|
|
setLoadingPage(true);
|
|
|
|
resolveNextPage(uris, page).finally(() => {
|
|
|
|
setLoadingPage(false);
|
|
|
|
setPage(page + 1);
|
|
|
|
});
|
2022-03-01 07:40:35 +01:00
|
|
|
}
|
|
|
|
}
|
2022-03-01 04:19:20 +01:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
setUris(subscribedChannelUris);
|
2022-03-01 07:40:35 +01:00
|
|
|
resolveNextPage(subscribedChannelUris, -1).finally(() => setPage(0));
|
2022-03-01 04:19:20 +01:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps, (lock list on mount so it doesn't shift when unfollow)
|
|
|
|
}, []);
|
|
|
|
|
2022-03-01 07:40:35 +01:00
|
|
|
React.useEffect(() => {
|
|
|
|
const filteredUris = getFilteredUris(uris, filterQuery);
|
|
|
|
if (filteredUris) {
|
|
|
|
resolveUris(filteredUris).finally(() => setFilteredUris(filteredUris));
|
|
|
|
} else {
|
|
|
|
setFilteredUris(filteredUris);
|
|
|
|
}
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps, (only need to respond to 'filterQuery')
|
|
|
|
}, [filterQuery]);
|
|
|
|
|
2022-03-01 04:19:20 +01:00
|
|
|
return (
|
|
|
|
<Page className="followManage-wrapper" noFooter>
|
|
|
|
<div className="card__title-section">
|
|
|
|
<div className="card__title"> {__('Followed Channels')}</div>
|
|
|
|
</div>
|
|
|
|
|
2022-03-01 07:40:35 +01:00
|
|
|
{page < 0 ? (
|
2022-03-01 04:19:20 +01:00
|
|
|
<div className="main--empty">
|
2022-03-01 07:40:35 +01:00
|
|
|
<Spinner delayed />
|
2022-03-01 04:19:20 +01:00
|
|
|
</div>
|
|
|
|
) : uris && uris.length === 0 ? (
|
|
|
|
<Empty padded text="No followed channels." />
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<DebouncedInput icon={ICONS.SEARCH} placeholder={__('Filter')} onChange={setFilterQuery} inline />
|
2022-03-01 07:40:35 +01:00
|
|
|
|
2022-03-01 04:19:20 +01:00
|
|
|
{filteredUris && <ClaimList uris={filteredUris} />}
|
2022-03-01 07:40:35 +01:00
|
|
|
|
|
|
|
{!filteredUris && uris.length > 0 && (
|
|
|
|
<ClaimList
|
|
|
|
uris={uris.slice(0, (page + 1) * FOLLOW_PAGE_SIZE)}
|
|
|
|
onScrollBottom={bumpPage}
|
|
|
|
page={page + 1}
|
|
|
|
pageSize={FOLLOW_PAGE_SIZE}
|
2022-03-02 14:07:35 +01:00
|
|
|
loading={loadingPage}
|
|
|
|
useLoadingSpinner
|
2022-03-01 04:19:20 +01:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</Page>
|
|
|
|
);
|
|
|
|
}
|