diff --git a/ui/component/channelContent/view.jsx b/ui/component/channelContent/view.jsx index 9f5d8ba74..2ff48cb50 100644 --- a/ui/component/channelContent/view.jsx +++ b/ui/component/channelContent/view.jsx @@ -26,7 +26,7 @@ type Props = { channelIsBlackListed: boolean, defaultPageSize?: number, defaultInfiniteScroll?: Boolean, - claim: ?Claim, + claim: Claim, isAuthenticated: boolean, showMature: boolean, tileLayout: boolean, @@ -135,43 +135,39 @@ function ChannelContent(props: Props) { {!channelIsMine && claimsInChannel > 0 && } - {claim && claimsInChannel > 0 ? ( - } - meta={ - showFilters && ( -
{}} className="wunderbar--inline"> - - - - ) - } - isChannel - channelIsMine={channelIsMine} - empty={empty} - /> - ) : ( -
{__("This channel hasn't published anything yet")}
- )} + } + meta={ + showFilters && ( +
{}} className="wunderbar--inline"> + + + + ) + } + isChannel + channelIsMine={channelIsMine} + empty={empty} + /> ); } diff --git a/ui/component/claimListDiscover/view.jsx b/ui/component/claimListDiscover/view.jsx index d2edc09fd..e76334dd3 100644 --- a/ui/component/claimListDiscover/view.jsx +++ b/ui/component/claimListDiscover/view.jsx @@ -512,6 +512,7 @@ function ClaimListDiscover(props: Props) { liveLivestreamsFirst={liveLivestreamsFirst} livestreamMap={livestreamMap} searchOptions={options} + empty={empty} /> {loading && (
diff --git a/ui/component/claimMenuList/index.js b/ui/component/claimMenuList/index.js index 625ee41a6..5f985dd5c 100644 --- a/ui/component/claimMenuList/index.js +++ b/ui/component/claimMenuList/index.js @@ -8,6 +8,7 @@ import { makeSelectNameForCollectionId, makeSelectCollectionIsMine, COLLECTIONS_CONSTS, + makeSelectEditedCollectionForId, } from 'lbry-redux'; import { makeSelectChannelIsMuted } from 'redux/selectors/blocked'; import { doChannelMute, doChannelUnmute } from 'redux/actions/blocked'; @@ -38,6 +39,7 @@ const select = (state, props) => { collectionName: makeSelectNameForCollectionId(props.collectionId)(state), isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state), hasExperimentalUi: makeSelectUserPropForProp(USER.EXPERIMENTAL_UI)(state), + editedCollection: makeSelectEditedCollectionForId(props.collectionId)(state), }; }; diff --git a/ui/component/claimMenuList/view.jsx b/ui/component/claimMenuList/view.jsx index fd176e0f9..1633ade72 100644 --- a/ui/component/claimMenuList/view.jsx +++ b/ui/component/claimMenuList/view.jsx @@ -49,6 +49,7 @@ type Props = { doChannelSubscribe: (SubscriptionArgs) => void, doChannelUnsubscribe: (SubscriptionArgs) => void, isChannelPage: boolean, + editedCollection: Collection, }; function ClaimMenuList(props: Props) { @@ -79,10 +80,11 @@ function ClaimMenuList(props: Props) { doChannelSubscribe, doChannelUnsubscribe, isChannelPage = false, + editedCollection, } = props; const repostedContent = claim && claim.reposted_claim; const contentClaim = repostedContent || claim; - const incognito = channelUri && !(channelUri.includes('@')); + const incognito = channelUri && !channelUri.includes('@'); const signingChannel = claim && (claim.signing_channel || claim); const permanentUrl = String(channelUri); const isChannel = !incognito && signingChannel === claim; @@ -226,6 +228,17 @@ function ClaimMenuList(props: Props) { {/* COLLECTION OPERATIONS */} {collectionId && collectionName && isCollectionClaim && ( <> + {Boolean(editedCollection) && ( + push(`/$/${PAGES.LIST}/${collectionId}?view=edit`)} + > +
+ + {__('Publish')} +
+
+ )} push(`/$/${PAGES.LIST}/${collectionId}`)}>
@@ -272,23 +285,25 @@ function ClaimMenuList(props: Props) { {!isMyCollection && ( <> - {(!claimIsMine || channelIsBlocked) && channelUri - ? !incognito && !isRepost && ( - <> - -
- - {channelIsBlocked ? __('Unblock Channel') : __('Block Channel')} -
-
+ {(!claimIsMine || channelIsBlocked) && channelUri ? ( + !incognito && + !isRepost && ( + <> + +
+ + {channelIsBlocked ? __('Unblock Channel') : __('Block Channel')} +
+
- -
- - {channelIsMuted ? __('Unmute Channel') : __('Mute Channel')} -
-
- + +
+ + {channelIsMuted ? __('Unmute Channel') : __('Mute Channel')} +
+
+ + ) ) : ( <> {!isChannelPage && !isRepost && ( @@ -310,9 +325,7 @@ function ClaimMenuList(props: Props) { )} )} - {!isRepost && ( -
- )} + {!isRepost &&
} )} diff --git a/ui/component/collectionEdit/view.jsx b/ui/component/collectionEdit/view.jsx index 22c29dde8..43f504ba0 100644 --- a/ui/component/collectionEdit/view.jsx +++ b/ui/component/collectionEdit/view.jsx @@ -235,7 +235,7 @@ function CollectionForm(props: Props) { <>
- + {__('General')} {__('Items')} {__('Credits')} diff --git a/ui/component/collectionMenuList/view.jsx b/ui/component/collectionMenuList/view.jsx index 564eaf9dd..969c88b23 100644 --- a/ui/component/collectionMenuList/view.jsx +++ b/ui/component/collectionMenuList/view.jsx @@ -37,7 +37,16 @@ function ClaimMenuList(props: Props) { push(`/$/${PAGES.LIST}/${collectionId}`)}>
- {__('Edit List')} + {__('View List')} +
+
+ push(`/$/${PAGES.LIST}/${collectionId}?view=edit`)} + > +
+ + {__('Publish List')}
list.id === COLLECTIONS_CONSTS.WATCH_LATER_ID); const favorites = builtinCollectionsList.find((list) => list.id === COLLECTIONS_CONSTS.FAVORITES_ID); const builtin = [watchLater, favorites]; + const [showHelp, setShowHelp] = usePersistedState('livestream-help-seen', true); + + const helpText = ( +
+

{__(`Find some content you want to add to a list`)}

+

{__(`Use the menu to add it to a list`)}

+

{__(`Create as many lists as you wish`)}

+

{__(`Keep the list private, or publish it (transaction fees apply).`)}

+
+ ); + return ( <> {builtin.map((list: Collection) => { @@ -72,12 +85,22 @@ export default function CollectionsListMine(props: Props) { ); })}
-

- {__('Playlists')} -
(Empty)
-

+
+

+ {__('Playlists')} + {!hasCollections &&
(Empty)
} +

+
+ {showHelp && ( + setShowHelp(false)} />} + title={__('Introducing Lists')} + actions={helpText} + /> + )} {Boolean(hasCollections) && ( - <> +
{unpublishedCollectionsList && unpublishedCollectionsList.length > 0 && @@ -88,7 +111,7 @@ export default function CollectionsListMine(props: Props) { publishedList.length > 0 && publishedList.map((key) => )}
- +
)} {!hasCollections && (
diff --git a/ui/page/channel/index.js b/ui/page/channel/index.js index 3b92172e5..9befca133 100644 --- a/ui/page/channel/index.js +++ b/ui/page/channel/index.js @@ -7,6 +7,7 @@ import { selectCurrentChannelPage, makeSelectClaimForUri, makeSelectClaimIsPending, + selectMyUnpublishedCollections, } from 'lbry-redux'; import { selectBlackListedOutpoints, doFetchSubCount, makeSelectSubCountForUri } from 'lbryinc'; import { selectYoutubeChannels } from 'redux/selectors/user'; @@ -30,6 +31,7 @@ const select = (state, props) => ({ youtubeChannels: selectYoutubeChannels(state), blockedChannels: selectModerationBlockList(state), mutedChannels: selectMutedChannels(state), + unpublishedCollections: selectMyUnpublishedCollections(state), }); const perform = (dispatch) => ({ diff --git a/ui/page/channel/view.jsx b/ui/page/channel/view.jsx index e7238c226..78c7d306a 100644 --- a/ui/page/channel/view.jsx +++ b/ui/page/channel/view.jsx @@ -22,6 +22,7 @@ import ClaimSupportButton from 'component/claimSupportButton'; import ChannelStakedIndicator from 'component/channelStakedIndicator'; import ClaimMenuList from 'component/claimMenuList'; import Yrbl from 'component/yrbl'; +import I18nMessage from '../../component/i18nMessage'; export const PAGE_VIEW_QUERY = `view`; const CONTENT_PAGE = 'content'; @@ -52,6 +53,7 @@ type Props = { youtubeChannels: ?Array<{ channel_claim_id: string, sync_status: string, transfer_state: string }>, blockedChannels: Array, mutedChannels: Array, + unpublishedCollections: CollectionGroup, }; function ChannelPage(props: Props) { @@ -70,6 +72,7 @@ function ChannelPage(props: Props) { youtubeChannels, blockedChannels, mutedChannels, + unpublishedCollections, } = props; const { push, @@ -99,6 +102,31 @@ function ChannelPage(props: Props) { return true; } }); + + const hasUnpublishedCollections = unpublishedCollections && Object.keys(unpublishedCollections).length; + + let collectionEmpty; + if (channelIsMine) { + collectionEmpty = hasUnpublishedCollections ? ( +
+ { +

+ , + }} + > + You have unpublished lists! %pick% one and publish it! + +

+ } +
+ ) : ( +
{__('You have no lists! Create one from any playable content.')}
+ ); + } else { + collectionEmpty =
{__('You have unpublished lists')}
; + } let channelIsBlackListed = false; if (claim && blackListedOutpoints) { @@ -269,7 +297,7 @@ function ChannelPage(props: Props) { uri={uri} channelIsBlackListed={channelIsBlackListed} viewHiddenChannels - empty={__('No Content Found')} + empty={
{__('No Content Found')}
} /> @@ -278,7 +306,7 @@ function ChannelPage(props: Props) { uri={uri} channelIsBlackListed={channelIsBlackListed} viewHiddenChannels - empty={__('No Lists Found')} + empty={collectionEmpty} /> @@ -287,7 +315,7 @@ function ChannelPage(props: Props) { uri={uri} channelIsBlackListed={channelIsBlackListed} viewHiddenChannels - empty={__('No Reposts Found')} + empty={
{__('No Reposts Found')}
} />
diff --git a/ui/scss/component/_claim-list.scss b/ui/scss/component/_claim-list.scss index 678848b5f..d5602e264 100644 --- a/ui/scss/component/_claim-list.scss +++ b/ui/scss/component/_claim-list.scss @@ -408,10 +408,15 @@ } } +.claim-grid__header--between { + justify-content: space-between; +} + .claim-grid__title { font-weight: 300; font-size: var(--font-large); margin-right: var(--spacing-m); + display: flex; } .claim-grid__title-span { diff --git a/ui/scss/component/tabs.scss b/ui/scss/component/tabs.scss index dfd66581d..84f3885cd 100644 --- a/ui/scss/component/tabs.scss +++ b/ui/scss/component/tabs.scss @@ -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 { @extend .button--link; margin-right: var(--spacing-l);