Limit channel-creation count from the UI (#886)
## Issue 534 prevent new channel creation over x channels ## Notes Also handled from the API call (`doCreateChannel`) in case there are other UI components that create channels.
This commit is contained in:
parent
0774090bdc
commit
80d4d8c57c
7 changed files with 44 additions and 4 deletions
|
@ -88,6 +88,7 @@ ENABLE_NO_SOURCE_CLAIMS=true
|
||||||
ENABLE_PREROLL_ADS=true
|
ENABLE_PREROLL_ADS=true
|
||||||
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS=4
|
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS=4
|
||||||
CHANNEL_STAKED_LEVEL_LIVESTREAM=5
|
CHANNEL_STAKED_LEVEL_LIVESTREAM=5
|
||||||
|
CHANNEL_CREATION_LIMIT=5
|
||||||
WEB_PUBLISH_SIZE_LIMIT_GB=4
|
WEB_PUBLISH_SIZE_LIMIT_GB=4
|
||||||
LIGHTHOUSE_DEFAULT_TYPES=audio,video
|
LIGHTHOUSE_DEFAULT_TYPES=audio,video
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,10 @@ const config = {
|
||||||
ENABLE_PREROLL_ADS: process.env.ENABLE_PREROLL_ADS === 'true',
|
ENABLE_PREROLL_ADS: process.env.ENABLE_PREROLL_ADS === 'true',
|
||||||
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS: process.env.CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS,
|
CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS: process.env.CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS,
|
||||||
CHANNEL_STAKED_LEVEL_LIVESTREAM: process.env.CHANNEL_STAKED_LEVEL_LIVESTREAM,
|
CHANNEL_STAKED_LEVEL_LIVESTREAM: process.env.CHANNEL_STAKED_LEVEL_LIVESTREAM,
|
||||||
|
CHANNEL_CREATION_LIMIT: process.env.CHANNEL_CREATION_LIMIT,
|
||||||
WEB_PUBLISH_SIZE_LIMIT_GB: process.env.WEB_PUBLISH_SIZE_LIMIT_GB,
|
WEB_PUBLISH_SIZE_LIMIT_GB: process.env.WEB_PUBLISH_SIZE_LIMIT_GB,
|
||||||
LOADING_BAR_COLOR: process.env.LOADING_BAR_COLOR,
|
LOADING_BAR_COLOR: process.env.LOADING_BAR_COLOR,
|
||||||
SIMPLE_SITE: process.env.SIMPLE_SITE === 'true',
|
SIMPLE_SITE: process.env.SIMPLE_SITE === 'true',
|
||||||
SHOW_ADS: process.env.SHOW_ADS === 'true',
|
SHOW_ADS: process.env.SHOW_ADS === 'true',
|
||||||
PINNED_URI_1: process.env.PINNED_URI_1,
|
PINNED_URI_1: process.env.PINNED_URI_1,
|
||||||
PINNED_LABEL_1: process.env.PINNED_LABEL_1,
|
PINNED_LABEL_1: process.env.PINNED_LABEL_1,
|
||||||
|
|
|
@ -1413,6 +1413,7 @@
|
||||||
"Change to list layout": "Change to list layout",
|
"Change to list layout": "Change to list layout",
|
||||||
"Change to tile layout": "Change to tile layout",
|
"Change to tile layout": "Change to tile layout",
|
||||||
"Create a channel": "Create a channel",
|
"Create a channel": "Create a channel",
|
||||||
|
"Sorry, you have exceeded the channel creation limit.": "Sorry, you have exceeded the channel creation limit.",
|
||||||
"Credit Details": "Credit Details",
|
"Credit Details": "Credit Details",
|
||||||
"LBRY Credits": "LBRY Credits",
|
"LBRY Credits": "LBRY Credits",
|
||||||
"Mark as read": "Mark as read",
|
"Mark as read": "Mark as read",
|
||||||
|
|
|
@ -3,11 +3,13 @@ import { connect } from 'react-redux';
|
||||||
import { selectBalance } from 'redux/selectors/wallet';
|
import { selectBalance } from 'redux/selectors/wallet';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
import { doClaimRewardType } from 'redux/actions/rewards';
|
import { doClaimRewardType } from 'redux/actions/rewards';
|
||||||
|
import { selectIsMyChannelCountOverLimit } from 'redux/selectors/claims';
|
||||||
import ChannelNew from './view';
|
import ChannelNew from './view';
|
||||||
|
|
||||||
const select = (state) => ({
|
const select = (state) => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
isAuthenticated: selectUserVerifiedEmail(state),
|
isAuthenticated: selectUserVerifiedEmail(state),
|
||||||
|
channelCountOverLimit: selectIsMyChannelCountOverLimit(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, (dispatch) => ({
|
export default connect(select, (dispatch) => ({
|
||||||
|
|
|
@ -10,10 +10,11 @@ type Props = {
|
||||||
balance: number,
|
balance: number,
|
||||||
claimConfirmEmailReward: () => void,
|
claimConfirmEmailReward: () => void,
|
||||||
isAuthenticated: boolean,
|
isAuthenticated: boolean,
|
||||||
|
channelCountOverLimit: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChannelNew(props: Props) {
|
function ChannelNew(props: Props) {
|
||||||
const { balance, claimConfirmEmailReward, isAuthenticated } = props;
|
const { balance, claimConfirmEmailReward, isAuthenticated, channelCountOverLimit } = props;
|
||||||
const { push, location } = useHistory();
|
const { push, location } = useHistory();
|
||||||
const urlSearchParams = new URLSearchParams(location.search);
|
const urlSearchParams = new URLSearchParams(location.search);
|
||||||
const redirectUrl = urlSearchParams.get('redirect');
|
const redirectUrl = urlSearchParams.get('redirect');
|
||||||
|
@ -29,8 +30,12 @@ function ChannelNew(props: Props) {
|
||||||
<Page noSideNavigation noFooter backout={{ title: __('Create a channel'), backLabel: __('Cancel') }}>
|
<Page noSideNavigation noFooter backout={{ title: __('Create a channel'), backLabel: __('Cancel') }}>
|
||||||
{emptyBalance && <YrblWalletEmpty />}
|
{emptyBalance && <YrblWalletEmpty />}
|
||||||
|
|
||||||
|
{channelCountOverLimit && (
|
||||||
|
<div className="empty empty--centered">{__('Sorry, you have exceeded the channel creation limit.')}</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<ChannelEdit
|
<ChannelEdit
|
||||||
disabled={emptyBalance}
|
disabled={emptyBalance || channelCountOverLimit}
|
||||||
onDone={() => {
|
onDone={() => {
|
||||||
push(redirectUrl || `/$/${PAGES.CHANNELS}`);
|
push(redirectUrl || `/$/${PAGES.CHANNELS}`);
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
selectMyChannelClaims,
|
selectMyChannelClaims,
|
||||||
selectPendingClaimsById,
|
selectPendingClaimsById,
|
||||||
selectClaimIsMine,
|
selectClaimIsMine,
|
||||||
|
selectIsMyChannelCountOverLimit,
|
||||||
} from 'redux/selectors/claims';
|
} from 'redux/selectors/claims';
|
||||||
|
|
||||||
import { doFetchTxoPage } from 'redux/actions/wallet';
|
import { doFetchTxoPage } from 'redux/actions/wallet';
|
||||||
|
@ -390,11 +391,22 @@ export function doClearChannelErrors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function doCreateChannel(name: string, amount: number, optionalParams: any, onConfirm: any) {
|
export function doCreateChannel(name: string, amount: number, optionalParams: any, onConfirm: any) {
|
||||||
return (dispatch: Dispatch) => {
|
return (dispatch: Dispatch, getState: GetState) => {
|
||||||
|
const state = getState();
|
||||||
|
const channelCountOverLimit = selectIsMyChannelCountOverLimit(state);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ACTIONS.CREATE_CHANNEL_STARTED,
|
type: ACTIONS.CREATE_CHANNEL_STARTED,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (channelCountOverLimit) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.CREATE_CHANNEL_FAILED,
|
||||||
|
data: 'Channel limit exceeded',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const createParams: {
|
const createParams: {
|
||||||
name: string,
|
name: string,
|
||||||
bid: string,
|
bid: string,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import { CHANNEL_CREATION_LIMIT } from 'config';
|
||||||
import { normalizeURI, parseURI, isURIValid } from 'util/lbryURI';
|
import { normalizeURI, parseURI, isURIValid } from 'util/lbryURI';
|
||||||
|
import { selectYoutubeChannels } from 'redux/selectors/user';
|
||||||
import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
|
import { selectSupportsByOutpoint } from 'redux/selectors/wallet';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { createCachedSelector } from 're-reselect';
|
import { createCachedSelector } from 're-reselect';
|
||||||
|
@ -773,3 +775,19 @@ export const selectUpdatingCollection = (state: State) => selectState(state).upd
|
||||||
export const selectUpdateCollectionError = (state: State) => selectState(state).updateCollectionError;
|
export const selectUpdateCollectionError = (state: State) => selectState(state).updateCollectionError;
|
||||||
export const selectCreatingCollection = (state: State) => selectState(state).creatingCollection;
|
export const selectCreatingCollection = (state: State) => selectState(state).creatingCollection;
|
||||||
export const selectCreateCollectionError = (state: State) => selectState(state).createCollectionError;
|
export const selectCreateCollectionError = (state: State) => selectState(state).createCollectionError;
|
||||||
|
|
||||||
|
export const selectIsMyChannelCountOverLimit = createSelector(
|
||||||
|
selectMyChannelClaimIds,
|
||||||
|
selectYoutubeChannels,
|
||||||
|
(myClaimIds, ytChannels: ?Array<{ channel_claim_id: string }>) => {
|
||||||
|
if (myClaimIds) {
|
||||||
|
if (ytChannels && ytChannels.length > 0) {
|
||||||
|
// $FlowFixMe - null 'ytChannels' already excluded
|
||||||
|
const ids = myClaimIds.filter((id) => !ytChannels.some((yt) => yt.channel_claim_id === id));
|
||||||
|
return ids.length > CHANNEL_CREATION_LIMIT;
|
||||||
|
}
|
||||||
|
return myClaimIds.length > CHANNEL_CREATION_LIMIT;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
Loading…
Reference in a new issue