improve pop up not identifying your own content in some cases
edit option delete option analytics for channel claim support option follow option fix revert subscription actions block actions mute actions block and mute buttons mute menu option lint handle edit channel fix comment mute logic analytics handle delete channel fix claimismine fix rebase
This commit is contained in:
parent
8f423c5ffb
commit
7d3f35b0c5
16 changed files with 331 additions and 129 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@ function ChannelBlockButton(props: Props) {
|
|||
? __('Unblocking...')
|
||||
: __('Unblock')
|
||||
: isBlockingOrUnBlocking
|
||||
? __('Blocking...')
|
||||
: __('Block')
|
||||
? __('Blocking...')
|
||||
: __('Block')
|
||||
}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
function ClaimListDiscover(props: Props) {
|
||||
|
@ -129,7 +128,6 @@ function ClaimListDiscover(props: Props) {
|
|||
livestreamMap,
|
||||
hasSource,
|
||||
isChannel = false,
|
||||
channelIsMine = false,
|
||||
} = props;
|
||||
const didNavigateForward = history.action === 'PUSH';
|
||||
const { search } = location;
|
||||
|
@ -512,7 +510,6 @@ function ClaimListDiscover(props: Props) {
|
|||
liveLivestreamsFirst={liveLivestreamsFirst}
|
||||
livestreamMap={livestreamMap}
|
||||
searchOptions={options}
|
||||
channelIsMine={channelIsMine}
|
||||
/>
|
||||
{loading && (
|
||||
<div className="claim-grid">
|
||||
|
|
|
@ -7,16 +7,23 @@ import {
|
|||
makeSelectNameForCollectionId,
|
||||
makeSelectCollectionIsMine,
|
||||
COLLECTIONS_CONSTS,
|
||||
makeSelectFileInfoForUri,
|
||||
doPrepareEdit,
|
||||
} 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 { makeSelectSigningIsMine } from 'redux/selectors/content';
|
||||
import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions';
|
||||
import { makeSelectIsSubscribed } from 'redux/selectors/subscriptions';
|
||||
import ClaimPreview from './view';
|
||||
import * as USER from 'constants/user';
|
||||
import fs from 'fs';
|
||||
|
||||
const select = (state, props) => {
|
||||
const claim = makeSelectClaimForUri(props.uri)(state);
|
||||
|
@ -35,14 +42,31 @@ const select = (state, props) => {
|
|||
collectionName: makeSelectNameForCollectionId(props.collectionId)(state),
|
||||
isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state),
|
||||
hasExperimentalUi: makeSelectUserPropForProp(USER.EXPERIMENTAL_UI)(state),
|
||||
fileInfo: makeSelectFileInfoForUri(props.uri)(state),
|
||||
isSubscribed: makeSelectIsSubscribed(props.channelUri, true)(state),
|
||||
};
|
||||
};
|
||||
|
||||
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));
|
||||
},
|
||||
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: (id, params) => dispatch(doCollectionEdit(id, params)),
|
||||
doToast: (params) => dispatch(doToast(params)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ClaimPreview);
|
||||
|
|
|
@ -10,54 +10,81 @@ 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 } 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();
|
||||
const { push, replace } = useHistory();
|
||||
if (!claim) {
|
||||
return null;
|
||||
}
|
||||
|
@ -78,8 +105,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 +137,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);
|
||||
}
|
||||
|
@ -172,7 +253,29 @@ function ClaimMenuList(props: Props) {
|
|||
</>
|
||||
)}
|
||||
<hr className="menu__separator" />
|
||||
{channelUri && !claimIsMine && !isMyCollection && (
|
||||
{!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>
|
||||
{channelUri && !claimIsMine && !isMyCollection && !incognito ? (
|
||||
<>
|
||||
<MenuItem className="comment__menu-option" onSelect={handleToggleBlock}>
|
||||
<div className="menu__link">
|
||||
|
@ -187,10 +290,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">
|
||||
|
|
|
@ -30,7 +30,7 @@ import * as ICONS from 'constants/icons';
|
|||
|
||||
type Props = {
|
||||
uri: string,
|
||||
claim: ?Claim, // maybe?
|
||||
claim: ?Claim,
|
||||
obscureNsfw: boolean,
|
||||
showUserBlocked: boolean,
|
||||
claimIsMine: boolean,
|
||||
|
@ -155,6 +155,8 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
|||
const isCollection = claim && claim.value_type === 'collection';
|
||||
const isChannelUri = isValid ? parseURI(uri).isChannel : false;
|
||||
const signingChannel = claim && claim.signing_channel;
|
||||
const channelUri = claim && (signingChannel ? signingChannel.permanent_url : claim.permanent_url);
|
||||
|
||||
let navigateUrl = formatLbryUrlForWeb((claim && claim.canonical_url) || uri || '/');
|
||||
if (collectionId) {
|
||||
const collectionParams = new URLSearchParams();
|
||||
|
@ -421,7 +423,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 (
|
||||
|
|
|
@ -186,7 +186,7 @@ function ChannelPage(props: Props) {
|
|||
{!(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,19 +2,40 @@
|
|||
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) => {
|
||||
const state = getState();
|
||||
const ready = selectPrefsReady(state);
|
||||
export function doToggleMuteChannel(uri: string, showLink: boolean, unmute: boolean = false) {
|
||||
return async (dispatch: Dispatch, getState: GetState) => {
|
||||
const state = getState();
|
||||
const ready = selectPrefsReady(state);
|
||||
|
||||
if (!ready) {
|
||||
return dispatch(doAlertWaitingForSync());
|
||||
}
|
||||
if (!ready) {
|
||||
return dispatch(doAlertWaitingForSync());
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.TOGGLE_BLOCK_CHANNEL,
|
||||
data: {
|
||||
uri,
|
||||
},
|
||||
});
|
||||
};
|
||||
dispatch({
|
||||
type: ACTIONS.TOGGLE_BLOCK_CHANNEL,
|
||||
data: {
|
||||
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,15 @@ 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 +588,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,69 +1,78 @@
|
|||
// @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) => {
|
||||
const {
|
||||
settings: { daemonSettings },
|
||||
sync: { prefsReady: ready },
|
||||
} = getState();
|
||||
|
||||
if (!ready) {
|
||||
return dispatch(doAlertWaitingForSync());
|
||||
}
|
||||
|
||||
const { share_usage_data: shareSetting } = daemonSettings;
|
||||
const isSharingData = shareSetting || IS_WEB;
|
||||
|
||||
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,
|
||||
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);
|
||||
// They are sharing data, we can store their subscriptions in our internal database
|
||||
Lbryio.call('subscription', 'new', {
|
||||
channel_name: subscription.channelName,
|
||||
claim_id: channelClaimId,
|
||||
notifications_disabled: subscription.notificationsDisabled,
|
||||
});
|
||||
|
||||
dispatch(doClaimRewardType(REWARDS.TYPE_SUBSCRIPTION, { failSilently: true }));
|
||||
}
|
||||
type SubscriptionArgs = {
|
||||
channelName: string,
|
||||
uri: string,
|
||||
notificationsDisabled?: boolean,
|
||||
};
|
||||
|
||||
export const doChannelUnsubscribe = subscription => (dispatch, getState) => {
|
||||
const {
|
||||
settings: { daemonSettings },
|
||||
sync: { prefsReady: ready },
|
||||
} = getState();
|
||||
export function doToggleSubscription(subscription: SubscriptionArgs, isSubscribed: boolean = false) {
|
||||
return async (dispatch: Dispatch, getState: GetState) => {
|
||||
const {
|
||||
settings: { daemonSettings },
|
||||
sync: { prefsReady: ready },
|
||||
} = getState();
|
||||
|
||||
if (!ready) {
|
||||
return dispatch(doAlertWaitingForSync());
|
||||
}
|
||||
if (!ready) {
|
||||
return dispatch(doAlertWaitingForSync());
|
||||
}
|
||||
|
||||
const { share_usage_data: shareSetting } = daemonSettings;
|
||||
const isSharingData = shareSetting || IS_WEB;
|
||||
const { share_usage_data: shareSetting } = daemonSettings;
|
||||
const isSharingData = shareSetting || IS_WEB;
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||
data: subscription,
|
||||
});
|
||||
if (!isSubscribed) {
|
||||
const subscriptionUri = subscription.uri;
|
||||
if (!subscriptionUri.startsWith('lbry://')) {
|
||||
throw Error(`Subscription uris must include the "lbry://" prefix.\nTried to subscribe to ${subscriptionUri}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (isSharingData) {
|
||||
const { channelClaimId } = parseURI(subscription.uri);
|
||||
Lbryio.call('subscription', 'delete', {
|
||||
claim_id: channelClaimId,
|
||||
dispatch({
|
||||
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,
|
||||
claim_id: channelClaimId,
|
||||
notifications_disabled: subscription.notificationsDisabled,
|
||||
});
|
||||
|
||||
dispatch(doClaimRewardType(REWARDS.TYPE_SUBSCRIPTION, { failSilently: true }));
|
||||
} 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