Additional pop up menu options
This commit is contained in:
parent
524370711c
commit
2aaa9f358b
16 changed files with 336 additions and 150 deletions
|
@ -6,8 +6,8 @@ type Props = {
|
|||
uri: string,
|
||||
isBlocked: boolean,
|
||||
isBlockingOrUnBlocking: boolean,
|
||||
doCommentModUnBlock: (string) => void,
|
||||
doCommentModBlock: (string) => void,
|
||||
doCommentModUnBlock: (string, boolean) => void,
|
||||
doCommentModBlock: (string, boolean) => void,
|
||||
};
|
||||
|
||||
function ChannelBlockButton(props: Props) {
|
||||
|
@ -15,9 +15,9 @@ function ChannelBlockButton(props: Props) {
|
|||
|
||||
function handleClick() {
|
||||
if (isBlocked) {
|
||||
doCommentModUnBlock(uri);
|
||||
doCommentModUnBlock(uri, false);
|
||||
} else {
|
||||
doCommentModBlock(uri);
|
||||
doCommentModBlock(uri, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doToggleMuteChannel } from 'redux/actions/blocked';
|
||||
import { doChannelMute, doChannelUnmute } from 'redux/actions/blocked';
|
||||
import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
|
||||
import ChannelMuteButton from './view';
|
||||
|
||||
|
@ -8,5 +8,6 @@ const select = (state, props) => ({
|
|||
});
|
||||
|
||||
export default connect(select, {
|
||||
doToggleMuteChannel,
|
||||
doChannelMute,
|
||||
doChannelUnmute,
|
||||
})(ChannelMuteButton);
|
||||
|
|
|
@ -6,17 +6,26 @@ type Props = {
|
|||
uri: string,
|
||||
isMuted: boolean,
|
||||
channelClaim: ?ChannelClaim,
|
||||
doToggleMuteChannel: (string) => void,
|
||||
doChannelMute: (string, boolean) => void,
|
||||
doChannelUnmute: (string, boolean) => void,
|
||||
};
|
||||
|
||||
function ChannelBlockButton(props: Props) {
|
||||
const { uri, doToggleMuteChannel, isMuted } = props;
|
||||
const { uri, doChannelMute, doChannelUnmute, isMuted } = props;
|
||||
|
||||
function handleClick() {
|
||||
if (isMuted) {
|
||||
doChannelUnmute(uri, false);
|
||||
} else {
|
||||
doChannelMute(uri, false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
button={isMuted ? 'alt' : 'secondary'}
|
||||
label={isMuted ? __('Unmute') : __('Mute')}
|
||||
onClick={() => doToggleMuteChannel(uri)}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ type Props = {
|
|||
liveLivestreamsFirst?: boolean,
|
||||
livestreamMap?: { [string]: any },
|
||||
searchOptions?: any,
|
||||
channelIsMine: boolean,
|
||||
collectionId?: string,
|
||||
};
|
||||
|
||||
|
@ -76,7 +75,6 @@ export default function ClaimList(props: Props) {
|
|||
liveLivestreamsFirst,
|
||||
livestreamMap,
|
||||
searchOptions,
|
||||
channelIsMine,
|
||||
collectionId,
|
||||
} = props;
|
||||
|
||||
|
@ -136,7 +134,6 @@ export default function ClaimList(props: Props) {
|
|||
showHiddenByUser={showHiddenByUser}
|
||||
properties={renderProperties}
|
||||
live={resolveLive(index)}
|
||||
channelIsMine={channelIsMine}
|
||||
collectionId={collectionId}
|
||||
/>
|
||||
))}
|
||||
|
|
|
@ -73,7 +73,6 @@ type Props = {
|
|||
livestreamMap?: { [string]: any },
|
||||
hasSource?: boolean,
|
||||
isChannel?: boolean,
|
||||
channelIsMine?: boolean,
|
||||
empty?: string,
|
||||
};
|
||||
|
||||
|
@ -130,7 +129,6 @@ function ClaimListDiscover(props: Props) {
|
|||
livestreamMap,
|
||||
hasSource,
|
||||
isChannel = false,
|
||||
channelIsMine = false,
|
||||
empty,
|
||||
} = props;
|
||||
const didNavigateForward = history.action === 'PUSH';
|
||||
|
@ -514,7 +512,6 @@ function ClaimListDiscover(props: Props) {
|
|||
liveLivestreamsFirst={liveLivestreamsFirst}
|
||||
livestreamMap={livestreamMap}
|
||||
searchOptions={options}
|
||||
channelIsMine={channelIsMine}
|
||||
/>
|
||||
{loading && (
|
||||
<div className="claim-grid">
|
||||
|
|
|
@ -2,35 +2,38 @@ import { connect } from 'react-redux';
|
|||
import {
|
||||
doCollectionEdit,
|
||||
makeSelectClaimForUri,
|
||||
makeSelectClaimIsMine,
|
||||
makeSelectFileInfoForUri,
|
||||
doPrepareEdit,
|
||||
makeSelectCollectionForIdHasClaimUrl,
|
||||
makeSelectNameForCollectionId,
|
||||
makeSelectCollectionIsMine,
|
||||
COLLECTIONS_CONSTS,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
|
||||
import { doToggleMuteChannel } from 'redux/actions/blocked';
|
||||
import { doChannelMute, doChannelUnmute } from 'redux/actions/blocked';
|
||||
import { doSetActiveChannel, doSetIncognito, doOpenModal } from 'redux/actions/app';
|
||||
import { doCommentModBlock, doCommentModUnBlock } from 'redux/actions/comments';
|
||||
import { makeSelectChannelIsBlocked } from 'redux/selectors/comments';
|
||||
import { doOpenModal } from 'redux/actions/app';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
import { makeSelectUserPropForProp } from 'redux/selectors/user';
|
||||
import ClaimPreview from './view';
|
||||
import * as USER from 'constants/user';
|
||||
import { makeSelectSigningIsMine } from 'redux/selectors/content';
|
||||
import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions';
|
||||
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
||||
import ClaimPreview from './view';
|
||||
import fs from 'fs';
|
||||
|
||||
const select = (state, props) => {
|
||||
const claim = makeSelectClaimForUri(props.uri)(state);
|
||||
const permanentUri = claim && claim.permanent_url;
|
||||
return {
|
||||
claim,
|
||||
claimIsMine: props.channelIsMine
|
||||
? props.isRepost
|
||||
? makeSelectClaimIsMine(props.uri)(state)
|
||||
: true
|
||||
: makeSelectClaimIsMine(props.uri)(state),
|
||||
claimIsMine: makeSelectSigningIsMine(props.uri)(state),
|
||||
hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(COLLECTIONS_CONSTS.WATCH_LATER_ID, permanentUri)(state),
|
||||
channelIsMuted: makeSelectChannelIsMuted(props.uri)(state),
|
||||
channelIsBlocked: makeSelectChannelIsBlocked(props.uri)(state),
|
||||
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.channelUri, true)(state),
|
||||
claimInCollection: makeSelectCollectionForIdHasClaimUrl(props.collectionId, permanentUri)(state),
|
||||
collectionName: makeSelectNameForCollectionId(props.collectionId)(state),
|
||||
isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state),
|
||||
|
@ -38,11 +41,26 @@ const select = (state, props) => {
|
|||
};
|
||||
};
|
||||
|
||||
export default connect(select, {
|
||||
doToggleMuteChannel,
|
||||
doCommentModBlock,
|
||||
doCommentModUnBlock,
|
||||
doCollectionEdit,
|
||||
doOpenModal,
|
||||
doToast,
|
||||
})(ClaimPreview);
|
||||
const perform = (dispatch) => ({
|
||||
prepareEdit: (publishData, uri, fileInfo) => {
|
||||
if (publishData.signing_channel) {
|
||||
dispatch(doSetIncognito(false));
|
||||
dispatch(doSetActiveChannel(publishData.signing_channel.claim_id));
|
||||
} else {
|
||||
dispatch(doSetIncognito(true));
|
||||
}
|
||||
|
||||
dispatch(doPrepareEdit(publishData, uri, fileInfo, fs));
|
||||
},
|
||||
doToast: (props) => dispatch(doToast(props)),
|
||||
openModal: (modal, props) => dispatch(doOpenModal(modal, props)),
|
||||
doChannelMute: (channelUri) => dispatch(doChannelMute(channelUri)),
|
||||
doChannelUnmute: (channelUri) => dispatch(doChannelUnmute(channelUri)),
|
||||
doCommentModBlock: (channelUri) => dispatch(doCommentModBlock(channelUri)),
|
||||
doCommentModUnBlock: (channelUri) => dispatch(doCommentModUnBlock(channelUri)),
|
||||
doChannelSubscribe: (subscription) => dispatch(doChannelSubscribe(subscription)),
|
||||
doChannelUnsubscribe: (subscription) => dispatch(doChannelUnsubscribe(subscription)),
|
||||
doCollectionEdit: (collection, props) => dispatch(doCollectionEdit(collection, props)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ClaimPreview);
|
||||
|
|
|
@ -9,63 +9,84 @@ import { Menu, MenuButton, MenuList, MenuItem } from '@reach/menu-button';
|
|||
import Icon from 'component/common/icon';
|
||||
import { generateShareUrl } from 'util/url';
|
||||
import { useHistory } from 'react-router';
|
||||
import { COLLECTIONS_CONSTS } from 'lbry-redux';
|
||||
import { buildURI, parseURI, COLLECTIONS_CONSTS } from 'lbry-redux';
|
||||
|
||||
const SHARE_DOMAIN = SHARE_DOMAIN_URL || URL;
|
||||
const PAGE_VIEW_QUERY = `view`;
|
||||
const EDIT_PAGE = 'edit';
|
||||
|
||||
type SubscriptionArgs = {
|
||||
channelName: string,
|
||||
uri: string,
|
||||
notificationsDisabled?: boolean,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
uri: string,
|
||||
channelUri: string,
|
||||
claim: ?Claim,
|
||||
openModal: (id: string, {}) => void,
|
||||
inline?: boolean,
|
||||
claimIsMine: boolean,
|
||||
channelIsMuted: boolean,
|
||||
channelIsBlocked: boolean,
|
||||
doToggleMuteChannel: (string) => void,
|
||||
doChannelMute: (string) => void,
|
||||
doChannelUnmute: (string) => void,
|
||||
doCommentModBlock: (string) => void,
|
||||
doCommentModUnBlock: (string) => void,
|
||||
channelIsMine: boolean,
|
||||
isRepost: boolean,
|
||||
doCollectionEdit: (string, any) => void,
|
||||
hasClaimInWatchLater: boolean,
|
||||
doOpenModal: (string, {}) => void,
|
||||
claimInCollection: boolean,
|
||||
collectionName?: string,
|
||||
collectionId: string,
|
||||
isMyCollection: boolean,
|
||||
doToast: ({ message: string }) => void,
|
||||
hasExperimentalUi: boolean,
|
||||
claimIsMine: boolean,
|
||||
fileInfo: FileListItem,
|
||||
prepareEdit: ({}, string, {}) => void,
|
||||
isSubscribed: boolean,
|
||||
doChannelSubscribe: (SubscriptionArgs) => void,
|
||||
doChannelUnsubscribe: (SubscriptionArgs) => void,
|
||||
};
|
||||
|
||||
function ClaimMenuList(props: Props) {
|
||||
const {
|
||||
uri,
|
||||
channelUri,
|
||||
claim,
|
||||
openModal,
|
||||
inline = false,
|
||||
claimIsMine,
|
||||
doToggleMuteChannel,
|
||||
doChannelMute,
|
||||
doChannelUnmute,
|
||||
channelIsMuted,
|
||||
channelIsBlocked,
|
||||
doCommentModBlock,
|
||||
doCommentModUnBlock,
|
||||
doCollectionEdit,
|
||||
hasClaimInWatchLater,
|
||||
doOpenModal,
|
||||
collectionId,
|
||||
collectionName,
|
||||
isMyCollection,
|
||||
doToast,
|
||||
hasExperimentalUi,
|
||||
claimIsMine,
|
||||
fileInfo,
|
||||
prepareEdit,
|
||||
isSubscribed,
|
||||
doChannelSubscribe,
|
||||
doChannelUnsubscribe,
|
||||
} = props;
|
||||
const incognito = channelUri && !(channelUri.includes('@'));
|
||||
const signingChannel = claim && (claim.signing_channel || claim);
|
||||
const isChannel = !incognito && signingChannel === claim;
|
||||
const showDelete = claimIsMine || (fileInfo && (fileInfo.written_bytes > 0 || fileInfo.blobs_completed > 0));
|
||||
const subscriptionLabel = isSubscribed ? __('Unfollow') : __('Follow');
|
||||
|
||||
const { push } = useHistory();
|
||||
if (!claim) {
|
||||
return null;
|
||||
}
|
||||
const channelUri = claim
|
||||
? claim.value_type === 'channel'
|
||||
? claim.permanent_url
|
||||
: (claim.signing_channel && claim.signing_channel.permanent_url) || ''
|
||||
: '';
|
||||
|
||||
const shareUrl: string = generateShareUrl(SHARE_DOMAIN, uri);
|
||||
const isCollectionClaim = claim && claim.value_type === 'collection';
|
||||
|
@ -78,8 +99,28 @@ function ClaimMenuList(props: Props) {
|
|||
// $FlowFixMe
|
||||
(claim.value.stream_type === 'audio' || claim.value.stream_type === 'video');
|
||||
|
||||
function handleFollow() {
|
||||
const permanentUrl = signingChannel && signingChannel.permanent_url;
|
||||
const { channelName } = parseURI(permanentUrl);
|
||||
const subscriptionHandler = isSubscribed ? doChannelUnsubscribe : doChannelSubscribe;
|
||||
|
||||
subscriptionHandler({
|
||||
channelName: '@' + channelName,
|
||||
uri: permanentUrl,
|
||||
notificationsDisabled: true,
|
||||
});
|
||||
}
|
||||
|
||||
function handleAnalytics() {
|
||||
push(`/$/${PAGES.CREATOR_DASHBOARD}?channel=${encodeURIComponent(signingChannel.canonical_url)}`);
|
||||
}
|
||||
|
||||
function handleToggleMute() {
|
||||
doToggleMuteChannel(channelUri);
|
||||
if (channelIsMuted) {
|
||||
doChannelUnmute(channelUri);
|
||||
} else {
|
||||
doChannelMute(channelUri);
|
||||
}
|
||||
}
|
||||
|
||||
function handleToggleBlock() {
|
||||
|
@ -90,6 +131,40 @@ function ClaimMenuList(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
if (!isChannel) {
|
||||
const signingChannelName = signingChannel && signingChannel.name;
|
||||
|
||||
let editUri;
|
||||
const uriObject: { streamName: string, streamClaimId: string, channelName?: string } = {
|
||||
streamName: claim.name,
|
||||
streamClaimId: claim.claim_id,
|
||||
};
|
||||
if (signingChannelName) {
|
||||
uriObject.channelName = signingChannelName;
|
||||
}
|
||||
editUri = buildURI(uriObject);
|
||||
|
||||
push(`/$/${PAGES.UPLOAD}`);
|
||||
prepareEdit(claim, editUri, fileInfo);
|
||||
} else {
|
||||
const channelUrl = claim.name + ':' + claim.claim_id;
|
||||
push(`/${channelUrl}?${PAGE_VIEW_QUERY}=${EDIT_PAGE}`);
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete() {
|
||||
if (!isChannel) {
|
||||
openModal(MODALS.CONFIRM_FILE_REMOVE, { uri });
|
||||
} else {
|
||||
openModal(MODALS.CONFIRM_CLAIM_REVOKE, { claim: claim, cb: () => replace(`/$/${PAGES.CHANNELS}`) });
|
||||
}
|
||||
}
|
||||
|
||||
function handleSupport() {
|
||||
openModal(MODALS.SEND_TIP, { uri, isSupport: true });
|
||||
}
|
||||
|
||||
function handleCopyLink() {
|
||||
navigator.clipboard.writeText(shareUrl);
|
||||
}
|
||||
|
@ -110,6 +185,29 @@ function ClaimMenuList(props: Props) {
|
|||
<Icon size={20} icon={ICONS.MORE_VERTICAL} />
|
||||
</MenuButton>
|
||||
<MenuList className="menu__list">
|
||||
|
||||
{!incognito && (!claimIsMine ? (
|
||||
<MenuItem className="comment__menu-option" onSelect={handleFollow}>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.SUBSCRIBE} />
|
||||
{subscriptionLabel}
|
||||
</div>
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem className="comment__menu-option" onSelect={handleAnalytics}>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.ANALYTICS} />
|
||||
{__('Channel Analytics')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
))}
|
||||
<MenuItem className="comment__menu-option" onSelect={handleSupport}>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.LBC} />
|
||||
{__('Support')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
|
||||
{hasExperimentalUi && (
|
||||
<>
|
||||
{/* WATCH LATER */}
|
||||
|
@ -148,7 +246,7 @@ function ClaimMenuList(props: Props) {
|
|||
</MenuItem>
|
||||
<MenuItem
|
||||
className="comment__menu-option"
|
||||
onSelect={() => doOpenModal(MODALS.COLLECTION_DELETE, { collectionId })}
|
||||
onSelect={() => openModal(MODALS.COLLECTION_DELETE, { collectionId })}
|
||||
>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.DELETE} />
|
||||
|
@ -161,7 +259,7 @@ function ClaimMenuList(props: Props) {
|
|||
{isPlayable && (
|
||||
<MenuItem
|
||||
className="comment__menu-option"
|
||||
onSelect={() => doOpenModal(MODALS.COLLECTION_ADD, { uri, type: 'playlist' })}
|
||||
onSelect={() => openModal(MODALS.COLLECTION_ADD, { uri, type: 'playlist' })}
|
||||
>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.STACK} />
|
||||
|
@ -169,10 +267,11 @@ function ClaimMenuList(props: Props) {
|
|||
</div>
|
||||
</MenuItem>
|
||||
)}
|
||||
<hr className="menu__separator" />
|
||||
</>
|
||||
)}
|
||||
<hr className="menu__separator" />
|
||||
{channelUri && !claimIsMine && !isMyCollection && (
|
||||
|
||||
{channelUri && !claimIsMine && !isMyCollection ? !incognito && (
|
||||
<>
|
||||
<MenuItem className="comment__menu-option" onSelect={handleToggleBlock}>
|
||||
<div className="menu__link">
|
||||
|
@ -187,10 +286,27 @@ function ClaimMenuList(props: Props) {
|
|||
{channelIsMuted ? __('Unmute Channel') : __('Mute Channel')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<MenuItem className="comment__menu-option" onSelect={handleEdit}>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.EDIT} />
|
||||
{__('Edit')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
|
||||
<hr className="menu__separator" />
|
||||
{showDelete && (
|
||||
<MenuItem className="comment__menu-option" onSelect={handleDelete}>
|
||||
<div className="menu__link">
|
||||
<Icon aria-hidden icon={ICONS.DELETE} />
|
||||
{__('Delete')}
|
||||
</div>
|
||||
</MenuItem>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<hr className="menu__separator" />
|
||||
|
||||
<MenuItem className="comment__menu-option" onSelect={handleCopyLink}>
|
||||
<div className="menu__link">
|
||||
|
|
|
@ -161,6 +161,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
collectionParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, collectionId);
|
||||
navigateUrl = navigateUrl + `?` + collectionParams.toString();
|
||||
}
|
||||
const channelUri = claim && (signingChannel ? signingChannel.permanent_url : claim.permanent_url);
|
||||
const navLinkProps = {
|
||||
to: navigateUrl,
|
||||
onClick: (e) => e.stopPropagation(),
|
||||
|
@ -421,7 +422,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
{!hideMenu && <ClaimMenuList uri={uri} collectionId={collectionId} />}
|
||||
{!hideMenu && <ClaimMenuList uri={uri} collectionId={collectionId} channelUri={channelUri} />}
|
||||
</>
|
||||
</WrapperElement>
|
||||
);
|
||||
|
|
|
@ -43,7 +43,6 @@ type Props = {
|
|||
showHiddenByUser?: boolean,
|
||||
properties?: (Claim) => void,
|
||||
live?: boolean,
|
||||
channelIsMine?: boolean,
|
||||
collectionId?: string,
|
||||
};
|
||||
|
||||
|
@ -67,7 +66,6 @@ function ClaimPreviewTile(props: Props) {
|
|||
showHiddenByUser,
|
||||
properties,
|
||||
live,
|
||||
channelIsMine,
|
||||
collectionId,
|
||||
} = props;
|
||||
const isRepost = claim && claim.repost_channel_url;
|
||||
|
@ -100,11 +98,8 @@ function ClaimPreviewTile(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
let channelUri;
|
||||
const signingChannel = claim && claim.signing_channel;
|
||||
if (signingChannel) {
|
||||
channelUri = signingChannel.permanent_url;
|
||||
}
|
||||
const channelUri = signingChannel && signingChannel.permanent_url;
|
||||
|
||||
function handleClick(e) {
|
||||
if (navigateUrl) {
|
||||
|
@ -219,7 +214,7 @@ function ClaimPreviewTile(props: Props) {
|
|||
</div>
|
||||
)}
|
||||
{/* CHECK CLAIM MENU LIST PARAMS (IS REPOST?) */}
|
||||
<ClaimMenuList uri={uri} collectionId={listId} channelIsMine={channelIsMine} isRepost={isRepost} />
|
||||
<ClaimMenuList uri={uri} collectionId={listId} channelUri={channelUri} isRepost={isRepost} />
|
||||
</h2>
|
||||
</NavLink>
|
||||
<div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectChannelPermUrlForClaimUri, makeSelectClaimIsMine, makeSelectClaimForUri } from 'lbry-redux';
|
||||
import { doCommentAbandon, doCommentPin, doCommentList, doCommentModBlock } from 'redux/actions/comments';
|
||||
import { doToggleMuteChannel } from 'redux/actions/blocked';
|
||||
import { doChannelMute } from 'redux/actions/blocked';
|
||||
// import { doSetActiveChannel } from 'redux/actions/app';
|
||||
import { doSetPlayingUri } from 'redux/actions/content';
|
||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||
|
@ -19,7 +19,7 @@ const select = (state, props) => ({
|
|||
const perform = (dispatch) => ({
|
||||
clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
|
||||
deleteComment: (commentId, creatorChannelUrl) => dispatch(doCommentAbandon(commentId, creatorChannelUrl)),
|
||||
blockChannel: (channelUri) => dispatch(doToggleMuteChannel(channelUri)),
|
||||
muteChannel: (channelUri) => dispatch(doChannelMute(channelUri)),
|
||||
pinComment: (commentId, remove) => dispatch(doCommentPin(commentId, remove)),
|
||||
fetchComments: (uri) => dispatch(doCommentList(uri)),
|
||||
// setActiveChannel: channelId => dispatch(doSetActiveChannel(channelId)),
|
||||
|
|
|
@ -15,7 +15,7 @@ type Props = {
|
|||
linkedComment?: any,
|
||||
isPinned: boolean,
|
||||
pinComment: (string, boolean) => Promise<any>,
|
||||
blockChannel: (string) => void,
|
||||
muteChannel: (string) => void,
|
||||
fetchComments: (string) => void,
|
||||
handleEditComment: () => void,
|
||||
contentChannelPermanentUrl: any,
|
||||
|
@ -34,7 +34,7 @@ function CommentMenuList(props: Props) {
|
|||
commentIsMine,
|
||||
commentId,
|
||||
deleteComment,
|
||||
blockChannel,
|
||||
muteChannel,
|
||||
pinComment,
|
||||
clearPlayingUri,
|
||||
activeChannelClaim,
|
||||
|
@ -66,7 +66,7 @@ function CommentMenuList(props: Props) {
|
|||
}
|
||||
|
||||
function handleCommentMute() {
|
||||
blockChannel(authorUri);
|
||||
muteChannel(authorUri);
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -191,8 +191,7 @@ function ChannelPage(props: Props) {
|
|||
{!channelIsBlackListed && <ShareButton uri={uri} />}
|
||||
{!(isBlocked || isMuted) && <ClaimSupportButton uri={uri} />}
|
||||
{!(isBlocked || isMuted) && (!channelIsBlackListed || isSubscribed) && <SubscribeButton uri={permanentUrl} />}
|
||||
{/* TODO: add channel collections <ClaimCollectionAddButton uri={uri} fileAction /> */}
|
||||
<ClaimMenuList uri={claim.permanent_url} inline />
|
||||
<ClaimMenuList uri={claim.permanent_url} channelUri={claim.permanent_url} inline />
|
||||
</div>
|
||||
{cover && <img className={classnames('channel-cover__custom')} src={cover} />}
|
||||
<div className="channel__primary-info">
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import { selectPrefsReady } from 'redux/selectors/sync';
|
||||
import { doAlertWaitingForSync } from 'redux/actions/app';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
|
||||
export const doToggleMuteChannel = (uri: string) => (dispatch: Dispatch, getState: GetState) => {
|
||||
export function doToggleMuteChannel(uri: string, showLink: boolean, unmute: boolean = false) {
|
||||
return async (dispatch: Dispatch, getState: GetState) => {
|
||||
const state = getState();
|
||||
const ready = selectPrefsReady(state);
|
||||
|
||||
|
@ -17,4 +19,23 @@ export const doToggleMuteChannel = (uri: string) => (dispatch: Dispatch, getStat
|
|||
uri,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
dispatch(doToast({
|
||||
message: __(!unmute ? 'Channel muted. You will not see them again.' : 'Channel unmuted!'),
|
||||
linkText: __(showLink ? 'See All' : ''),
|
||||
linkTarget: '/settings/block_and_mute',
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
export function doChannelMute(uri: string, showLink: boolean = true) {
|
||||
return (dispatch: Dispatch) => {
|
||||
return dispatch(doToggleMuteChannel(uri, showLink));
|
||||
};
|
||||
}
|
||||
|
||||
export function doChannelUnmute(uri: string, showLink: boolean = true) {
|
||||
return (dispatch: Dispatch) => {
|
||||
return dispatch(doToggleMuteChannel(uri, showLink, true));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -506,7 +506,7 @@ async function channelSignName(channelClaimId: string, channelName: string) {
|
|||
}
|
||||
|
||||
// Hides a users comments from all creator's claims and prevent them from commenting in the future
|
||||
export function doCommentModToggleBlock(channelUri: string, unblock: boolean = false) {
|
||||
export function doCommentModToggleBlock(channelUri: string, showLink: boolean, unblock: boolean = false) {
|
||||
return async (dispatch: Dispatch, getState: GetState) => {
|
||||
const state = getState();
|
||||
const myChannels = selectMyChannelClaims(state);
|
||||
|
@ -564,9 +564,11 @@ export function doCommentModToggleBlock(channelUri: string, unblock: boolean = f
|
|||
data: { channelUri },
|
||||
});
|
||||
|
||||
if (!unblock) {
|
||||
dispatch(doToast({ message: __('Channel blocked. You will not see them again.') }));
|
||||
}
|
||||
dispatch(doToast({
|
||||
message: __(!unblock ? 'Channel blocked. They will not interact with you again.' : 'Channel unblocked!'),
|
||||
linkText: __(showLink ? 'See All' : ''),
|
||||
linkTarget: '/settings/block_and_mute',
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch({
|
||||
|
@ -582,15 +584,15 @@ export function doCommentModToggleBlock(channelUri: string, unblock: boolean = f
|
|||
};
|
||||
}
|
||||
|
||||
export function doCommentModBlock(commentAuthor: string) {
|
||||
export function doCommentModBlock(commentAuthor: string, showLink: boolean = true) {
|
||||
return (dispatch: Dispatch) => {
|
||||
return dispatch(doCommentModToggleBlock(commentAuthor));
|
||||
return dispatch(doCommentModToggleBlock(commentAuthor, showLink));
|
||||
};
|
||||
}
|
||||
|
||||
export function doCommentModUnBlock(commentAuthor: string) {
|
||||
export function doCommentModUnBlock(commentAuthor: string, showLink: boolean = true) {
|
||||
return (dispatch: Dispatch) => {
|
||||
return dispatch(doCommentModToggleBlock(commentAuthor, true));
|
||||
return dispatch(doCommentModToggleBlock(commentAuthor, showLink, true));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
// @flow
|
||||
import * as ACTIONS from 'constants/action_types';
|
||||
import REWARDS from 'rewards';
|
||||
import { Lbryio } from 'lbryinc';
|
||||
import { doClaimRewardType } from 'redux/actions/rewards';
|
||||
import { parseURI } from 'lbry-redux';
|
||||
import { doAlertWaitingForSync } from 'redux/actions/app';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
|
||||
export const doChannelSubscribe = subscription => (dispatch, getState) => {
|
||||
type SubscriptionArgs = {
|
||||
channelName: string,
|
||||
uri: string,
|
||||
notificationsDisabled?: boolean,
|
||||
};
|
||||
|
||||
export function doToggleSubscription(subscription: SubscriptionArgs, isSubscribed: boolean = false) {
|
||||
return async (dispatch: Dispatch, getState: GetState) => {
|
||||
const {
|
||||
settings: { daemonSettings },
|
||||
sync: { prefsReady: ready },
|
||||
|
@ -18,19 +27,23 @@ export const doChannelSubscribe = subscription => (dispatch, getState) => {
|
|||
const { share_usage_data: shareSetting } = daemonSettings;
|
||||
const isSharingData = shareSetting || IS_WEB;
|
||||
|
||||
if (!isSubscribed) {
|
||||
const subscriptionUri = subscription.uri;
|
||||
if (!subscriptionUri.startsWith('lbry://')) {
|
||||
throw Error(`Subscription uris must include the "lbry://" prefix.\nTried to subscribe to ${subscriptionUri}`);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
||||
type: !isSubscribed ? ACTIONS.CHANNEL_SUBSCRIBE : ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||
data: subscription,
|
||||
});
|
||||
|
||||
// if the user isn't sharing data, keep the subscriptions entirely in the app
|
||||
if (isSharingData || IS_WEB) {
|
||||
const { channelClaimId } = parseURI(subscription.uri);
|
||||
|
||||
if (!isSubscribed) {
|
||||
// They are sharing data, we can store their subscriptions in our internal database
|
||||
Lbryio.call('subscription', 'new', {
|
||||
channel_name: subscription.channelName,
|
||||
|
@ -39,31 +52,27 @@ export const doChannelSubscribe = subscription => (dispatch, getState) => {
|
|||
});
|
||||
|
||||
dispatch(doClaimRewardType(REWARDS.TYPE_SUBSCRIPTION, { failSilently: true }));
|
||||
}
|
||||
};
|
||||
|
||||
export const doChannelUnsubscribe = subscription => (dispatch, getState) => {
|
||||
const {
|
||||
settings: { daemonSettings },
|
||||
sync: { prefsReady: ready },
|
||||
} = getState();
|
||||
|
||||
if (!ready) {
|
||||
return dispatch(doAlertWaitingForSync());
|
||||
}
|
||||
|
||||
const { share_usage_data: shareSetting } = daemonSettings;
|
||||
const isSharingData = shareSetting || IS_WEB;
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||
data: subscription,
|
||||
});
|
||||
|
||||
if (isSharingData) {
|
||||
const { channelClaimId } = parseURI(subscription.uri);
|
||||
} else {
|
||||
Lbryio.call('subscription', 'delete', {
|
||||
claim_id: channelClaimId,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dispatch(doToast({
|
||||
message: __(!isSubscribed ? 'You followed %CHANNEL_NAME%!' : 'Unfollowed %CHANNEL_NAME%.', { CHANNEL_NAME: subscription.channelName }),
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
export function doChannelSubscribe(subscription: SubscriptionArgs) {
|
||||
return (dispatch: Dispatch) => {
|
||||
return dispatch(doToggleSubscription(subscription));
|
||||
};
|
||||
}
|
||||
|
||||
export function doChannelUnsubscribe(subscription: SubscriptionArgs) {
|
||||
return (dispatch: Dispatch) => {
|
||||
return dispatch(doToggleSubscription(subscription, true));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
parseURI,
|
||||
makeSelectContentTypeForUri,
|
||||
makeSelectFileNameForUri,
|
||||
normalizeURI,
|
||||
selectMyActiveClaims,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectRecommendedContentForUri } from 'redux/selectors/search';
|
||||
import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||
|
@ -243,3 +245,22 @@ export const makeSelectInsufficientCreditsForUri = (uri: string) =>
|
|||
return !isMine && costInfo && costInfo.cost > 0 && costInfo.cost > balance;
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectSigningIsMine = (rawUri: string) => {
|
||||
let uri;
|
||||
try {
|
||||
uri = normalizeURI(rawUri);
|
||||
} catch (e) { }
|
||||
|
||||
return createSelector(selectClaimsByUri, selectMyActiveClaims, (claims, myClaims) => {
|
||||
try {
|
||||
parseURI(uri);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
const repostedChannel = claims && claims[uri] && claims[uri].reposted_claim && (claims[uri].reposted_claim.signing_channel || claims[uri].reposted_claim);
|
||||
const signingChannel = claims && claims[uri] && (repostedChannel || claims[uri].signing_channel || claims[uri]);
|
||||
|
||||
return signingChannel && myClaims.has(signingChannel.claim_id);
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue