From f5125b25c24e0f6860c6fc05d64e69f806baa0c9 Mon Sep 17 00:00:00 2001 From: seanyesmunt Date: Thu, 8 Apr 2021 15:19:14 -0400 Subject: [PATCH] update livestream eligibilty add CHANNEL_STAKED_LEVEL_LIVESTREAM to config set to level 5 use odysee_live_enabled tag on users insead of experimental_ui --- .env.defaults | 1 + config.js | 1 + flow-typed/user.js | 2 + ui/component/header/index.js | 3 +- ui/component/header/view.jsx | 11 ++++- ui/component/publishForm/index.js | 8 +++- ui/component/publishForm/view.jsx | 22 ++++++---- ui/redux/selectors/app.js | 73 +++++++++++++++++++------------ 8 files changed, 80 insertions(+), 41 deletions(-) diff --git a/.env.defaults b/.env.defaults index 757306814..08fe0410d 100644 --- a/.env.defaults +++ b/.env.defaults @@ -32,6 +32,7 @@ ENABLE_FILE_REACTIONS=false ENABLE_CREATOR_REACTIONS=false ENABLE_NO_SOURCE_CLAIMS=false CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS=4 +CHANNEL_STAKED_LEVEL_LIVESTREAM=5 # OG OG_TITLE_SUFFIX=| lbry.tv diff --git a/config.js b/config.js index be6d23e47..9f07d391e 100644 --- a/config.js +++ b/config.js @@ -37,6 +37,7 @@ const config = { ENABLE_CREATOR_REACTIONS: process.env.ENABLE_CREATOR_REACTIONS === 'true', ENABLE_NO_SOURCE_CLAIMS: process.env.ENABLE_NO_SOURCE_CLAIMS === 'true', CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS: process.env.CHANNEL_STAKED_LEVEL_VIDEO_COMMENTS, + CHANNEL_STAKED_LEVEL_LIVESTREAM: process.env.CHANNEL_STAKED_LEVEL_LIVESTREAM, SIMPLE_SITE: process.env.SIMPLE_SITE === 'true', SHOW_ADS: process.env.SHOW_ADS === 'true', PINNED_URI_1: process.env.PINNED_URI_1, diff --git a/flow-typed/user.js b/flow-typed/user.js index b77bc64ee..28f7d04d1 100644 --- a/flow-typed/user.js +++ b/flow-typed/user.js @@ -28,4 +28,6 @@ declare type User = { device_types: Array, lbry_first_approved: boolean, experimental_ui: boolean, + odysee_live_enabled: boolean, + odysee_live_disabled: boolean, }; diff --git a/ui/component/header/index.js b/ui/component/header/index.js index b0cf8e735..2356298e3 100644 --- a/ui/component/header/index.js +++ b/ui/component/header/index.js @@ -7,7 +7,7 @@ import { doClearEmailEntry, doClearPasswordEntry } from 'redux/actions/user'; import { doSetClientSetting } from 'redux/actions/settings'; import { doSignOut, doOpenModal } from 'redux/actions/app'; import { makeSelectClientSetting, selectLanguage } from 'redux/selectors/settings'; -import { selectHasNavigated, selectActiveChannelClaim } from 'redux/selectors/app'; +import { selectHasNavigated, selectActiveChannelClaim, selectActiveChannelStakedLevel } from 'redux/selectors/app'; import Header from './view'; const select = (state) => ({ @@ -25,6 +25,7 @@ const select = (state) => ({ hasNavigated: selectHasNavigated(state), user: selectUser(state), activeChannelClaim: selectActiveChannelClaim(state), + activeChannelStakedLevel: selectActiveChannelStakedLevel(state), }); const perform = (dispatch) => ({ diff --git a/ui/component/header/view.jsx b/ui/component/header/view.jsx index 0af8f65f4..f599119a1 100644 --- a/ui/component/header/view.jsx +++ b/ui/component/header/view.jsx @@ -1,5 +1,5 @@ // @flow -import { LOGO_TITLE, ENABLE_NO_SOURCE_CLAIMS } from 'config'; +import { LOGO_TITLE, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config'; import * as ICONS from 'constants/icons'; import { SETTINGS } from 'lbry-redux'; import * as PAGES from 'constants/pages'; @@ -61,6 +61,7 @@ type Props = { isAbsoluteSideNavHidden: boolean, hideCancel: boolean, activeChannelClaim: ?ChannelClaim, + activeChannelStakedLevel: number, }; const Header = (props: Props) => { @@ -89,6 +90,7 @@ const Header = (props: Props) => { user, hideCancel, activeChannelClaim, + activeChannelStakedLevel, } = props; const isMobile = useIsMobile(); // on the verify page don't let anyone escape other than by closing the tab to keep session data consistent @@ -99,7 +101,12 @@ const Header = (props: Props) => { const hasBackout = Boolean(backout); const { backLabel, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {}; const notificationsEnabled = (user && user.experimental_ui) || false; - const livestreamEnabled = (ENABLE_NO_SOURCE_CLAIMS && user && user.experimental_ui) || false; + const livestreamEnabled = Boolean( + ENABLE_NO_SOURCE_CLAIMS && + user && + !user.odysee_live_disabled && + (activeChannelStakedLevel >= CHANNEL_STAKED_LEVEL_LIVESTREAM || user.odysee_live_enabled) + ); const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url; // Sign out if they click the "x" when they are on the password prompt diff --git a/ui/component/publishForm/index.js b/ui/component/publishForm/index.js index af8d06050..e822f68b1 100644 --- a/ui/component/publishForm/index.js +++ b/ui/component/publishForm/index.js @@ -15,7 +15,12 @@ import { } from 'lbry-redux'; import { doPublishDesktop } from 'redux/actions/publish'; import { selectUnclaimedRewardValue } from 'redux/selectors/rewards'; -import { selectModal, selectActiveChannelClaim, selectIncognito } from 'redux/selectors/app'; +import { + selectModal, + selectActiveChannelClaim, + selectIncognito, + selectActiveChannelStakedLevel, +} from 'redux/selectors/app'; import { makeSelectClientSetting } from 'redux/selectors/settings'; import PublishPage from './view'; import { selectUser } from 'redux/selectors/user'; @@ -36,6 +41,7 @@ const select = (state) => ({ enablePublishPreview: makeSelectClientSetting(SETTINGS.ENABLE_PUBLISH_PREVIEW)(state), activeChannelClaim: selectActiveChannelClaim(state), incognito: selectIncognito(state), + activeChannelStakedLevel: selectActiveChannelStakedLevel(state), }); const perform = (dispatch) => ({ diff --git a/ui/component/publishForm/view.jsx b/ui/component/publishForm/view.jsx index f90aad531..ccce9df6d 100644 --- a/ui/component/publishForm/view.jsx +++ b/ui/component/publishForm/view.jsx @@ -8,7 +8,7 @@ File upload is carried out in the background by that function. */ -import { SITE_NAME, ENABLE_NO_SOURCE_CLAIMS, SIMPLE_SITE } from 'config'; +import { SITE_NAME, ENABLE_NO_SOURCE_CLAIMS, SIMPLE_SITE, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config'; import React, { useEffect } from 'react'; import { buildURI, isURIValid, isNameValid, THUMBNAIL_STATUSES } from 'lbry-redux'; import Button from 'component/button'; @@ -80,7 +80,8 @@ type Props = { enablePublishPreview: boolean, activeChannelClaim: ?ChannelClaim, incognito: boolean, - user: ?{ experimental_ui: boolean }, + user: ?User, + activeChannelStakedLevel: number, }; function PublishForm(props: Props) { @@ -112,16 +113,21 @@ function PublishForm(props: Props) { activeChannelClaim, incognito, user, + activeChannelStakedLevel, } = props; const { replace, location } = useHistory(); const urlParams = new URLSearchParams(location.search); const uploadType = urlParams.get('type'); + const livestreamEnabled = + ENABLE_NO_SOURCE_CLAIMS && + user && + !user.odysee_live_disabled && + (activeChannelStakedLevel >= CHANNEL_STAKED_LEVEL_LIVESTREAM || user.odysee_live_enabled); // $FlowFixMe - const MODES = - ENABLE_NO_SOURCE_CLAIMS && user && user.experimental_ui - ? Object.values(PUBLISH_MODES) - : Object.values(PUBLISH_MODES).filter((mode) => mode !== PUBLISH_MODES.LIVESTREAM); + const MODES = livestreamEnabled + ? Object.values(PUBLISH_MODES) + : Object.values(PUBLISH_MODES).filter((mode) => mode !== PUBLISH_MODES.LIVESTREAM); const MODE_TO_I18N_STR = { [PUBLISH_MODES.FILE]: SIMPLE_SITE ? 'Video' : 'File', @@ -304,14 +310,14 @@ function PublishForm(props: Props) { return; } // LiveStream publish - if (_uploadType === PUBLISH_MODES.LIVESTREAM.toLowerCase()) { + if (_uploadType === PUBLISH_MODES.LIVESTREAM.toLowerCase() && livestreamEnabled) { setMode(PUBLISH_MODES.LIVESTREAM); return; } // Default to standard file publish setMode(PUBLISH_MODES.FILE); - }, [uploadType]); + }, [uploadType, livestreamEnabled]); useEffect(() => { if (!uploadType) return; diff --git a/ui/redux/selectors/app.js b/ui/redux/selectors/app.js index 0cf2b778b..e433ba535 100644 --- a/ui/redux/selectors/app.js +++ b/ui/redux/selectors/app.js @@ -1,11 +1,11 @@ import { createSelector } from 'reselect'; -import { selectClaimsById, selectMyChannelClaims } from 'lbry-redux'; +import { selectClaimsById, selectMyChannelClaims, makeSelectStakedLevelForChannelUri } from 'lbry-redux'; -export const selectState = state => state.app || {}; +export const selectState = (state) => state.app || {}; -export const selectPlatform = createSelector(selectState, state => state.platform); +export const selectPlatform = createSelector(selectState, (state) => state.platform); -export const selectUpdateUrl = createSelector(selectPlatform, platform => { +export const selectUpdateUrl = createSelector(selectPlatform, (platform) => { switch (platform) { case 'darwin': return 'https://lbry.com/get/lbry.dmg'; @@ -18,11 +18,11 @@ export const selectUpdateUrl = createSelector(selectPlatform, platform => { } }); -export const selectHasClickedComment = createSelector(selectState, state => state.hasClickedComment); +export const selectHasClickedComment = createSelector(selectState, (state) => state.hasClickedComment); -export const selectRemoteVersion = createSelector(selectState, state => state.remoteVersion); +export const selectRemoteVersion = createSelector(selectState, (state) => state.remoteVersion); -export const selectIsUpgradeAvailable = createSelector(selectState, state => state.isUpgradeAvailable); +export const selectIsUpgradeAvailable = createSelector(selectState, (state) => state.isUpgradeAvailable); export const selectUpgradeFilename = createSelector(selectPlatform, selectRemoteVersion, (platform, version) => { switch (platform) { @@ -37,29 +37,29 @@ export const selectUpgradeFilename = createSelector(selectPlatform, selectRemote } }); -export const selectDownloadProgress = createSelector(selectState, state => state.downloadProgress); +export const selectDownloadProgress = createSelector(selectState, (state) => state.downloadProgress); -export const selectDownloadComplete = createSelector(selectState, state => state.upgradeDownloadCompleted); +export const selectDownloadComplete = createSelector(selectState, (state) => state.upgradeDownloadCompleted); -export const selectIsUpgradeSkipped = createSelector(selectState, state => state.isUpgradeSkipped); +export const selectIsUpgradeSkipped = createSelector(selectState, (state) => state.isUpgradeSkipped); -export const selectUpgradeDownloadPath = createSelector(selectState, state => state.downloadPath); +export const selectUpgradeDownloadPath = createSelector(selectState, (state) => state.downloadPath); -export const selectUpgradeDownloadItem = createSelector(selectState, state => state.downloadItem); +export const selectUpgradeDownloadItem = createSelector(selectState, (state) => state.downloadItem); -export const selectAutoUpdateDownloaded = createSelector(selectState, state => state.autoUpdateDownloaded); +export const selectAutoUpdateDownloaded = createSelector(selectState, (state) => state.autoUpdateDownloaded); -export const selectAutoUpdateDeclined = createSelector(selectState, state => state.autoUpdateDeclined); +export const selectAutoUpdateDeclined = createSelector(selectState, (state) => state.autoUpdateDeclined); -export const selectDaemonVersionMatched = createSelector(selectState, state => state.daemonVersionMatched); +export const selectDaemonVersionMatched = createSelector(selectState, (state) => state.daemonVersionMatched); -export const selectVolume = createSelector(selectState, state => state.volume); +export const selectVolume = createSelector(selectState, (state) => state.volume); -export const selectMute = createSelector(selectState, state => state.muted); +export const selectMute = createSelector(selectState, (state) => state.muted); -export const selectUpgradeTimer = createSelector(selectState, state => state.checkUpgradeTimer); +export const selectUpgradeTimer = createSelector(selectState, (state) => state.checkUpgradeTimer); -export const selectModal = createSelector(selectState, state => { +export const selectModal = createSelector(selectState, (state) => { if (!state.modal) { return null; } @@ -70,23 +70,23 @@ export const selectModal = createSelector(selectState, state => { }; }); -export const selectSearchOptionsExpanded = createSelector(selectState, state => state.searchOptionsExpanded); +export const selectSearchOptionsExpanded = createSelector(selectState, (state) => state.searchOptionsExpanded); -export const selectWelcomeVersion = createSelector(selectState, state => state.welcomeVersion); +export const selectWelcomeVersion = createSelector(selectState, (state) => state.welcomeVersion); -export const selectHasNavigated = createSelector(selectState, state => state.hasNavigated); +export const selectHasNavigated = createSelector(selectState, (state) => state.hasNavigated); -export const selectAllowAnalytics = createSelector(selectState, state => state.allowAnalytics); +export const selectAllowAnalytics = createSelector(selectState, (state) => state.allowAnalytics); -export const selectScrollStartingPosition = createSelector(selectState, state => state.currentScroll); +export const selectScrollStartingPosition = createSelector(selectState, (state) => state.currentScroll); -export const selectIsPasswordSaved = createSelector(selectState, state => state.isPasswordSaved); +export const selectIsPasswordSaved = createSelector(selectState, (state) => state.isPasswordSaved); -export const selectInterestedInYoutubeSync = createSelector(selectState, state => state.interestedInYoutubeSync); +export const selectInterestedInYoutubeSync = createSelector(selectState, (state) => state.interestedInYoutubeSync); -export const selectSplashAnimationEnabled = createSelector(selectState, state => state.splashAnimationEnabled); +export const selectSplashAnimationEnabled = createSelector(selectState, (state) => state.splashAnimationEnabled); -export const selectActiveChannelId = createSelector(selectState, state => state.activeChannel); +export const selectActiveChannelId = createSelector(selectState, (state) => state.activeChannel); export const selectActiveChannelClaim = createSelector( selectActiveChannelId, @@ -118,4 +118,19 @@ export const selectActiveChannelClaim = createSelector( } ); -export const selectIncognito = createSelector(selectState, state => state.incognito); +export const selectActiveChannelStakedLevel = createSelector( + (state) => state, + selectActiveChannelClaim, + (state, activeChannelClaim) => { + if (!activeChannelClaim) { + return 0; + } + + const uri = activeChannelClaim.permanent_url; + const stakedLevel = makeSelectStakedLevelForChannelUri(uri)(state); + + return stakedLevel; + } +); + +export const selectIncognito = createSelector(selectState, (state) => state.incognito);