Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
|
bd1b2df5b7 | ||
|
34913e33fc | ||
|
975b6a3b01 |
12 changed files with 280 additions and 87 deletions
|
@ -2,22 +2,44 @@ import { connect } from 'react-redux';
|
||||||
import ClaimCollectionAdd from './view';
|
import ClaimCollectionAdd from './view';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import {
|
import {
|
||||||
|
doResolveUris,
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
doLocalCollectionCreate,
|
doLocalCollectionCreate,
|
||||||
selectBuiltinCollections,
|
selectBuiltinCollections,
|
||||||
selectMyPublishedCollections,
|
selectMyPublishedCollections,
|
||||||
selectMyUnpublishedCollections,
|
selectMyUnpublishedCollections,
|
||||||
|
doCollectionEdit,
|
||||||
|
makeSelectUrlsForCollectionId,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
|
|
||||||
const select = (state, props) => ({
|
const select = (state, props) => {
|
||||||
claim: makeSelectClaimForUri(props.uri)(state),
|
const collectionId = props.collectionId;
|
||||||
builtin: selectBuiltinCollections(state),
|
let items;
|
||||||
published: selectMyPublishedCollections(state),
|
let itemsClaims = [];
|
||||||
unpublished: selectMyUnpublishedCollections(state),
|
|
||||||
});
|
if (collectionId) {
|
||||||
|
items = makeSelectUrlsForCollectionId(collectionId)(state);
|
||||||
|
if (items) {
|
||||||
|
items.map((uri) => {
|
||||||
|
itemsClaims.push(makeSelectClaimForUri(uri)(state));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
claim: makeSelectClaimForUri(props.uri)(state),
|
||||||
|
builtin: selectBuiltinCollections(state),
|
||||||
|
published: selectMyPublishedCollections(state),
|
||||||
|
unpublished: selectMyUnpublishedCollections(state),
|
||||||
|
items,
|
||||||
|
itemsClaims,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
addCollection: (name, items, type) => dispatch(doLocalCollectionCreate(name, items, type)),
|
addCollection: (name, items, type) => dispatch(doLocalCollectionCreate(name, items, type)),
|
||||||
|
editCollection: (id, params) => dispatch(doCollectionEdit(id, params)),
|
||||||
|
doResolveUris: (uris) => dispatch(doResolveUris(uris)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default withRouter(connect(select, perform)(ClaimCollectionAdd));
|
export default withRouter(connect(select, perform)(ClaimCollectionAdd));
|
||||||
|
|
|
@ -13,16 +13,33 @@ type Props = {
|
||||||
published: any,
|
published: any,
|
||||||
unpublished: any,
|
unpublished: any,
|
||||||
addCollection: (string, Array<string>, string) => void,
|
addCollection: (string, Array<string>, string) => void,
|
||||||
|
editCollection: (string, {}) => void,
|
||||||
closeModal: () => void,
|
closeModal: () => void,
|
||||||
uri: string,
|
uri: string,
|
||||||
|
collectionId: string,
|
||||||
|
doResolveUris: (Array<string>) => void,
|
||||||
|
items: Array<string>,
|
||||||
|
itemsClaims: Array<string>,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClaimCollectionAdd = (props: Props) => {
|
const ClaimCollectionAdd = (props: Props) => {
|
||||||
const { builtin, published, unpublished, addCollection, claim, closeModal, uri } = props;
|
const {
|
||||||
|
builtin,
|
||||||
|
published,
|
||||||
|
unpublished,
|
||||||
|
addCollection,
|
||||||
|
editCollection,
|
||||||
|
claim,
|
||||||
|
closeModal,
|
||||||
|
uri,
|
||||||
|
doResolveUris,
|
||||||
|
items,
|
||||||
|
itemsClaims,
|
||||||
|
} = props;
|
||||||
const buttonref: ElementRef<any> = React.useRef();
|
const buttonref: ElementRef<any> = React.useRef();
|
||||||
const permanentUrl = claim && claim.permanent_url;
|
const permanentUrl = claim && claim.permanent_url;
|
||||||
const isChannel = claim && claim.value_type === 'channel';
|
const isChannel = claim && claim.value_type === 'channel';
|
||||||
|
const [selectedCollections, setSelectedCollections] = React.useState([]);
|
||||||
const [addNewCollection, setAddNewCollection] = React.useState(false);
|
const [addNewCollection, setAddNewCollection] = React.useState(false);
|
||||||
const [newCollectionName, setNewCollectionName] = React.useState('');
|
const [newCollectionName, setNewCollectionName] = React.useState('');
|
||||||
|
|
||||||
|
@ -34,17 +51,32 @@ const ClaimCollectionAdd = (props: Props) => {
|
||||||
// claim.value.stream_type &&
|
// claim.value.stream_type &&
|
||||||
// (claim.value.stream_type === 'audio' || claim.value.stream_type === 'video');
|
// (claim.value.stream_type === 'audio' || claim.value.stream_type === 'video');
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (items) {
|
||||||
|
doResolveUris(items);
|
||||||
|
}
|
||||||
|
}, [doResolveUris, items]);
|
||||||
|
|
||||||
function handleNameInput(e) {
|
function handleNameInput(e) {
|
||||||
const { value } = e.target;
|
const { value } = e.target;
|
||||||
setNewCollectionName(value);
|
setNewCollectionName(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAddCollection() {
|
function handleAddCollection() {
|
||||||
addCollection(newCollectionName, [permanentUrl], isChannel ? 'collection' : 'playlist');
|
addCollection(newCollectionName, items || [permanentUrl], isChannel ? 'collection' : 'playlist');
|
||||||
|
if (items) setSelectedCollections([...selectedCollections, newCollectionName]);
|
||||||
setNewCollectionName('');
|
setNewCollectionName('');
|
||||||
setAddNewCollection(false);
|
setAddNewCollection(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleEditCollection() {
|
||||||
|
if (selectedCollections) {
|
||||||
|
selectedCollections.map((id) => {
|
||||||
|
editCollection(id, { claims: itemsClaims, remove: false });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function altEnterListener(e: SyntheticKeyboardEvent<*>) {
|
function altEnterListener(e: SyntheticKeyboardEvent<*>) {
|
||||||
const KEYCODE_ENTER = 13;
|
const KEYCODE_ENTER = 13;
|
||||||
if (e.keyCode === KEYCODE_ENTER) {
|
if (e.keyCode === KEYCODE_ENTER) {
|
||||||
|
@ -71,7 +103,7 @@ const ClaimCollectionAdd = (props: Props) => {
|
||||||
title={__('Add To...')}
|
title={__('Add To...')}
|
||||||
actions={
|
actions={
|
||||||
<div className="card__body">
|
<div className="card__body">
|
||||||
{uri && (
|
{(uri || items) && (
|
||||||
<fieldset-section>
|
<fieldset-section>
|
||||||
<div className={'card__body-scrollable'}>
|
<div className={'card__body-scrollable'}>
|
||||||
{(Object.values(builtin): any)
|
{(Object.values(builtin): any)
|
||||||
|
@ -86,6 +118,9 @@ const ClaimCollectionAdd = (props: Props) => {
|
||||||
uri={permanentUrl}
|
uri={permanentUrl}
|
||||||
key={id}
|
key={id}
|
||||||
category={'builtin'}
|
category={'builtin'}
|
||||||
|
setSelectedCollections={setSelectedCollections}
|
||||||
|
selectedCollections={selectedCollections}
|
||||||
|
items={items}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -102,6 +137,9 @@ const ClaimCollectionAdd = (props: Props) => {
|
||||||
uri={permanentUrl}
|
uri={permanentUrl}
|
||||||
key={id}
|
key={id}
|
||||||
category={'unpublished'}
|
category={'unpublished'}
|
||||||
|
setSelectedCollections={setSelectedCollections}
|
||||||
|
selectedCollections={selectedCollections}
|
||||||
|
items={items}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -116,6 +154,9 @@ const ClaimCollectionAdd = (props: Props) => {
|
||||||
uri={permanentUrl}
|
uri={permanentUrl}
|
||||||
key={id}
|
key={id}
|
||||||
category={'published'}
|
category={'published'}
|
||||||
|
setSelectedCollections={setSelectedCollections}
|
||||||
|
selectedCollections={selectedCollections}
|
||||||
|
items={items}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -158,7 +199,17 @@ const ClaimCollectionAdd = (props: Props) => {
|
||||||
)}
|
)}
|
||||||
</fieldset-section>
|
</fieldset-section>
|
||||||
<div className="card__actions">
|
<div className="card__actions">
|
||||||
<Button button="secondary" label={__('Done')} disabled={addNewCollection} onClick={closeModal} />
|
<Button
|
||||||
|
button="secondary"
|
||||||
|
label={__('Done')}
|
||||||
|
disabled={addNewCollection}
|
||||||
|
onClick={() => {
|
||||||
|
if (items) {
|
||||||
|
handleEditCollection();
|
||||||
|
}
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
COLLECTIONS_CONSTS,
|
COLLECTIONS_CONSTS,
|
||||||
makeSelectEditedCollectionForId,
|
makeSelectEditedCollectionForId,
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
|
doFetchItemsInCollection,
|
||||||
|
makeSelectUrlsForCollectionId,
|
||||||
} 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';
|
||||||
|
@ -33,6 +35,8 @@ import fs from 'fs';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const claim = makeSelectClaimForUri(props.uri, false)(state);
|
const claim = makeSelectClaimForUri(props.uri, false)(state);
|
||||||
|
const collectionId = props.collectionId;
|
||||||
|
const resolvedList = makeSelectUrlsForCollectionId(collectionId)(state);
|
||||||
const repostedClaim = claim && claim.reposted_claim;
|
const repostedClaim = claim && claim.reposted_claim;
|
||||||
const contentClaim = repostedClaim || claim;
|
const contentClaim = repostedClaim || claim;
|
||||||
const contentSigningChannel = contentClaim && contentClaim.signing_channel;
|
const contentSigningChannel = contentClaim && contentClaim.signing_channel;
|
||||||
|
@ -60,10 +64,11 @@ const select = (state, props) => {
|
||||||
isSubscribed: makeSelectIsSubscribed(contentChannelUri, true)(state),
|
isSubscribed: makeSelectIsSubscribed(contentChannelUri, true)(state),
|
||||||
channelIsAdminBlocked: makeSelectChannelIsAdminBlocked(props.uri)(state),
|
channelIsAdminBlocked: makeSelectChannelIsAdminBlocked(props.uri)(state),
|
||||||
isAdmin: selectHasAdminChannel(state),
|
isAdmin: selectHasAdminChannel(state),
|
||||||
claimInCollection: makeSelectCollectionForIdHasClaimUrl(props.collectionId, contentPermanentUri)(state),
|
claimInCollection: makeSelectCollectionForIdHasClaimUrl(collectionId, contentPermanentUri)(state),
|
||||||
isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state),
|
isMyCollection: makeSelectCollectionIsMine(collectionId)(state),
|
||||||
editedCollection: makeSelectEditedCollectionForId(props.collectionId)(state),
|
editedCollection: makeSelectEditedCollectionForId(collectionId)(state),
|
||||||
isAuthenticated: Boolean(selectUserVerifiedEmail(state)),
|
isAuthenticated: Boolean(selectUserVerifiedEmail(state)),
|
||||||
|
resolvedList,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,6 +95,7 @@ const perform = (dispatch) => ({
|
||||||
doChannelSubscribe: (subscription) => dispatch(doChannelSubscribe(subscription)),
|
doChannelSubscribe: (subscription) => dispatch(doChannelSubscribe(subscription)),
|
||||||
doChannelUnsubscribe: (subscription) => dispatch(doChannelUnsubscribe(subscription)),
|
doChannelUnsubscribe: (subscription) => dispatch(doChannelUnsubscribe(subscription)),
|
||||||
doCollectionEdit: (collection, props) => dispatch(doCollectionEdit(collection, props)),
|
doCollectionEdit: (collection, props) => dispatch(doCollectionEdit(collection, props)),
|
||||||
|
fetchCollectionItems: (collectionId) => dispatch(doFetchItemsInCollection({ collectionId })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(ClaimPreview);
|
export default connect(select, perform)(ClaimPreview);
|
||||||
|
|
|
@ -56,6 +56,8 @@ type Props = {
|
||||||
isChannelPage: boolean,
|
isChannelPage: boolean,
|
||||||
editedCollection: Collection,
|
editedCollection: Collection,
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
|
fetchCollectionItems: (string) => void,
|
||||||
|
resolvedList: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ClaimMenuList(props: Props) {
|
function ClaimMenuList(props: Props) {
|
||||||
|
@ -93,6 +95,8 @@ function ClaimMenuList(props: Props) {
|
||||||
isChannelPage = false,
|
isChannelPage = false,
|
||||||
editedCollection,
|
editedCollection,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
|
fetchCollectionItems,
|
||||||
|
resolvedList,
|
||||||
} = props;
|
} = props;
|
||||||
const incognitoClaim = contentChannelUri && !contentChannelUri.includes('@');
|
const incognitoClaim = contentChannelUri && !contentChannelUri.includes('@');
|
||||||
const isChannel = !incognitoClaim && !contentSigningChannel;
|
const isChannel = !incognitoClaim && !contentSigningChannel;
|
||||||
|
@ -106,6 +110,12 @@ function ClaimMenuList(props: Props) {
|
||||||
? __('Unfollow')
|
? __('Unfollow')
|
||||||
: __('Follow');
|
: __('Follow');
|
||||||
|
|
||||||
|
const fetchItems = React.useCallback(() => {
|
||||||
|
if (collectionId) {
|
||||||
|
fetchCollectionItems(collectionId);
|
||||||
|
}
|
||||||
|
}, [collectionId, fetchCollectionItems]);
|
||||||
|
|
||||||
const { push, replace } = useHistory();
|
const { push, replace } = useHistory();
|
||||||
if (!claim) {
|
if (!claim) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -251,6 +261,18 @@ function ClaimMenuList(props: Props) {
|
||||||
{__('View List')}
|
{__('View List')}
|
||||||
</div>
|
</div>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
className="comment__menu-option"
|
||||||
|
onSelect={() => {
|
||||||
|
fetchItems();
|
||||||
|
openModal(MODALS.COLLECTION_ADD, { collectionId });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="menu__link">
|
||||||
|
<Icon aria-hidden icon={ICONS.COPY} />
|
||||||
|
{__('Copy List')}
|
||||||
|
</div>
|
||||||
|
</MenuItem>
|
||||||
{isMyCollection && (
|
{isMyCollection && (
|
||||||
<>
|
<>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { ENABLE_FILE_REACTIONS } from 'config';
|
||||||
type Props = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
claim: StreamClaim,
|
claim: StreamClaim,
|
||||||
openModal: (id: string, { uri: string, claimIsMine?: boolean, isSupport?: boolean }) => void,
|
openModal: (id: string, {}) => void,
|
||||||
myChannels: ?Array<ChannelClaim>,
|
myChannels: ?Array<ChannelClaim>,
|
||||||
doToast: ({ message: string }) => void,
|
doToast: ({ message: string }) => void,
|
||||||
claimIsPending: boolean,
|
claimIsPending: boolean,
|
||||||
|
@ -24,6 +24,7 @@ type Props = {
|
||||||
showInfo: boolean,
|
showInfo: boolean,
|
||||||
setShowInfo: (boolean) => void,
|
setShowInfo: (boolean) => void,
|
||||||
collectionHasEdits: boolean,
|
collectionHasEdits: boolean,
|
||||||
|
isBuiltin: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function CollectionActions(props: Props) {
|
function CollectionActions(props: Props) {
|
||||||
|
@ -37,6 +38,7 @@ function CollectionActions(props: Props) {
|
||||||
showInfo,
|
showInfo,
|
||||||
setShowInfo,
|
setShowInfo,
|
||||||
collectionHasEdits,
|
collectionHasEdits,
|
||||||
|
isBuiltin,
|
||||||
} = props;
|
} = props;
|
||||||
const { push } = useHistory();
|
const { push } = useHistory();
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
@ -44,54 +46,66 @@ function CollectionActions(props: Props) {
|
||||||
const webShareable = true; // collections have cost?
|
const webShareable = true; // collections have cost?
|
||||||
const lhsSection = (
|
const lhsSection = (
|
||||||
<>
|
<>
|
||||||
{ENABLE_FILE_REACTIONS && uri && <FileReactions uri={uri} />}
|
{!isBuiltin && (
|
||||||
{uri && <ClaimSupportButton uri={uri} fileAction />}
|
<>
|
||||||
{/* TODO Add ClaimRepostButton component */}
|
{ENABLE_FILE_REACTIONS && uri && <FileReactions uri={uri} />}
|
||||||
{uri && (
|
{uri && <ClaimSupportButton uri={uri} fileAction />}
|
||||||
<Button
|
{/* TODO Add ClaimRepostButton component */}
|
||||||
className="button--file-action"
|
{uri && (
|
||||||
icon={ICONS.SHARE}
|
<Button
|
||||||
label={__('Share')}
|
className="button--file-action"
|
||||||
title={__('Share')}
|
icon={ICONS.SHARE}
|
||||||
onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, webShareable })}
|
label={__('Share')}
|
||||||
/>
|
title={__('Share')}
|
||||||
|
onClick={() => openModal(MODALS.SOCIAL_SHARE, { uri, webShareable })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const rhsSection = (
|
const rhsSection = (
|
||||||
<>
|
<>
|
||||||
{isMyCollection && (
|
{!isBuiltin &&
|
||||||
<Button
|
(isMyCollection ? (
|
||||||
title={uri ? __('Update') : __('Publish')}
|
<>
|
||||||
label={uri ? __('Update') : __('Publish')}
|
<Button
|
||||||
className={classnames('button--file-action')}
|
title={uri ? __('Update') : __('Publish')}
|
||||||
onClick={() => push(`?${PAGE_VIEW_QUERY}=${EDIT_PAGE}`)}
|
label={uri ? __('Update') : __('Publish')}
|
||||||
icon={ICONS.PUBLISH}
|
className={classnames('button--file-action')}
|
||||||
iconColor={collectionHasEdits && 'red'}
|
onClick={() => push(`?${PAGE_VIEW_QUERY}=${EDIT_PAGE}`)}
|
||||||
iconSize={18}
|
icon={ICONS.PUBLISH}
|
||||||
disabled={claimIsPending}
|
iconColor={collectionHasEdits && 'red'}
|
||||||
/>
|
iconSize={18}
|
||||||
)}
|
disabled={claimIsPending}
|
||||||
{isMyCollection && (
|
/>
|
||||||
<Button
|
<Button
|
||||||
className={classnames('button--file-action')}
|
className={classnames('button--file-action')}
|
||||||
title={__('Delete List')}
|
title={__('Delete List')}
|
||||||
onClick={() => openModal(MODALS.COLLECTION_DELETE, { uri, collectionId, redirect: `/$/${PAGES.LISTS}` })}
|
onClick={() => openModal(MODALS.COLLECTION_DELETE, { uri, collectionId, redirect: `/$/${PAGES.LISTS}` })}
|
||||||
icon={ICONS.DELETE}
|
icon={ICONS.DELETE}
|
||||||
iconSize={18}
|
iconSize={18}
|
||||||
description={__('Delete List')}
|
description={__('Delete List')}
|
||||||
disabled={claimIsPending}
|
disabled={claimIsPending}
|
||||||
/>
|
/>
|
||||||
)}
|
</>
|
||||||
{!isMyCollection && (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
title={__('Report content')}
|
title={__('Report content')}
|
||||||
className="button--file-action"
|
className="button--file-action"
|
||||||
icon={ICONS.REPORT}
|
icon={ICONS.REPORT}
|
||||||
navigate={`/$/${PAGES.REPORT_CONTENT}?claimId=${claimId}`}
|
navigate={`/$/${PAGES.REPORT_CONTENT}?claimId=${claimId}`}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
|
<Button
|
||||||
|
className={classnames('button--file-action')}
|
||||||
|
label={__('Copy List')}
|
||||||
|
title={__('Copy List')}
|
||||||
|
onClick={() => openModal(MODALS.COLLECTION_ADD, { collectionId })}
|
||||||
|
icon={ICONS.COPY}
|
||||||
|
iconSize={18}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ import {
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectClaimIsMine,
|
makeSelectClaimIsMine,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import {
|
import { selectPlayingUri } from 'redux/selectors/content';
|
||||||
selectPlayingUri,
|
import { doOpenModal } from 'redux/actions/app';
|
||||||
} from 'redux/selectors/content';
|
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
|
@ -26,4 +25,6 @@ const select = (state, props) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(select)(CollectionContent);
|
export default connect(select, {
|
||||||
|
doOpenModal,
|
||||||
|
})(CollectionContent);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ClaimList from 'component/claimList';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import * as PAGES from 'constants/pages';
|
import * as PAGES from 'constants/pages';
|
||||||
|
import * as MODALS from 'constants/modal_types';
|
||||||
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 { COLLECTIONS_CONSTS } from 'lbry-redux';
|
import { COLLECTIONS_CONSTS } from 'lbry-redux';
|
||||||
|
@ -16,28 +17,52 @@ type Props = {
|
||||||
collectionName: string,
|
collectionName: string,
|
||||||
collection: any,
|
collection: any,
|
||||||
createUnpublishedCollection: (string, Array<any>, ?string) => void,
|
createUnpublishedCollection: (string, Array<any>, ?string) => void,
|
||||||
|
doOpenModal: (id: string, { collectionId: string }) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function CollectionContent(props: Props) {
|
export default function CollectionContent(props: Props) {
|
||||||
const { collectionUrls, collectionName, id, url } = props;
|
const {
|
||||||
|
collectionUrls,
|
||||||
|
collectionName,
|
||||||
|
id,
|
||||||
|
url,
|
||||||
|
doOpenModal,
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
isBodyList
|
isBodyList
|
||||||
className="file-page__recommended"
|
className="file-page__recommended"
|
||||||
title={
|
title={
|
||||||
<span>
|
<>
|
||||||
<Icon
|
<span className="file-page__recommended-collection__row">
|
||||||
icon={(id === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
|
<Icon
|
||||||
(id === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) || ICONS.STACK}
|
icon={
|
||||||
className="icon--margin-right" />
|
(id === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
|
||||||
{collectionName}
|
(id === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) ||
|
||||||
</span>
|
ICONS.STACK
|
||||||
|
}
|
||||||
|
className="icon--margin-right"
|
||||||
|
/>
|
||||||
|
{collectionName}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
titleActions={
|
titleActions={
|
||||||
<div className="card__title-actions--link">
|
<>
|
||||||
{/* TODO: BUTTON TO SAVE COLLECTION - Probably save/copy modal */}
|
<div className="card__title-actions--link">
|
||||||
<Button label={'View List'} button="link" navigate={`/$/${PAGES.LIST}/${id}`} />
|
<Button label={'View List'} button="link" navigate={`/$/${PAGES.LIST}/${id}`} />
|
||||||
</div>
|
</div>
|
||||||
|
<span>
|
||||||
|
<Button
|
||||||
|
button="alt"
|
||||||
|
title={__('Copy')}
|
||||||
|
icon={ICONS.COPY}
|
||||||
|
className="button--file-action--right"
|
||||||
|
onClick={() => doOpenModal(MODALS.COLLECTION_ADD, { collectionId: id })}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
body={
|
body={
|
||||||
<ClaimList
|
<ClaimList
|
||||||
|
|
|
@ -40,6 +40,15 @@ function CollectionMenuList(props: Props) {
|
||||||
{__('View List')}
|
{__('View List')}
|
||||||
</div>
|
</div>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
className="comment__menu-option"
|
||||||
|
onSelect={() => doOpenModal(MODALS.COLLECTION_ADD, { collectionId })}
|
||||||
|
>
|
||||||
|
<div className="menu__link">
|
||||||
|
<Icon aria-hidden icon={ICONS.COPY} />
|
||||||
|
{__('Copy List')}
|
||||||
|
</div>
|
||||||
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className="comment__menu-option"
|
className="comment__menu-option"
|
||||||
onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}?view=edit`)}
|
onSelect={() => push(`/$/${PAGES.LIST}/${collectionId}?view=edit`)}
|
||||||
|
|
|
@ -13,19 +13,48 @@ type Props = {
|
||||||
editCollection: (string, CollectionEditParams) => void,
|
editCollection: (string, CollectionEditParams) => void,
|
||||||
claim: Claim,
|
claim: Claim,
|
||||||
collectionPending: Collection,
|
collectionPending: Collection,
|
||||||
|
setSelectedCollections: (any) => void,
|
||||||
|
selectedCollections: Array<string>,
|
||||||
|
items: Array<string>,
|
||||||
};
|
};
|
||||||
|
|
||||||
function CollectionSelectItem(props: Props) {
|
function CollectionSelectItem(props: Props) {
|
||||||
const { collection, hasClaim, category, editCollection, claim, collectionPending } = props;
|
const {
|
||||||
|
collection,
|
||||||
|
hasClaim,
|
||||||
|
category,
|
||||||
|
editCollection,
|
||||||
|
claim,
|
||||||
|
collectionPending,
|
||||||
|
setSelectedCollections,
|
||||||
|
selectedCollections,
|
||||||
|
items,
|
||||||
|
} = props;
|
||||||
const { name, id } = collection;
|
const { name, id } = collection;
|
||||||
const handleChange = (e) => {
|
const justAdded = selectedCollections.includes(name);
|
||||||
editCollection(id, { claims: [claim], remove: hasClaim });
|
const [active, setActive] = React.useState(justAdded);
|
||||||
|
|
||||||
|
const handleChange = () => {
|
||||||
|
if (items) {
|
||||||
|
if (active) {
|
||||||
|
selectedCollections.splice(selectedCollections.indexOf(id), 1);
|
||||||
|
setSelectedCollections([...selectedCollections]);
|
||||||
|
} else {
|
||||||
|
setSelectedCollections([...selectedCollections, id]);
|
||||||
|
}
|
||||||
|
setActive(!active);
|
||||||
|
} else {
|
||||||
|
editCollection(id, { claims: [claim], remove: hasClaim });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let icon;
|
let icon;
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case 'builtin':
|
case 'builtin':
|
||||||
icon = (id === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) || (id === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) || ICONS.STACK;
|
icon =
|
||||||
|
(id === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
|
||||||
|
(id === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) ||
|
||||||
|
ICONS.STACK;
|
||||||
break;
|
break;
|
||||||
case 'published':
|
case 'published':
|
||||||
icon = ICONS.STACK;
|
icon = ICONS.STACK;
|
||||||
|
@ -39,12 +68,12 @@ function CollectionSelectItem(props: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={'collection-select__item'}>
|
<div className={'collection-select__item'}>
|
||||||
<FormField
|
<FormField
|
||||||
checked={hasClaim}
|
checked={items ? active : hasClaim}
|
||||||
disabled={collectionPending}
|
disabled={collectionPending}
|
||||||
icon={icon}
|
icon={icon}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name={`select-${id}`}
|
name={`select-${id}`}
|
||||||
onChange={handleChange} // edit the collection
|
onChange={!justAdded && handleChange} // edit the collection
|
||||||
label={
|
label={
|
||||||
<span>
|
<span>
|
||||||
<Icon icon={icon} className={'icon-collection-select'} />
|
<Icon icon={icon} className={'icon-collection-select'} />
|
||||||
|
|
|
@ -6,13 +6,14 @@ import { Modal } from 'modal/modal';
|
||||||
type Props = {
|
type Props = {
|
||||||
doHideModal: () => void,
|
doHideModal: () => void,
|
||||||
uri: string,
|
uri: string,
|
||||||
|
collectionId: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModalClaimCollectionAdd = (props: Props) => {
|
const ModalClaimCollectionAdd = (props: Props) => {
|
||||||
const { doHideModal, uri } = props;
|
const { doHideModal, uri, collectionId } = props;
|
||||||
return (
|
return (
|
||||||
<Modal isOpen type="card" onAborted={doHideModal}>
|
<Modal isOpen type="card" onAborted={doHideModal}>
|
||||||
<ClaimCollectionAdd uri={uri} closeModal={doHideModal} />
|
<ClaimCollectionAdd uri={uri} closeModal={doHideModal} collectionId={collectionId} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,18 +112,26 @@ export default function CollectionPage(props: Props) {
|
||||||
title={
|
title={
|
||||||
<span>
|
<span>
|
||||||
<Icon
|
<Icon
|
||||||
icon={(collectionId === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
|
icon={
|
||||||
(collectionId === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) || ICONS.STACK}
|
(collectionId === COLLECTIONS_CONSTS.WATCH_LATER_ID && ICONS.TIME) ||
|
||||||
className="icon--margin-right" />
|
(collectionId === COLLECTIONS_CONSTS.FAVORITES_ID && ICONS.STAR) ||
|
||||||
|
ICONS.STACK
|
||||||
|
}
|
||||||
|
className="icon--margin-right"
|
||||||
|
/>
|
||||||
{claim ? claim.value.title || claim.name : collection && collection.name}
|
{claim ? claim.value.title || claim.name : collection && collection.name}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
titleActions={titleActions}
|
titleActions={titleActions}
|
||||||
subtitle={subTitle}
|
subtitle={subTitle}
|
||||||
body={
|
body={
|
||||||
!isBuiltin && (
|
<CollectionActions
|
||||||
<CollectionActions uri={uri} collectionId={collectionId} setShowInfo={setShowInfo} showInfo={showInfo} />
|
uri={uri}
|
||||||
)
|
collectionId={collectionId}
|
||||||
|
setShowInfo={setShowInfo}
|
||||||
|
showInfo={showInfo}
|
||||||
|
isBuiltin={isBuiltin}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
showInfo &&
|
showInfo &&
|
||||||
|
|
|
@ -240,6 +240,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button--file-action--right {
|
||||||
|
@extend .button--file-action;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
.button--fire {
|
.button--fire {
|
||||||
color: var(--color-fire);
|
color: var(--color-fire);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
Loading…
Reference in a new issue