Manage Subs page

This commit is contained in:
infinite-persistence 2022-03-01 11:19:20 +08:00 committed by Thomas Zarebczan
parent 1249b0394e
commit 0090e9b1ae
8 changed files with 126 additions and 16 deletions

View file

@ -746,6 +746,7 @@
"gaming, crypto": "gaming, crypto", "gaming, crypto": "gaming, crypto",
"Autocomplete": "Autocomplete", "Autocomplete": "Autocomplete",
"Followed Tags": "Followed Tags", "Followed Tags": "Followed Tags",
"Followed Channels": "Followed Channels",
"Manage Tags": "Manage Tags", "Manage Tags": "Manage Tags",
"%selectTagsLabel% (%number% left)": "%selectTagsLabel% (%number% left)", "%selectTagsLabel% (%number% left)": "%selectTagsLabel% (%number% left)",
"Matching": "Matching", "Matching": "Matching",

View file

@ -48,6 +48,9 @@ const ChannelsFollowingDiscoverPage = lazyImport(() =>
const ChannelsFollowingPage = lazyImport(() => const ChannelsFollowingPage = lazyImport(() =>
import('page/channelsFollowing' /* webpackChunkName: "channelsFollowing" */) import('page/channelsFollowing' /* webpackChunkName: "channelsFollowing" */)
); );
const ChannelsFollowingManage = lazyImport(() =>
import('page/channelsFollowingManage' /* webpackChunkName: "channelsFollowing" */)
);
const ChannelsPage = lazyImport(() => import('page/channels' /* webpackChunkName: "channels" */)); const ChannelsPage = lazyImport(() => import('page/channels' /* webpackChunkName: "channels" */));
const CheckoutPage = lazyImport(() => import('page/checkoutPage' /* webpackChunkName: "checkoutPage" */)); const CheckoutPage = lazyImport(() => import('page/checkoutPage' /* webpackChunkName: "checkoutPage" */));
const CreatorDashboard = lazyImport(() => import('page/creatorDashboard' /* webpackChunkName: "creatorDashboard" */)); const CreatorDashboard = lazyImport(() => import('page/creatorDashboard' /* webpackChunkName: "creatorDashboard" */));
@ -330,6 +333,12 @@ function AppRouter(props: Props) {
path={`/$/${PAGES.CHANNELS_FOLLOWING_DISCOVER}`} path={`/$/${PAGES.CHANNELS_FOLLOWING_DISCOVER}`}
component={ChannelsFollowingDiscoverPage} component={ChannelsFollowingDiscoverPage}
/> />
<PrivateRoute
{...props}
exact
path={`/$/${PAGES.CHANNELS_FOLLOWING_MANAGE}`}
component={ChannelsFollowingManage}
/>
<PrivateRoute {...props} path={`/$/${PAGES.INVITE}`} component={InvitePage} /> <PrivateRoute {...props} path={`/$/${PAGES.INVITE}`} component={InvitePage} />
<PrivateRoute {...props} path={`/$/${PAGES.CHANNEL_NEW}`} component={ChannelNew} /> <PrivateRoute {...props} path={`/$/${PAGES.CHANNEL_NEW}`} component={ChannelNew} />
<PrivateRoute {...props} path={`/$/${PAGES.REPOST_NEW}`} component={RepostNew} /> <PrivateRoute {...props} path={`/$/${PAGES.REPOST_NEW}`} component={RepostNew} />

View file

@ -232,7 +232,6 @@ function SideNavigation(props: Props) {
); );
const [pulseLibrary, setPulseLibrary] = React.useState(false); const [pulseLibrary, setPulseLibrary] = React.useState(false);
const [expandSubscriptions, setExpandSubscriptions] = React.useState(false);
const [expandTags, setExpandTags] = React.useState(false); const [expandTags, setExpandTags] = React.useState(false);
const isPersonalized = !IS_WEB || isAuthenticated; const isPersonalized = !IS_WEB || isAuthenticated;
@ -276,12 +275,7 @@ function SideNavigation(props: Props) {
); );
let displayedSubscriptions = filteredSubscriptions; let displayedSubscriptions = filteredSubscriptions;
if ( if (showSubscriptionSection && !subscriptionFilter && subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT) {
showSubscriptionSection &&
!subscriptionFilter &&
subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT &&
!expandSubscriptions
) {
displayedSubscriptions = subscriptions.slice(0, FOLLOWED_ITEM_INITIAL_LIMIT); displayedSubscriptions = subscriptions.slice(0, FOLLOWED_ITEM_INITIAL_LIMIT);
} }
@ -337,12 +331,12 @@ function SideNavigation(props: Props) {
</div> </div>
</li> </li>
)} )}
{!subscriptionFilter && subscriptions.length > FOLLOWED_ITEM_INITIAL_LIMIT && ( {!subscriptionFilter && (
<Button <Button
key="showMore" key="showMore"
label={expandSubscriptions ? __('Show less') : __('Show more')} label={__('Manage')}
className="navigation-link" className="navigation-link"
onClick={() => setExpandSubscriptions(!expandSubscriptions)} navigate={`/$/${PAGES.CHANNELS_FOLLOWING_MANAGE}`}
/> />
)} )}
</ul> </ul>

View file

@ -63,6 +63,7 @@ exports.DEPRECATED__CHANNELS_FOLLOWING = 'following/channels';
exports.CHANNELS_FOLLOWING = 'following'; exports.CHANNELS_FOLLOWING = 'following';
exports.DEPRECATED__CHANNELS_FOLLOWING_MANAGE = 'following/channels/manage'; exports.DEPRECATED__CHANNELS_FOLLOWING_MANAGE = 'following/channels/manage';
exports.CHANNELS_FOLLOWING_DISCOVER = 'following/discover'; exports.CHANNELS_FOLLOWING_DISCOVER = 'following/discover';
exports.CHANNELS_FOLLOWING_MANAGE = 'following/manage';
exports.WALLET = 'wallet'; exports.WALLET = 'wallet';
exports.CHANNELS = 'channels'; exports.CHANNELS = 'channels';
exports.EMBED = 'embed'; exports.EMBED = 'embed';

View file

@ -69,12 +69,20 @@ function ChannelsFollowingPage(props: Props) {
defaultOrderBy={CS.ORDER_BY_NEW} defaultOrderBy={CS.ORDER_BY_NEW}
channelIds={channelIds} channelIds={channelIds}
meta={ meta={
<Button <>
icon={ICONS.SEARCH} <Button
button="secondary" icon={ICONS.SEARCH}
label={__('Discover Channels')} button="secondary"
navigate={`/$/${PAGES.CHANNELS_FOLLOWING_DISCOVER}`} label={__('Discover Channels')}
/> navigate={`/$/${PAGES.CHANNELS_FOLLOWING_DISCOVER}`}
/>
<Button
icon={ICONS.SETTINGS}
button="secondary"
label={__('Manage')}
navigate={`/$/${PAGES.CHANNELS_FOLLOWING_MANAGE}`}
/>
</>
} }
subSection={ subSection={
<LivestreamSection <LivestreamSection

View file

@ -0,0 +1,9 @@
import { connect } from 'react-redux';
import { selectSubscriptionUris } from 'redux/selectors/subscriptions';
import ChannelsFollowingManage from './view';
const select = (state) => ({
subscribedChannelUris: selectSubscriptionUris(state),
});
export default connect(select)(ChannelsFollowingManage);

View file

@ -0,0 +1,81 @@
// @flow
import React from 'react';
import ClaimList from 'component/claimList';
import ClaimListDiscover from 'component/claimListDiscover';
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 CS from 'constants/claim_search';
import * as ICONS from 'constants/icons';
import { parseURI } from 'util/lbryURI';
function getFilteredUris(uris, filterQuery) {
if (filterQuery) {
const filterQueryLowerCase = filterQuery.toLowerCase();
return uris.filter((uri) => uri.toLowerCase().includes(filterQueryLowerCase));
}
return null;
}
function parseIdFromUri(uri) {
try {
const { channelClaimId } = parseURI(uri);
return channelClaimId;
} catch {
return '';
}
}
// ****************************************************************************
// ChannelsFollowingManage
// ****************************************************************************
type Props = {
subscribedChannelUris: Array<string>,
};
export default function ChannelsFollowingManage(props: Props) {
const { subscribedChannelUris } = props;
const [uris, setUris] = React.useState([]);
const [filterQuery, setFilterQuery] = React.useState('');
const filteredUris = getFilteredUris(uris, filterQuery);
const [channelIds, setChannelIds] = React.useState(null);
React.useEffect(() => {
setUris(subscribedChannelUris);
setChannelIds(subscribedChannelUris.map((uri) => parseIdFromUri(uri)));
// eslint-disable-next-line react-hooks/exhaustive-deps, (lock list on mount so it doesn't shift when unfollow)
}, []);
return (
<Page className="followManage-wrapper" noFooter>
<div className="card__title-section">
<div className="card__title"> {__('Followed Channels')}</div>
</div>
{channelIds === null ? (
<div className="main--empty">
<Spinner />
</div>
) : uris && uris.length === 0 ? (
<Empty padded text="No followed channels." />
) : (
<>
<DebouncedInput icon={ICONS.SEARCH} placeholder={__('Filter')} onChange={setFilterQuery} inline />
{filteredUris && <ClaimList uris={filteredUris} />}
{!filteredUris && channelIds.length && (
<ClaimListDiscover
orderBy={CS.ORDER_BY_NAME_ASC}
claimType={CS.CLAIM_CHANNEL}
claimIds={channelIds}
showHeader={false}
hideFilters
hideAdvancedFilter
/>
)}
</>
)}
</Page>
);
}

View file

@ -653,6 +653,13 @@ img {
} }
} }
.followManage-wrapper {
@extend .discoverPage-wrapper;
.claim-list {
margin-top: var(--spacing-m);
}
}
.uploadPage-wraper { .uploadPage-wraper {
&.card-stack { &.card-stack {
.card:not(:last-of-type) { .card:not(:last-of-type) {