extra collection publish buttons, styling

This commit is contained in:
zeppi 2021-06-15 16:06:57 -04:00 committed by jessopb
parent c92bcc945f
commit 761974ca6f
11 changed files with 164 additions and 70 deletions

View file

@ -26,7 +26,7 @@ type Props = {
channelIsBlackListed: boolean, channelIsBlackListed: boolean,
defaultPageSize?: number, defaultPageSize?: number,
defaultInfiniteScroll?: Boolean, defaultInfiniteScroll?: Boolean,
claim: ?Claim, claim: Claim,
isAuthenticated: boolean, isAuthenticated: boolean,
showMature: boolean, showMature: boolean,
tileLayout: boolean, tileLayout: boolean,
@ -135,43 +135,39 @@ function ChannelContent(props: Props) {
{!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />} {!channelIsMine && claimsInChannel > 0 && <HiddenNsfwClaims uri={uri} />}
{claim && claimsInChannel > 0 ? ( <ClaimListDiscover
<ClaimListDiscover defaultFreshness={CS.FRESH_ALL}
defaultFreshness={CS.FRESH_ALL} showHiddenByUser={viewHiddenChannels}
showHiddenByUser={viewHiddenChannels} forceShowReposts
forceShowReposts hideFilters={!showFilters}
hideFilters={!showFilters} hideAdvancedFilter={!showFilters}
hideAdvancedFilter={!showFilters} tileLayout={tileLayout}
tileLayout={tileLayout} uris={searchResults}
uris={searchResults} channelIds={[claim.claim_id]}
channelIds={[claim.claim_id]} claimType={claimType}
claimType={claimType} feeAmount={CS.FEE_AMOUNT_ANY}
feeAmount={CS.FEE_AMOUNT_ANY} defaultOrderBy={CS.ORDER_BY_NEW}
defaultOrderBy={CS.ORDER_BY_NEW} pageSize={defaultPageSize}
pageSize={defaultPageSize} infiniteScroll={defaultInfiniteScroll}
infiniteScroll={defaultInfiniteScroll} injectedItem={SHOW_ADS && !isAuthenticated && IS_WEB && <Ads type="video" />}
injectedItem={SHOW_ADS && !isAuthenticated && IS_WEB && <Ads type="video" />} meta={
meta={ showFilters && (
showFilters && ( <Form onSubmit={() => {}} className="wunderbar--inline">
<Form onSubmit={() => {}} className="wunderbar--inline"> <Icon icon={ICONS.SEARCH} />
<Icon icon={ICONS.SEARCH} /> <FormField
<FormField className="wunderbar__input--inline"
className="wunderbar__input--inline" value={searchQuery}
value={searchQuery} onChange={handleInputChange}
onChange={handleInputChange} type="text"
type="text" placeholder={__('Search')}
placeholder={__('Search')} />
/> </Form>
</Form> )
) }
} isChannel
isChannel channelIsMine={channelIsMine}
channelIsMine={channelIsMine} empty={empty}
empty={empty} />
/>
) : (
<section className="main--empty">{__("This channel hasn't published anything yet")}</section>
)}
</Fragment> </Fragment>
); );
} }

View file

@ -512,6 +512,7 @@ function ClaimListDiscover(props: Props) {
liveLivestreamsFirst={liveLivestreamsFirst} liveLivestreamsFirst={liveLivestreamsFirst}
livestreamMap={livestreamMap} livestreamMap={livestreamMap}
searchOptions={options} searchOptions={options}
empty={empty}
/> />
{loading && ( {loading && (
<div className="claim-grid"> <div className="claim-grid">

View file

@ -8,6 +8,7 @@ import {
makeSelectNameForCollectionId, makeSelectNameForCollectionId,
makeSelectCollectionIsMine, makeSelectCollectionIsMine,
COLLECTIONS_CONSTS, COLLECTIONS_CONSTS,
makeSelectEditedCollectionForId,
} from 'lbry-redux'; } from 'lbry-redux';
import { makeSelectChannelIsMuted } from 'redux/selectors/blocked'; import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
import { doChannelMute, doChannelUnmute } from 'redux/actions/blocked'; import { doChannelMute, doChannelUnmute } from 'redux/actions/blocked';
@ -38,6 +39,7 @@ const select = (state, props) => {
collectionName: makeSelectNameForCollectionId(props.collectionId)(state), collectionName: makeSelectNameForCollectionId(props.collectionId)(state),
isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state), isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state),
hasExperimentalUi: makeSelectUserPropForProp(USER.EXPERIMENTAL_UI)(state), hasExperimentalUi: makeSelectUserPropForProp(USER.EXPERIMENTAL_UI)(state),
editedCollection: makeSelectEditedCollectionForId(props.collectionId)(state),
}; };
}; };

View file

@ -49,6 +49,7 @@ type Props = {
doChannelSubscribe: (SubscriptionArgs) => void, doChannelSubscribe: (SubscriptionArgs) => void,
doChannelUnsubscribe: (SubscriptionArgs) => void, doChannelUnsubscribe: (SubscriptionArgs) => void,
isChannelPage: boolean, isChannelPage: boolean,
editedCollection: Collection,
}; };
function ClaimMenuList(props: Props) { function ClaimMenuList(props: Props) {
@ -79,10 +80,11 @@ function ClaimMenuList(props: Props) {
doChannelSubscribe, doChannelSubscribe,
doChannelUnsubscribe, doChannelUnsubscribe,
isChannelPage = false, isChannelPage = false,
editedCollection,
} = props; } = props;
const repostedContent = claim && claim.reposted_claim; const repostedContent = claim && claim.reposted_claim;
const contentClaim = repostedContent || claim; const contentClaim = repostedContent || claim;
const incognito = channelUri && !(channelUri.includes('@')); const incognito = channelUri && !channelUri.includes('@');
const signingChannel = claim && (claim.signing_channel || claim); const signingChannel = claim && (claim.signing_channel || claim);
const permanentUrl = String(channelUri); const permanentUrl = String(channelUri);
const isChannel = !incognito && signingChannel === claim; const isChannel = !incognito && signingChannel === claim;
@ -226,6 +228,17 @@ function ClaimMenuList(props: Props) {
{/* COLLECTION OPERATIONS */} {/* COLLECTION OPERATIONS */}
{collectionId && collectionName && isCollectionClaim && ( {collectionId && collectionName && isCollectionClaim && (
<> <>
{Boolean(editedCollection) && (
<MenuItem
className="comment__menu-option"
onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}?view=edit`)}
>
<div className="menu__link">
<Icon aria-hidden iconColor={'red'} icon={ICONS.PUBLISH} />
{__('Publish')}
</div>
</MenuItem>
)}
<MenuItem className="comment__menu-option" onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}`)}> <MenuItem className="comment__menu-option" onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}`)}>
<div className="menu__link"> <div className="menu__link">
<Icon aria-hidden icon={ICONS.VIEW} /> <Icon aria-hidden icon={ICONS.VIEW} />
@ -272,23 +285,25 @@ function ClaimMenuList(props: Props) {
{!isMyCollection && ( {!isMyCollection && (
<> <>
{(!claimIsMine || channelIsBlocked) && channelUri {(!claimIsMine || channelIsBlocked) && channelUri ? (
? !incognito && !isRepost && ( !incognito &&
<> !isRepost && (
<MenuItem className="comment__menu-option" onSelect={handleToggleBlock}> <>
<div className="menu__link"> <MenuItem className="comment__menu-option" onSelect={handleToggleBlock}>
<Icon aria-hidden icon={ICONS.BLOCK} /> <div className="menu__link">
{channelIsBlocked ? __('Unblock Channel') : __('Block Channel')} <Icon aria-hidden icon={ICONS.BLOCK} />
</div> {channelIsBlocked ? __('Unblock Channel') : __('Block Channel')}
</MenuItem> </div>
</MenuItem>
<MenuItem className="comment__menu-option" onSelect={handleToggleMute}> <MenuItem className="comment__menu-option" onSelect={handleToggleMute}>
<div className="menu__link"> <div className="menu__link">
<Icon aria-hidden icon={ICONS.MUTE} /> <Icon aria-hidden icon={ICONS.MUTE} />
{channelIsMuted ? __('Unmute Channel') : __('Mute Channel')} {channelIsMuted ? __('Unmute Channel') : __('Mute Channel')}
</div> </div>
</MenuItem> </MenuItem>
</> </>
)
) : ( ) : (
<> <>
{!isChannelPage && !isRepost && ( {!isChannelPage && !isRepost && (
@ -310,9 +325,7 @@ function ClaimMenuList(props: Props) {
)} )}
</> </>
)} )}
{!isRepost && ( {!isRepost && <hr className="menu__separator" />}
<hr className="menu__separator" />
)}
</> </>
)} )}

View file

@ -235,7 +235,7 @@ function CollectionForm(props: Props) {
<> <>
<div className={classnames('main--contained', { 'card--disabled': disabled })}> <div className={classnames('main--contained', { 'card--disabled': disabled })}>
<Tabs> <Tabs>
<TabList className="tabs__list--channel-page"> <TabList className="tabs__list--collection-edit-page">
<Tab>{__('General')}</Tab> <Tab>{__('General')}</Tab>
<Tab>{__('Items')}</Tab> <Tab>{__('Items')}</Tab>
<Tab>{__('Credits')}</Tab> <Tab>{__('Credits')}</Tab>

View file

@ -37,7 +37,16 @@ function ClaimMenuList(props: Props) {
<MenuItem className="comment__menu-option" onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}`)}> <MenuItem className="comment__menu-option" onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}`)}>
<div className="menu__link"> <div className="menu__link">
<Icon aria-hidden icon={ICONS.VIEW} /> <Icon aria-hidden icon={ICONS.VIEW} />
{__('Edit List')} {__('View List')}
</div>
</MenuItem>
<MenuItem
className="comment__menu-option"
onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}?view=edit`)}
>
<div className="menu__link">
<Icon aria-hidden icon={ICONS.PUBLISH} />
{__('Publish List')}
</div> </div>
</MenuItem> </MenuItem>
<MenuItem <MenuItem

View file

@ -7,7 +7,9 @@ import { COLLECTIONS_CONSTS } from 'lbry-redux';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import Yrbl from '../yrbl'; import Yrbl from 'component/yrbl';
import usePersistedState from 'effects/use-persisted-state';
import Card from 'component/common/card';
type Props = { type Props = {
builtinCollections: CollectionGroup, builtinCollections: CollectionGroup,
@ -33,6 +35,17 @@ export default function CollectionsListMine(props: Props) {
const watchLater = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.WATCH_LATER_ID); const watchLater = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.WATCH_LATER_ID);
const favorites = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.FAVORITES_ID); const favorites = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.FAVORITES_ID);
const builtin = [watchLater, favorites]; const builtin = [watchLater, favorites];
const [showHelp, setShowHelp] = usePersistedState('livestream-help-seen', true);
const helpText = (
<div className="section__subtitle">
<p>{__(`Find some content you want to add to a list`)}</p>
<p>{__(`Use the menu to add it to a list`)}</p>
<p>{__(`Create as many lists as you wish`)}</p>
<p>{__(`Keep the list private, or publish it (transaction fees apply).`)}</p>
</div>
);
return ( return (
<> <>
{builtin.map((list: Collection) => { {builtin.map((list: Collection) => {
@ -72,12 +85,22 @@ export default function CollectionsListMine(props: Props) {
); );
})} })}
<div className="claim-grid__wrapper"> <div className="claim-grid__wrapper">
<h1 className="claim-grid__header claim-grid__title"> <div className="claim-grid__header claim-grid__header--between section">
{__('Playlists')} <h1 className="claim-grid__title">
<div className="claim-grid__title--empty">(Empty)</div> {__('Playlists')}
</h1> {!hasCollections && <div className="claim-grid__title--empty">(Empty)</div>}
</h1>
<Button button="link" onClick={() => setShowHelp(!showHelp)} label={__('How does this work?')} />
</div>
{showHelp && (
<Card
titleActions={<Button button="close" icon={ICONS.REMOVE} onClick={() => setShowHelp(false)} />}
title={__('Introducing Lists')}
actions={helpText}
/>
)}
{Boolean(hasCollections) && ( {Boolean(hasCollections) && (
<> <div className="section">
<div className="claim-grid"> <div className="claim-grid">
{unpublishedCollectionsList && {unpublishedCollectionsList &&
unpublishedCollectionsList.length > 0 && unpublishedCollectionsList.length > 0 &&
@ -88,7 +111,7 @@ export default function CollectionsListMine(props: Props) {
publishedList.length > 0 && publishedList.length > 0 &&
publishedList.map((key) => <CollectionPreviewTile tileLayout collectionId={key} key={key} />)} publishedList.map((key) => <CollectionPreviewTile tileLayout collectionId={key} key={key} />)}
</div> </div>
</> </div>
)} )}
{!hasCollections && ( {!hasCollections && (
<div className="main--empty"> <div className="main--empty">

View file

@ -7,6 +7,7 @@ import {
selectCurrentChannelPage, selectCurrentChannelPage,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectClaimIsPending, makeSelectClaimIsPending,
selectMyUnpublishedCollections,
} from 'lbry-redux'; } from 'lbry-redux';
import { selectBlackListedOutpoints, doFetchSubCount, makeSelectSubCountForUri } from 'lbryinc'; import { selectBlackListedOutpoints, doFetchSubCount, makeSelectSubCountForUri } from 'lbryinc';
import { selectYoutubeChannels } from 'redux/selectors/user'; import { selectYoutubeChannels } from 'redux/selectors/user';
@ -30,6 +31,7 @@ const select = (state, props) => ({
youtubeChannels: selectYoutubeChannels(state), youtubeChannels: selectYoutubeChannels(state),
blockedChannels: selectModerationBlockList(state), blockedChannels: selectModerationBlockList(state),
mutedChannels: selectMutedChannels(state), mutedChannels: selectMutedChannels(state),
unpublishedCollections: selectMyUnpublishedCollections(state),
}); });
const perform = (dispatch) => ({ const perform = (dispatch) => ({

View file

@ -22,6 +22,7 @@ import ClaimSupportButton from 'component/claimSupportButton';
import ChannelStakedIndicator from 'component/channelStakedIndicator'; import ChannelStakedIndicator from 'component/channelStakedIndicator';
import ClaimMenuList from 'component/claimMenuList'; import ClaimMenuList from 'component/claimMenuList';
import Yrbl from 'component/yrbl'; import Yrbl from 'component/yrbl';
import I18nMessage from '../../component/i18nMessage';
export const PAGE_VIEW_QUERY = `view`; export const PAGE_VIEW_QUERY = `view`;
const CONTENT_PAGE = 'content'; const CONTENT_PAGE = 'content';
@ -52,6 +53,7 @@ type Props = {
youtubeChannels: ?Array<{ channel_claim_id: string, sync_status: string, transfer_state: string }>, youtubeChannels: ?Array<{ channel_claim_id: string, sync_status: string, transfer_state: string }>,
blockedChannels: Array<string>, blockedChannels: Array<string>,
mutedChannels: Array<string>, mutedChannels: Array<string>,
unpublishedCollections: CollectionGroup,
}; };
function ChannelPage(props: Props) { function ChannelPage(props: Props) {
@ -70,6 +72,7 @@ function ChannelPage(props: Props) {
youtubeChannels, youtubeChannels,
blockedChannels, blockedChannels,
mutedChannels, mutedChannels,
unpublishedCollections,
} = props; } = props;
const { const {
push, push,
@ -99,6 +102,31 @@ function ChannelPage(props: Props) {
return true; return true;
} }
}); });
const hasUnpublishedCollections = unpublishedCollections && Object.keys(unpublishedCollections).length;
let collectionEmpty;
if (channelIsMine) {
collectionEmpty = hasUnpublishedCollections ? (
<section className="main--empty">
{
<p>
<I18nMessage
tokens={{
pick: <Button button="link" navigate={`/$/${PAGES.LISTS}`} label={__('Pick')} />,
}}
>
You have unpublished lists! %pick% one and publish it!
</I18nMessage>
</p>
}
</section>
) : (
<section className="main--empty">{__('You have no lists! Create one from any playable content.')}</section>
);
} else {
collectionEmpty = <section className="main--empty">{__('You have unpublished lists')}</section>;
}
let channelIsBlackListed = false; let channelIsBlackListed = false;
if (claim && blackListedOutpoints) { if (claim && blackListedOutpoints) {
@ -269,7 +297,7 @@ function ChannelPage(props: Props) {
uri={uri} uri={uri}
channelIsBlackListed={channelIsBlackListed} channelIsBlackListed={channelIsBlackListed}
viewHiddenChannels viewHiddenChannels
empty={__('No Content Found')} empty={<section className="main--empty">{__('No Content Found')}</section>}
/> />
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
@ -278,7 +306,7 @@ function ChannelPage(props: Props) {
uri={uri} uri={uri}
channelIsBlackListed={channelIsBlackListed} channelIsBlackListed={channelIsBlackListed}
viewHiddenChannels viewHiddenChannels
empty={__('No Lists Found')} empty={collectionEmpty}
/> />
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
@ -287,7 +315,7 @@ function ChannelPage(props: Props) {
uri={uri} uri={uri}
channelIsBlackListed={channelIsBlackListed} channelIsBlackListed={channelIsBlackListed}
viewHiddenChannels viewHiddenChannels
empty={__('No Reposts Found')} empty={<section className="main--empty">{__('No Reposts Found')}</section>}
/> />
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>

View file

@ -408,10 +408,15 @@
} }
} }
.claim-grid__header--between {
justify-content: space-between;
}
.claim-grid__title { .claim-grid__title {
font-weight: 300; font-weight: 300;
font-size: var(--font-large); font-size: var(--font-large);
margin-right: var(--spacing-m); margin-right: var(--spacing-m);
display: flex;
} }
.claim-grid__title-span { .claim-grid__title-span {

View file

@ -29,6 +29,21 @@
} }
} }
.tabs__list--collection-edit-page {
padding-right: var(--spacing-m);
margin-bottom: var(--spacing-l);
height: 4rem;
border-bottom-left-radius: var(--card-radius);
border-bottom-right-radius: var(--card-radius);
border-top-left-radius: var(--card-radius);
border-top-right-radius: var(--card-radius);
border: 1px solid var(--color-border);
@media (max-width: $breakpoint-small) {
padding-left: var(--spacing-m);
}
}
.tab { .tab {
@extend .button--link; @extend .button--link;
margin-right: var(--spacing-l); margin-right: var(--spacing-l);