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,
|
uri: string,
|
||||||
isBlocked: boolean,
|
isBlocked: boolean,
|
||||||
isBlockingOrUnBlocking: boolean,
|
isBlockingOrUnBlocking: boolean,
|
||||||
doCommentModUnBlock: (string) => void,
|
doCommentModUnBlock: (string, boolean) => void,
|
||||||
doCommentModBlock: (string) => void,
|
doCommentModBlock: (string, boolean) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelBlockButton(props: Props) {
|
function ChannelBlockButton(props: Props) {
|
||||||
|
@ -15,9 +15,9 @@ function ChannelBlockButton(props: Props) {
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
if (isBlocked) {
|
if (isBlocked) {
|
||||||
doCommentModUnBlock(uri);
|
doCommentModUnBlock(uri, false);
|
||||||
} else {
|
} else {
|
||||||
doCommentModBlock(uri);
|
doCommentModBlock(uri, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
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 { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
|
||||||
import ChannelMuteButton from './view';
|
import ChannelMuteButton from './view';
|
||||||
|
|
||||||
|
@ -8,5 +8,6 @@ const select = (state, props) => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, {
|
export default connect(select, {
|
||||||
doToggleMuteChannel,
|
doChannelMute,
|
||||||
|
doChannelUnmute,
|
||||||
})(ChannelMuteButton);
|
})(ChannelMuteButton);
|
||||||
|
|
|
@ -6,17 +6,26 @@ type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
isMuted: boolean,
|
isMuted: boolean,
|
||||||
channelClaim: ?ChannelClaim,
|
channelClaim: ?ChannelClaim,
|
||||||
doToggleMuteChannel: (string) => void,
|
doChannelMute: (string, boolean) => void,
|
||||||
|
doChannelUnmute: (string, boolean) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelBlockButton(props: Props) {
|
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 (
|
return (
|
||||||
<Button
|
<Button
|
||||||
button={isMuted ? 'alt' : 'secondary'}
|
button={isMuted ? 'alt' : 'secondary'}
|
||||||
label={isMuted ? __('Unmute') : __('Mute')}
|
label={isMuted ? __('Unmute') : __('Mute')}
|
||||||
onClick={() => doToggleMuteChannel(uri)}
|
onClick={handleClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ type Props = {
|
||||||
liveLivestreamsFirst?: boolean,
|
liveLivestreamsFirst?: boolean,
|
||||||
livestreamMap?: { [string]: any },
|
livestreamMap?: { [string]: any },
|
||||||
searchOptions?: any,
|
searchOptions?: any,
|
||||||
channelIsMine: boolean,
|
|
||||||
collectionId?: string,
|
collectionId?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,7 +75,6 @@ export default function ClaimList(props: Props) {
|
||||||
liveLivestreamsFirst,
|
liveLivestreamsFirst,
|
||||||
livestreamMap,
|
livestreamMap,
|
||||||
searchOptions,
|
searchOptions,
|
||||||
channelIsMine,
|
|
||||||
collectionId,
|
collectionId,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
@ -136,7 +134,6 @@ export default function ClaimList(props: Props) {
|
||||||
showHiddenByUser={showHiddenByUser}
|
showHiddenByUser={showHiddenByUser}
|
||||||
properties={renderProperties}
|
properties={renderProperties}
|
||||||
live={resolveLive(index)}
|
live={resolveLive(index)}
|
||||||
channelIsMine={channelIsMine}
|
|
||||||
collectionId={collectionId}
|
collectionId={collectionId}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -73,7 +73,6 @@ type Props = {
|
||||||
livestreamMap?: { [string]: any },
|
livestreamMap?: { [string]: any },
|
||||||
hasSource?: boolean,
|
hasSource?: boolean,
|
||||||
isChannel?: boolean,
|
isChannel?: boolean,
|
||||||
channelIsMine?: boolean,
|
|
||||||
empty?: string,
|
empty?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,7 +129,6 @@ function ClaimListDiscover(props: Props) {
|
||||||
livestreamMap,
|
livestreamMap,
|
||||||
hasSource,
|
hasSource,
|
||||||
isChannel = false,
|
isChannel = false,
|
||||||
channelIsMine = false,
|
|
||||||
empty,
|
empty,
|
||||||
} = props;
|
} = props;
|
||||||
const didNavigateForward = history.action === 'PUSH';
|
const didNavigateForward = history.action === 'PUSH';
|
||||||
|
@ -514,7 +512,6 @@ function ClaimListDiscover(props: Props) {
|
||||||
liveLivestreamsFirst={liveLivestreamsFirst}
|
liveLivestreamsFirst={liveLivestreamsFirst}
|
||||||
livestreamMap={livestreamMap}
|
livestreamMap={livestreamMap}
|
||||||
searchOptions={options}
|
searchOptions={options}
|
||||||
channelIsMine={channelIsMine}
|
|
||||||
/>
|
/>
|
||||||
{loading && (
|
{loading && (
|
||||||
<div className="claim-grid">
|
<div className="claim-grid">
|
||||||
|
|
|
@ -2,35 +2,38 @@ import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
doCollectionEdit,
|
doCollectionEdit,
|
||||||
makeSelectClaimForUri,
|
makeSelectClaimForUri,
|
||||||
makeSelectClaimIsMine,
|
makeSelectFileInfoForUri,
|
||||||
|
doPrepareEdit,
|
||||||
makeSelectCollectionForIdHasClaimUrl,
|
makeSelectCollectionForIdHasClaimUrl,
|
||||||
makeSelectNameForCollectionId,
|
makeSelectNameForCollectionId,
|
||||||
makeSelectCollectionIsMine,
|
makeSelectCollectionIsMine,
|
||||||
COLLECTIONS_CONSTS,
|
COLLECTIONS_CONSTS,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
|
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 { doCommentModBlock, doCommentModUnBlock } from 'redux/actions/comments';
|
||||||
import { makeSelectChannelIsBlocked } from 'redux/selectors/comments';
|
import { makeSelectChannelIsBlocked } from 'redux/selectors/comments';
|
||||||
import { doOpenModal } from 'redux/actions/app';
|
|
||||||
import { doToast } from 'redux/actions/notifications';
|
import { doToast } from 'redux/actions/notifications';
|
||||||
import { makeSelectUserPropForProp } from 'redux/selectors/user';
|
import { makeSelectUserPropForProp } from 'redux/selectors/user';
|
||||||
import ClaimPreview from './view';
|
|
||||||
import * as USER from 'constants/user';
|
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 select = (state, props) => {
|
||||||
const claim = makeSelectClaimForUri(props.uri)(state);
|
const claim = makeSelectClaimForUri(props.uri)(state);
|
||||||
const permanentUri = claim && claim.permanent_url;
|
const permanentUri = claim && claim.permanent_url;
|
||||||
return {
|
return {
|
||||||
claim,
|
claim,
|
||||||
claimIsMine: props.channelIsMine
|
claimIsMine: makeSelectSigningIsMine(props.uri)(state),
|
||||||
? props.isRepost
|
|
||||||
? makeSelectClaimIsMine(props.uri)(state)
|
|
||||||
: true
|
|
||||||
: makeSelectClaimIsMine(props.uri)(state),
|
|
||||||
hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(COLLECTIONS_CONSTS.WATCH_LATER_ID, permanentUri)(state),
|
hasClaimInWatchLater: makeSelectCollectionForIdHasClaimUrl(COLLECTIONS_CONSTS.WATCH_LATER_ID, permanentUri)(state),
|
||||||
channelIsMuted: makeSelectChannelIsMuted(props.uri)(state),
|
channelIsMuted: makeSelectChannelIsMuted(props.uri)(state),
|
||||||
channelIsBlocked: makeSelectChannelIsBlocked(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),
|
claimInCollection: makeSelectCollectionForIdHasClaimUrl(props.collectionId, permanentUri)(state),
|
||||||
collectionName: makeSelectNameForCollectionId(props.collectionId)(state),
|
collectionName: makeSelectNameForCollectionId(props.collectionId)(state),
|
||||||
isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state),
|
isMyCollection: makeSelectCollectionIsMine(props.collectionId)(state),
|
||||||
|
@ -38,11 +41,26 @@ const select = (state, props) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(select, {
|
const perform = (dispatch) => ({
|
||||||
doToggleMuteChannel,
|
prepareEdit: (publishData, uri, fileInfo) => {
|
||||||
doCommentModBlock,
|
if (publishData.signing_channel) {
|
||||||
doCommentModUnBlock,
|
dispatch(doSetIncognito(false));
|
||||||
doCollectionEdit,
|
dispatch(doSetActiveChannel(publishData.signing_channel.claim_id));
|
||||||
doOpenModal,
|
} else {
|
||||||
doToast,
|
dispatch(doSetIncognito(true));
|
||||||
})(ClaimPreview);
|
}
|
||||||
|
|
||||||
|
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 Icon from 'component/common/icon';
|
||||||
import { generateShareUrl } from 'util/url';
|
import { generateShareUrl } from 'util/url';
|
||||||
import { useHistory } from 'react-router';
|
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 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 = {
|
type Props = {
|
||||||
uri: string,
|
uri: string,
|
||||||
|
channelUri: string,
|
||||||
claim: ?Claim,
|
claim: ?Claim,
|
||||||
|
openModal: (id: string, {}) => void,
|
||||||
inline?: boolean,
|
inline?: boolean,
|
||||||
claimIsMine: boolean,
|
|
||||||
channelIsMuted: boolean,
|
channelIsMuted: boolean,
|
||||||
channelIsBlocked: boolean,
|
channelIsBlocked: boolean,
|
||||||
doToggleMuteChannel: (string) => void,
|
doChannelMute: (string) => void,
|
||||||
|
doChannelUnmute: (string) => void,
|
||||||
doCommentModBlock: (string) => void,
|
doCommentModBlock: (string) => void,
|
||||||
doCommentModUnBlock: (string) => void,
|
doCommentModUnBlock: (string) => void,
|
||||||
channelIsMine: boolean,
|
|
||||||
isRepost: boolean,
|
isRepost: boolean,
|
||||||
doCollectionEdit: (string, any) => void,
|
doCollectionEdit: (string, any) => void,
|
||||||
hasClaimInWatchLater: boolean,
|
hasClaimInWatchLater: boolean,
|
||||||
doOpenModal: (string, {}) => void,
|
|
||||||
claimInCollection: boolean,
|
claimInCollection: boolean,
|
||||||
collectionName?: string,
|
collectionName?: string,
|
||||||
collectionId: string,
|
collectionId: string,
|
||||||
isMyCollection: boolean,
|
isMyCollection: boolean,
|
||||||
doToast: ({ message: string }) => void,
|
doToast: ({ message: string }) => void,
|
||||||
hasExperimentalUi: boolean,
|
hasExperimentalUi: boolean,
|
||||||
|
claimIsMine: boolean,
|
||||||
|
fileInfo: FileListItem,
|
||||||
|
prepareEdit: ({}, string, {}) => void,
|
||||||
|
isSubscribed: boolean,
|
||||||
|
doChannelSubscribe: (SubscriptionArgs) => void,
|
||||||
|
doChannelUnsubscribe: (SubscriptionArgs) => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ClaimMenuList(props: Props) {
|
function ClaimMenuList(props: Props) {
|
||||||
const {
|
const {
|
||||||
uri,
|
uri,
|
||||||
|
channelUri,
|
||||||
claim,
|
claim,
|
||||||
|
openModal,
|
||||||
inline = false,
|
inline = false,
|
||||||
claimIsMine,
|
doChannelMute,
|
||||||
doToggleMuteChannel,
|
doChannelUnmute,
|
||||||
channelIsMuted,
|
channelIsMuted,
|
||||||
channelIsBlocked,
|
channelIsBlocked,
|
||||||
doCommentModBlock,
|
doCommentModBlock,
|
||||||
doCommentModUnBlock,
|
doCommentModUnBlock,
|
||||||
doCollectionEdit,
|
doCollectionEdit,
|
||||||
hasClaimInWatchLater,
|
hasClaimInWatchLater,
|
||||||
doOpenModal,
|
|
||||||
collectionId,
|
collectionId,
|
||||||
collectionName,
|
collectionName,
|
||||||
isMyCollection,
|
isMyCollection,
|
||||||
doToast,
|
doToast,
|
||||||
hasExperimentalUi,
|
hasExperimentalUi,
|
||||||
|
claimIsMine,
|
||||||
|
fileInfo,
|
||||||
|
prepareEdit,
|
||||||
|
isSubscribed,
|
||||||
|
doChannelSubscribe,
|
||||||
|
doChannelUnsubscribe,
|
||||||
} = props;
|
} = 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 } = useHistory();
|
||||||
if (!claim) {
|
if (!claim) {
|
||||||
return null;
|
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 shareUrl: string = generateShareUrl(SHARE_DOMAIN, uri);
|
||||||
const isCollectionClaim = claim && claim.value_type === 'collection';
|
const isCollectionClaim = claim && claim.value_type === 'collection';
|
||||||
|
@ -78,8 +99,28 @@ function ClaimMenuList(props: Props) {
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
(claim.value.stream_type === 'audio' || claim.value.stream_type === 'video');
|
(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() {
|
function handleToggleMute() {
|
||||||
doToggleMuteChannel(channelUri);
|
if (channelIsMuted) {
|
||||||
|
doChannelUnmute(channelUri);
|
||||||
|
} else {
|
||||||
|
doChannelMute(channelUri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleToggleBlock() {
|
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() {
|
function handleCopyLink() {
|
||||||
navigator.clipboard.writeText(shareUrl);
|
navigator.clipboard.writeText(shareUrl);
|
||||||
}
|
}
|
||||||
|
@ -110,6 +185,29 @@ function ClaimMenuList(props: Props) {
|
||||||
<Icon size={20} icon={ICONS.MORE_VERTICAL} />
|
<Icon size={20} icon={ICONS.MORE_VERTICAL} />
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
<MenuList className="menu__list">
|
<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 && (
|
{hasExperimentalUi && (
|
||||||
<>
|
<>
|
||||||
{/* WATCH LATER */}
|
{/* WATCH LATER */}
|
||||||
|
@ -148,7 +246,7 @@ function ClaimMenuList(props: Props) {
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className="comment__menu-option"
|
className="comment__menu-option"
|
||||||
onSelect={() => doOpenModal(MODALS.COLLECTION_DELETE, { collectionId })}
|
onSelect={() => openModal(MODALS.COLLECTION_DELETE, { collectionId })}
|
||||||
>
|
>
|
||||||
<div className="menu__link">
|
<div className="menu__link">
|
||||||
<Icon aria-hidden icon={ICONS.DELETE} />
|
<Icon aria-hidden icon={ICONS.DELETE} />
|
||||||
|
@ -161,7 +259,7 @@ function ClaimMenuList(props: Props) {
|
||||||
{isPlayable && (
|
{isPlayable && (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
className="comment__menu-option"
|
className="comment__menu-option"
|
||||||
onSelect={() => doOpenModal(MODALS.COLLECTION_ADD, { uri, type: 'playlist' })}
|
onSelect={() => openModal(MODALS.COLLECTION_ADD, { uri, type: 'playlist' })}
|
||||||
>
|
>
|
||||||
<div className="menu__link">
|
<div className="menu__link">
|
||||||
<Icon aria-hidden icon={ICONS.STACK} />
|
<Icon aria-hidden icon={ICONS.STACK} />
|
||||||
|
@ -169,10 +267,11 @@ function ClaimMenuList(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
|
<hr className="menu__separator" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<hr className="menu__separator" />
|
|
||||||
{channelUri && !claimIsMine && !isMyCollection && (
|
{channelUri && !claimIsMine && !isMyCollection ? !incognito && (
|
||||||
<>
|
<>
|
||||||
<MenuItem className="comment__menu-option" onSelect={handleToggleBlock}>
|
<MenuItem className="comment__menu-option" onSelect={handleToggleBlock}>
|
||||||
<div className="menu__link">
|
<div className="menu__link">
|
||||||
|
@ -187,10 +286,27 @@ function ClaimMenuList(props: Props) {
|
||||||
{channelIsMuted ? __('Unmute Channel') : __('Mute Channel')}
|
{channelIsMuted ? __('Unmute Channel') : __('Mute Channel')}
|
||||||
</div>
|
</div>
|
||||||
</MenuItem>
|
</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}>
|
<MenuItem className="comment__menu-option" onSelect={handleCopyLink}>
|
||||||
<div className="menu__link">
|
<div className="menu__link">
|
||||||
|
|
|
@ -161,6 +161,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
collectionParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, collectionId);
|
collectionParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, collectionId);
|
||||||
navigateUrl = navigateUrl + `?` + collectionParams.toString();
|
navigateUrl = navigateUrl + `?` + collectionParams.toString();
|
||||||
}
|
}
|
||||||
|
const channelUri = claim && (signingChannel ? signingChannel.permanent_url : claim.permanent_url);
|
||||||
const navLinkProps = {
|
const navLinkProps = {
|
||||||
to: navigateUrl,
|
to: navigateUrl,
|
||||||
onClick: (e) => e.stopPropagation(),
|
onClick: (e) => e.stopPropagation(),
|
||||||
|
@ -421,7 +422,7 @@ const ClaimPreview = forwardRef<any, {}>((props: Props, ref: any) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!hideMenu && <ClaimMenuList uri={uri} collectionId={collectionId} />}
|
{!hideMenu && <ClaimMenuList uri={uri} collectionId={collectionId} channelUri={channelUri} />}
|
||||||
</>
|
</>
|
||||||
</WrapperElement>
|
</WrapperElement>
|
||||||
);
|
);
|
||||||
|
|
|
@ -43,7 +43,6 @@ type Props = {
|
||||||
showHiddenByUser?: boolean,
|
showHiddenByUser?: boolean,
|
||||||
properties?: (Claim) => void,
|
properties?: (Claim) => void,
|
||||||
live?: boolean,
|
live?: boolean,
|
||||||
channelIsMine?: boolean,
|
|
||||||
collectionId?: string,
|
collectionId?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,7 +66,6 @@ function ClaimPreviewTile(props: Props) {
|
||||||
showHiddenByUser,
|
showHiddenByUser,
|
||||||
properties,
|
properties,
|
||||||
live,
|
live,
|
||||||
channelIsMine,
|
|
||||||
collectionId,
|
collectionId,
|
||||||
} = props;
|
} = props;
|
||||||
const isRepost = claim && claim.repost_channel_url;
|
const isRepost = claim && claim.repost_channel_url;
|
||||||
|
@ -100,11 +98,8 @@ function ClaimPreviewTile(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let channelUri;
|
|
||||||
const signingChannel = claim && claim.signing_channel;
|
const signingChannel = claim && claim.signing_channel;
|
||||||
if (signingChannel) {
|
const channelUri = signingChannel && signingChannel.permanent_url;
|
||||||
channelUri = signingChannel.permanent_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleClick(e) {
|
function handleClick(e) {
|
||||||
if (navigateUrl) {
|
if (navigateUrl) {
|
||||||
|
@ -219,7 +214,7 @@ function ClaimPreviewTile(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* CHECK CLAIM MENU LIST PARAMS (IS REPOST?) */}
|
{/* 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>
|
</h2>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectChannelPermUrlForClaimUri, makeSelectClaimIsMine, makeSelectClaimForUri } from 'lbry-redux';
|
import { makeSelectChannelPermUrlForClaimUri, makeSelectClaimIsMine, makeSelectClaimForUri } from 'lbry-redux';
|
||||||
import { doCommentAbandon, doCommentPin, doCommentList, doCommentModBlock } from 'redux/actions/comments';
|
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 { doSetActiveChannel } from 'redux/actions/app';
|
||||||
import { doSetPlayingUri } from 'redux/actions/content';
|
import { doSetPlayingUri } from 'redux/actions/content';
|
||||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||||
|
@ -19,7 +19,7 @@ const select = (state, props) => ({
|
||||||
const perform = (dispatch) => ({
|
const perform = (dispatch) => ({
|
||||||
clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
|
clearPlayingUri: () => dispatch(doSetPlayingUri({ uri: null })),
|
||||||
deleteComment: (commentId, creatorChannelUrl) => dispatch(doCommentAbandon(commentId, creatorChannelUrl)),
|
deleteComment: (commentId, creatorChannelUrl) => dispatch(doCommentAbandon(commentId, creatorChannelUrl)),
|
||||||
blockChannel: (channelUri) => dispatch(doToggleMuteChannel(channelUri)),
|
muteChannel: (channelUri) => dispatch(doChannelMute(channelUri)),
|
||||||
pinComment: (commentId, remove) => dispatch(doCommentPin(commentId, remove)),
|
pinComment: (commentId, remove) => dispatch(doCommentPin(commentId, remove)),
|
||||||
fetchComments: (uri) => dispatch(doCommentList(uri)),
|
fetchComments: (uri) => dispatch(doCommentList(uri)),
|
||||||
// setActiveChannel: channelId => dispatch(doSetActiveChannel(channelId)),
|
// setActiveChannel: channelId => dispatch(doSetActiveChannel(channelId)),
|
||||||
|
|
|
@ -15,7 +15,7 @@ type Props = {
|
||||||
linkedComment?: any,
|
linkedComment?: any,
|
||||||
isPinned: boolean,
|
isPinned: boolean,
|
||||||
pinComment: (string, boolean) => Promise<any>,
|
pinComment: (string, boolean) => Promise<any>,
|
||||||
blockChannel: (string) => void,
|
muteChannel: (string) => void,
|
||||||
fetchComments: (string) => void,
|
fetchComments: (string) => void,
|
||||||
handleEditComment: () => void,
|
handleEditComment: () => void,
|
||||||
contentChannelPermanentUrl: any,
|
contentChannelPermanentUrl: any,
|
||||||
|
@ -34,7 +34,7 @@ function CommentMenuList(props: Props) {
|
||||||
commentIsMine,
|
commentIsMine,
|
||||||
commentId,
|
commentId,
|
||||||
deleteComment,
|
deleteComment,
|
||||||
blockChannel,
|
muteChannel,
|
||||||
pinComment,
|
pinComment,
|
||||||
clearPlayingUri,
|
clearPlayingUri,
|
||||||
activeChannelClaim,
|
activeChannelClaim,
|
||||||
|
@ -66,7 +66,7 @@ function CommentMenuList(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCommentMute() {
|
function handleCommentMute() {
|
||||||
blockChannel(authorUri);
|
muteChannel(authorUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -191,8 +191,7 @@ function ChannelPage(props: Props) {
|
||||||
{!channelIsBlackListed && <ShareButton uri={uri} />}
|
{!channelIsBlackListed && <ShareButton uri={uri} />}
|
||||||
{!(isBlocked || isMuted) && <ClaimSupportButton uri={uri} />}
|
{!(isBlocked || isMuted) && <ClaimSupportButton uri={uri} />}
|
||||||
{!(isBlocked || isMuted) && (!channelIsBlackListed || isSubscribed) && <SubscribeButton uri={permanentUrl} />}
|
{!(isBlocked || isMuted) && (!channelIsBlackListed || isSubscribed) && <SubscribeButton uri={permanentUrl} />}
|
||||||
{/* TODO: add channel collections <ClaimCollectionAddButton uri={uri} fileAction /> */}
|
<ClaimMenuList uri={claim.permanent_url} channelUri={claim.permanent_url} inline />
|
||||||
<ClaimMenuList uri={claim.permanent_url} inline />
|
|
||||||
</div>
|
</div>
|
||||||
{cover && <img className={classnames('channel-cover__custom')} src={cover} />}
|
{cover && <img className={classnames('channel-cover__custom')} src={cover} />}
|
||||||
<div className="channel__primary-info">
|
<div className="channel__primary-info">
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
import { selectPrefsReady } from 'redux/selectors/sync';
|
import { selectPrefsReady } from 'redux/selectors/sync';
|
||||||
import { doAlertWaitingForSync } from 'redux/actions/app';
|
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 state = getState();
|
||||||
const ready = selectPrefsReady(state);
|
const ready = selectPrefsReady(state);
|
||||||
|
|
||||||
|
@ -17,4 +19,23 @@ export const doToggleMuteChannel = (uri: string) => (dispatch: Dispatch, getStat
|
||||||
uri,
|
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
|
// 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) => {
|
return async (dispatch: Dispatch, getState: GetState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const myChannels = selectMyChannelClaims(state);
|
const myChannels = selectMyChannelClaims(state);
|
||||||
|
@ -564,9 +564,11 @@ export function doCommentModToggleBlock(channelUri: string, unblock: boolean = f
|
||||||
data: { channelUri },
|
data: { channelUri },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!unblock) {
|
dispatch(doToast({
|
||||||
dispatch(doToast({ message: __('Channel blocked. You will not see them again.') }));
|
message: __(!unblock ? 'Channel blocked. They will not interact with you again.' : 'Channel unblocked!'),
|
||||||
}
|
linkText: __(showLink ? 'See All' : ''),
|
||||||
|
linkTarget: '/settings/block_and_mute',
|
||||||
|
}));
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
dispatch({
|
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: 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: 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 * as ACTIONS from 'constants/action_types';
|
||||||
import REWARDS from 'rewards';
|
import REWARDS from 'rewards';
|
||||||
import { Lbryio } from 'lbryinc';
|
import { Lbryio } from 'lbryinc';
|
||||||
import { doClaimRewardType } from 'redux/actions/rewards';
|
import { doClaimRewardType } from 'redux/actions/rewards';
|
||||||
import { parseURI } from 'lbry-redux';
|
import { parseURI } from 'lbry-redux';
|
||||||
import { doAlertWaitingForSync } from 'redux/actions/app';
|
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 {
|
const {
|
||||||
settings: { daemonSettings },
|
settings: { daemonSettings },
|
||||||
sync: { prefsReady: ready },
|
sync: { prefsReady: ready },
|
||||||
|
@ -18,19 +27,23 @@ export const doChannelSubscribe = subscription => (dispatch, getState) => {
|
||||||
const { share_usage_data: shareSetting } = daemonSettings;
|
const { share_usage_data: shareSetting } = daemonSettings;
|
||||||
const isSharingData = shareSetting || IS_WEB;
|
const isSharingData = shareSetting || IS_WEB;
|
||||||
|
|
||||||
|
if (!isSubscribed) {
|
||||||
const subscriptionUri = subscription.uri;
|
const subscriptionUri = subscription.uri;
|
||||||
if (!subscriptionUri.startsWith('lbry://')) {
|
if (!subscriptionUri.startsWith('lbry://')) {
|
||||||
throw Error(`Subscription uris must include the "lbry://" prefix.\nTried to subscribe to ${subscriptionUri}`);
|
throw Error(`Subscription uris must include the "lbry://" prefix.\nTried to subscribe to ${subscriptionUri}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CHANNEL_SUBSCRIBE,
|
type: !isSubscribed ? ACTIONS.CHANNEL_SUBSCRIBE : ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||||
data: subscription,
|
data: subscription,
|
||||||
});
|
});
|
||||||
|
|
||||||
// if the user isn't sharing data, keep the subscriptions entirely in the app
|
// if the user isn't sharing data, keep the subscriptions entirely in the app
|
||||||
if (isSharingData || IS_WEB) {
|
if (isSharingData || IS_WEB) {
|
||||||
const { channelClaimId } = parseURI(subscription.uri);
|
const { channelClaimId } = parseURI(subscription.uri);
|
||||||
|
|
||||||
|
if (!isSubscribed) {
|
||||||
// They are sharing data, we can store their subscriptions in our internal database
|
// They are sharing data, we can store their subscriptions in our internal database
|
||||||
Lbryio.call('subscription', 'new', {
|
Lbryio.call('subscription', 'new', {
|
||||||
channel_name: subscription.channelName,
|
channel_name: subscription.channelName,
|
||||||
|
@ -39,31 +52,27 @@ export const doChannelSubscribe = subscription => (dispatch, getState) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatch(doClaimRewardType(REWARDS.TYPE_SUBSCRIPTION, { failSilently: true }));
|
dispatch(doClaimRewardType(REWARDS.TYPE_SUBSCRIPTION, { failSilently: true }));
|
||||||
}
|
} else {
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
Lbryio.call('subscription', 'delete', {
|
Lbryio.call('subscription', 'delete', {
|
||||||
claim_id: channelClaimId,
|
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,
|
parseURI,
|
||||||
makeSelectContentTypeForUri,
|
makeSelectContentTypeForUri,
|
||||||
makeSelectFileNameForUri,
|
makeSelectFileNameForUri,
|
||||||
|
normalizeURI,
|
||||||
|
selectMyActiveClaims,
|
||||||
} from 'lbry-redux';
|
} from 'lbry-redux';
|
||||||
import { makeSelectRecommendedContentForUri } from 'redux/selectors/search';
|
import { makeSelectRecommendedContentForUri } from 'redux/selectors/search';
|
||||||
import { selectMutedChannels } from 'redux/selectors/blocked';
|
import { selectMutedChannels } from 'redux/selectors/blocked';
|
||||||
|
@ -243,3 +245,22 @@ export const makeSelectInsufficientCreditsForUri = (uri: string) =>
|
||||||
return !isMine && costInfo && costInfo.cost > 0 && costInfo.cost > balance;
|
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…
Add table
Reference in a new issue