diff --git a/.env.defaults b/.env.defaults
index af17f2375..1c519e9bb 100644
--- a/.env.defaults
+++ b/.env.defaults
@@ -41,7 +41,6 @@ SITE_HELP_EMAIL=help@lbry.com
LOGO_TITLE=lbry.tv
## Social media
TWITTER_ACCOUNT=LBRYcom
-BRANDED_SITE=odysee
## IMAGE ASSETS
YRBL_HAPPY_IMG_URL=https://cdn.lbryplayer.xyz/api/v3/streams/free/yrbl-happy/7aa50a7e5adaf48691935d55e45d697547392929/839d9a
diff --git a/package.json b/package.json
index 0c4ee9992..d387e3456 100644
--- a/package.json
+++ b/package.json
@@ -152,7 +152,7 @@
"imagesloaded": "^4.1.4",
"json-loader": "^0.5.4",
"lbry-format": "https://github.com/lbryio/lbry-format.git",
- "lbry-redux": "lbryio/lbry-redux#e4d0662100a5f4b28bb1bf3cbc1e51b2eebab5b6",
+ "lbry-redux": "lbryio/lbry-redux#7cc9923ed9ff1940b508842af6be44c8da906a60",
"lbryinc": "lbryio/lbryinc#8f9a58bfc8312a65614fd7327661cdcc502c4e59",
"lint-staged": "^7.0.2",
"localforage": "^1.7.1",
diff --git a/ui/component/channelEdit/index.js b/ui/component/channelEdit/index.js
index 82618960f..9a195039b 100644
--- a/ui/component/channelEdit/index.js
+++ b/ui/component/channelEdit/index.js
@@ -17,6 +17,8 @@ import {
} from 'lbry-redux';
import { doOpenModal } from 'redux/actions/app';
import { doUpdateBlockListForPublishedChannel } from 'redux/actions/comments';
+import { doClaimInitialRewards } from 'redux/actions/rewards';
+import { selectIsClaimingInitialRewards, selectHasClaimedInitialRewards } from 'redux/selectors/rewards';
import ChannelForm from './view';
const select = (state, props) => ({
@@ -36,6 +38,8 @@ const select = (state, props) => ({
createError: selectCreateChannelError(state),
creatingChannel: selectCreatingChannel(state),
balance: selectBalance(state),
+ isClaimingInitialRewards: selectIsClaimingInitialRewards(state),
+ hasClaimedInitialRewards: selectHasClaimedInitialRewards(state),
});
const perform = (dispatch) => ({
@@ -50,6 +54,7 @@ const perform = (dispatch) => ({
);
},
clearChannelErrors: () => dispatch(doClearChannelErrors()),
+ claimInitialRewards: () => dispatch(doClaimInitialRewards()),
});
export default connect(select, perform)(ChannelForm);
diff --git a/ui/component/channelEdit/view.jsx b/ui/component/channelEdit/view.jsx
index ccd452142..61c9df69f 100644
--- a/ui/component/channelEdit/view.jsx
+++ b/ui/component/channelEdit/view.jsx
@@ -48,6 +48,7 @@ type Props = {
createError: string,
creatingChannel: boolean,
clearChannelErrors: () => void,
+ claimInitialRewards: () => void,
onDone: () => void,
openModal: (
id: string,
@@ -55,6 +56,8 @@ type Props = {
) => void,
uri: string,
disabled: boolean,
+ isClaimingInitialRewards: boolean,
+ hasClaimedInitialRewards: boolean,
};
function ChannelForm(props: Props) {
@@ -79,8 +82,11 @@ function ChannelForm(props: Props) {
creatingChannel,
createError,
clearChannelErrors,
+ claimInitialRewards,
openModal,
disabled,
+ isClaimingInitialRewards,
+ hasClaimedInitialRewards,
} = props;
const [nameError, setNameError] = React.useState(undefined);
const [bidError, setBidError] = React.useState('');
@@ -94,6 +100,22 @@ function ChannelForm(props: Props) {
const languageParam = params.languages;
const primaryLanguage = Array.isArray(languageParam) && languageParam.length && languageParam[0];
const secondaryLanguage = Array.isArray(languageParam) && languageParam.length >= 2 && languageParam[1];
+ const submitLabel = React.useMemo(() => {
+ if (isClaimingInitialRewards) {
+ return __('Claiming credits...');
+ }
+ return creatingChannel || updatingChannel ? __('Submitting') : __('Submit');
+ }, [isClaimingInitialRewards, creatingChannel, updatingChannel]);
+ const submitDisabled = React.useMemo(() => {
+ return (
+ isClaimingInitialRewards ||
+ creatingChannel ||
+ updatingChannel ||
+ nameError ||
+ bidError ||
+ (isNewChannel && !params.name)
+ );
+ }, [isClaimingInitialRewards, creatingChannel, updatingChannel, nameError, bidError, isNewChannel, params]);
function getChannelParams() {
// fill this in with sdk data
@@ -219,6 +241,12 @@ function ChannelForm(props: Props) {
clearChannelErrors();
}, [clearChannelErrors]);
+ React.useEffect(() => {
+ if (!hasClaimedInitialRewards) {
+ claimInitialRewards();
+ }
+ }, [hasClaimedInitialRewards, claimInitialRewards]);
+
// TODO clear and bail after submit
return (
<>
@@ -453,14 +481,7 @@ function ChannelForm(props: Props) {
actions={
<>
-
+
{errorMsg ? (
diff --git a/ui/component/publishBid/index.js b/ui/component/publishBid/index.js
index 17ce7cf2a..c570d5d7d 100644
--- a/ui/component/publishBid/index.js
+++ b/ui/component/publishBid/index.js
@@ -3,25 +3,23 @@ import {
makeSelectPublishFormValue,
selectMyClaimForUri,
selectIsResolvingPublishUris,
- selectTakeOverAmount,
doUpdatePublishForm,
doPrepareEdit,
selectBalance,
} from 'lbry-redux';
import PublishPage from './view';
-const select = (state) => ({
+const select = state => ({
name: makeSelectPublishFormValue('name')(state),
bid: makeSelectPublishFormValue('bid')(state),
uri: makeSelectPublishFormValue('uri')(state),
isResolvingUri: selectIsResolvingPublishUris(state),
balance: selectBalance(state),
myClaimForUri: selectMyClaimForUri(state),
- amountNeededForTakeover: selectTakeOverAmount(state),
});
-const perform = (dispatch) => ({
- updatePublishForm: (value) => dispatch(doUpdatePublishForm(value)),
+const perform = dispatch => ({
+ updatePublishForm: value => dispatch(doUpdatePublishForm(value)),
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
});
diff --git a/ui/component/publishForm/index.js b/ui/component/publishForm/index.js
index 47ed81a46..58b24bdb5 100644
--- a/ui/component/publishForm/index.js
+++ b/ui/component/publishForm/index.js
@@ -18,7 +18,12 @@ import {
} from 'lbry-redux';
import * as RENDER_MODES from 'constants/file_render_modes';
import { doPublishDesktop } from 'redux/actions/publish';
-import { selectUnclaimedRewardValue } from 'redux/selectors/rewards';
+import { doClaimInitialRewards } from 'redux/actions/rewards';
+import {
+ selectUnclaimedRewardValue,
+ selectIsClaimingInitialRewards,
+ selectHasClaimedInitialRewards,
+} from 'redux/selectors/rewards';
import {
selectModal,
selectActiveChannelClaim,
@@ -27,8 +32,8 @@ import {
} from 'redux/selectors/app';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { makeSelectFileRenderModeForUri } from 'redux/selectors/content';
-import PublishPage from './view';
import { selectUser } from 'redux/selectors/user';
+import PublishPage from './view';
const select = (state) => {
const myClaimForUri = selectMyClaimForUri(state);
@@ -59,6 +64,8 @@ const select = (state) => {
myChannels: selectMyChannelClaims(state),
incognito: selectIncognito(state),
activeChannelStakedLevel: selectActiveChannelStakedLevel(state),
+ isClaimingInitialRewards: selectIsClaimingInitialRewards(state),
+ hasClaimedInitialRewards: selectHasClaimedInitialRewards(state),
};
};
@@ -70,6 +77,7 @@ const perform = (dispatch) => ({
prepareEdit: (claim, uri) => dispatch(doPrepareEdit(claim, uri)),
resetThumbnailStatus: () => dispatch(doResetThumbnailStatus()),
checkAvailability: (name) => dispatch(doCheckPublishNameAvailability(name)),
+ claimInitialRewards: () => dispatch(doClaimInitialRewards()),
});
export default connect(select, perform)(PublishPage);
diff --git a/ui/component/publishForm/view.jsx b/ui/component/publishForm/view.jsx
index 2089fb6ca..eac23885b 100644
--- a/ui/component/publishForm/view.jsx
+++ b/ui/component/publishForm/view.jsx
@@ -90,6 +90,9 @@ type Props = {
isPostClaim: boolean,
permanentUrl: ?string,
remoteUrl: ?string,
+ isClaimingInitialRewards: boolean,
+ claimInitialRewards: () => void,
+ hasClaimedInitialRewards: boolean,
};
function PublishForm(props: Props) {
@@ -128,6 +131,9 @@ function PublishForm(props: Props) {
isPostClaim,
permanentUrl,
remoteUrl,
+ isClaimingInitialRewards,
+ claimInitialRewards,
+ hasClaimedInitialRewards,
} = props;
const { replace, location } = useHistory();
@@ -263,6 +269,12 @@ function PublishForm(props: Props) {
}
}, [activeChannelClaimStr, setSignedMessage]);
+ useEffect(() => {
+ if (!hasClaimedInitialRewards) {
+ claimInitialRewards();
+ }
+ }, [hasClaimedInitialRewards, claimInitialRewards]);
+
useEffect(() => {
if (!modal) {
setTimeout(() => {
@@ -298,7 +310,10 @@ function PublishForm(props: Props) {
const isLivestreamMode = mode === PUBLISH_MODES.LIVESTREAM;
let submitLabel;
- if (publishing) {
+
+ if (isClaimingInitialRewards) {
+ submitLabel = __('Claiming credits...');
+ } else if (publishing) {
if (isStillEditing) {
submitLabel = __('Saving...');
} else if (isLivestreamMode) {
@@ -623,6 +638,7 @@ function PublishForm(props: Props) {
onClick={handlePublish}
label={submitLabel}
disabled={
+ isClaimingInitialRewards ||
formDisabled ||
!formValid ||
uploadThumbnailStatus === THUMBNAIL_STATUSES.IN_PROGRESS ||
diff --git a/ui/component/publishName/index.js b/ui/component/publishName/index.js
index 4159056e3..67f5142fb 100644
--- a/ui/component/publishName/index.js
+++ b/ui/component/publishName/index.js
@@ -3,7 +3,6 @@ import {
makeSelectPublishFormValue,
selectIsStillEditing,
selectMyClaimForUri,
- selectTakeOverAmount,
doUpdatePublishForm,
doPrepareEdit,
} from 'lbry-redux';
@@ -18,7 +17,6 @@ const select = (state) => ({
myClaimForUri: selectMyClaimForUri(state),
activeChannelClaim: selectActiveChannelClaim(state),
incognito: selectIncognito(state),
- amountNeededForTakeover: selectTakeOverAmount(state),
});
const perform = (dispatch) => ({
diff --git a/ui/redux/actions/rewards.js b/ui/redux/actions/rewards.js
index 4af3b8c07..98351fd42 100644
--- a/ui/redux/actions/rewards.js
+++ b/ui/redux/actions/rewards.js
@@ -6,13 +6,13 @@ import { doFetchInviteStatus } from 'redux/actions/user';
import rewards from 'rewards';
export function doRewardList() {
- return dispatch => {
+ return (dispatch) => {
dispatch({
type: ACTIONS.FETCH_REWARDS_STARTED,
});
Lbryio.call('reward', 'list', { multiple_rewards_per_type: true })
- .then(userRewards => {
+ .then((userRewards) => {
dispatch({
type: ACTIONS.FETCH_REWARDS_COMPLETED,
data: { userRewards },
@@ -35,7 +35,7 @@ export function doClaimRewardType(rewardType, options = {}) {
const reward =
rewardType === rewards.TYPE_REWARD_CODE || rewardType === rewards.TYPE_NEW_ANDROID
? { reward_type: rewards.TYPE_REWARD_CODE }
- : unclaimedRewards.find(ur => ur.reward_type === rewardType);
+ : unclaimedRewards.find((ur) => ur.reward_type === rewardType);
// Try to claim the email reward right away, even if we haven't called reward_list yet
if (
@@ -74,7 +74,7 @@ export function doClaimRewardType(rewardType, options = {}) {
data: { reward },
});
- const success = successReward => {
+ const success = (successReward) => {
// Temporary timeout to ensure the sdk has the correct balance after claiming a reward
setTimeout(() => {
dispatch(doUpdateBalance()).then(() => {
@@ -99,7 +99,7 @@ export function doClaimRewardType(rewardType, options = {}) {
}, 2000);
};
- const failure = error => {
+ const failure = (error) => {
dispatch({
type: ACTIONS.CLAIM_REWARD_FAILURE,
data: {
@@ -121,6 +121,13 @@ export function doClaimRewardType(rewardType, options = {}) {
};
}
+export function doClaimInitialRewards() {
+ return (dispatch) => {
+ dispatch(doClaimRewardType(rewards.TYPE_NEW_USER));
+ dispatch(doClaimRewardType(rewards.TYPE_CONFIRM_EMAIL));
+ };
+}
+
export function doClaimEligiblePurchaseRewards() {
return (dispatch, getState) => {
const state = getState();
@@ -131,10 +138,10 @@ export function doClaimEligiblePurchaseRewards() {
return;
}
- if (unclaimedRewards.find(ur => ur.reward_type === rewards.TYPE_FIRST_STREAM)) {
+ if (unclaimedRewards.find((ur) => ur.reward_type === rewards.TYPE_FIRST_STREAM)) {
dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
} else {
- [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_DAILY_VIEW].forEach(type => {
+ [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_DAILY_VIEW].forEach((type) => {
dispatch(doClaimRewardType(type, { failSilently: true }));
});
}
@@ -142,7 +149,7 @@ export function doClaimEligiblePurchaseRewards() {
}
export function doClaimRewardClearError(reward) {
- return dispatch => {
+ return (dispatch) => {
dispatch({
type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR,
data: { reward },
@@ -151,8 +158,8 @@ export function doClaimRewardClearError(reward) {
}
export function doFetchRewardedContent() {
- return dispatch => {
- const success = nameToClaimId => {
+ return (dispatch) => {
+ const success = (nameToClaimId) => {
dispatch({
type: ACTIONS.FETCH_REWARD_CONTENT_COMPLETED,
data: {
diff --git a/ui/redux/selectors/reactions.js b/ui/redux/selectors/reactions.js
index 76feeebdc..0058d2095 100644
--- a/ui/redux/selectors/reactions.js
+++ b/ui/redux/selectors/reactions.js
@@ -54,10 +54,11 @@ export const makeSelectLikeCountForUri = (uri) =>
export const makeSelectDislikeCountForUri = (uri) =>
createSelector(makeSelectClaimForUri(uri), makeSelectReactionsForUri(uri), (claim, reactions) => {
- if (!claim || !reactions || reactions.my_reactions === null || reactions.others_reactions === null) {
+ const claimId = claim.claim_id;
+
+ if (!reactions || reactions.my_reactions === null || reactions.others_reactions === null) {
return 0;
}
- const claimId = claim.claim_id;
let count = 0;
if (reactions.others_reactions) {
diff --git a/ui/redux/selectors/rewards.js b/ui/redux/selectors/rewards.js
index c70b3cdc8..00d6d390a 100644
--- a/ui/redux/selectors/rewards.js
+++ b/ui/redux/selectors/rewards.js
@@ -1,15 +1,15 @@
import { createSelector } from 'reselect';
import REWARDS from 'rewards';
-const selectState = state => state.rewards || {};
+const selectState = (state) => state.rewards || {};
-export const selectUnclaimedRewardsByType = createSelector(selectState, state => state.unclaimedRewardsByType);
+export const selectUnclaimedRewardsByType = createSelector(selectState, (state) => state.unclaimedRewardsByType);
-export const selectClaimedRewardsById = createSelector(selectState, state => state.claimedRewardsById);
+export const selectClaimedRewardsById = createSelector(selectState, (state) => state.claimedRewardsById);
-export const selectClaimedRewards = createSelector(selectClaimedRewardsById, byId => Object.values(byId) || []);
+export const selectClaimedRewards = createSelector(selectClaimedRewardsById, (byId) => Object.values(byId) || []);
-export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedRewards, rewards =>
+export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedRewards, (rewards) =>
rewards.reduce((mapParam, reward) => {
const map = mapParam;
map[reward.transaction_id] = reward;
@@ -17,47 +17,58 @@ export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedR
}, {})
);
-export const selectUnclaimedRewards = createSelector(selectState, state => state.unclaimedRewards);
+export const selectUnclaimedRewards = createSelector(selectState, (state) => state.unclaimedRewards);
-export const selectFetchingRewards = createSelector(selectState, state => !!state.fetching);
+export const selectFetchingRewards = createSelector(selectState, (state) => !!state.fetching);
-export const selectUnclaimedRewardValue = createSelector(selectUnclaimedRewards, rewards =>
+export const selectUnclaimedRewardValue = createSelector(selectUnclaimedRewards, (rewards) =>
rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
);
-export const selectClaimsPendingByType = createSelector(selectState, state => state.claimPendingByType);
+export const selectClaimsPendingByType = createSelector(selectState, (state) => state.claimPendingByType);
const selectIsClaimRewardPending = (state, props) => selectClaimsPendingByType(state, props)[props.reward_type];
export const makeSelectIsRewardClaimPending = () =>
- createSelector(selectIsClaimRewardPending, isClaiming => isClaiming);
+ createSelector(selectIsClaimRewardPending, (isClaiming) => isClaiming);
-export const selectClaimErrorsByType = createSelector(selectState, state => state.claimErrorsByType);
+export const selectClaimErrorsByType = createSelector(selectState, (state) => state.claimErrorsByType);
const selectClaimRewardError = (state, props) => selectClaimErrorsByType(state, props)[props.reward_type];
-export const makeSelectClaimRewardError = () => createSelector(selectClaimRewardError, errorMessage => errorMessage);
+export const makeSelectClaimRewardError = () => createSelector(selectClaimRewardError, (errorMessage) => errorMessage);
const selectRewardByType = (state, rewardType) =>
- selectUnclaimedRewards(state).find(reward => reward.reward_type === rewardType);
+ selectUnclaimedRewards(state).find((reward) => reward.reward_type === rewardType);
-export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward);
+export const makeSelectRewardByType = () => createSelector(selectRewardByType, (reward) => reward);
const selectRewardByClaimCode = (state, claimCode) =>
- selectUnclaimedRewards(state).find(reward => reward.claim_code === claimCode);
+ selectUnclaimedRewards(state).find((reward) => reward.claim_code === claimCode);
-export const makeSelectRewardByClaimCode = () => createSelector(selectRewardByClaimCode, reward => reward);
+export const makeSelectRewardByClaimCode = () => createSelector(selectRewardByClaimCode, (reward) => reward);
export const makeSelectRewardAmountByType = () =>
- createSelector(selectRewardByType, reward => (reward ? reward.reward_amount : 0));
+ createSelector(selectRewardByType, (reward) => (reward ? reward.reward_amount : 0));
-export const selectRewardContentClaimIds = createSelector(selectState, state => state.rewardedContentClaimIds);
+export const selectRewardContentClaimIds = createSelector(selectState, (state) => state.rewardedContentClaimIds);
export const selectReferralReward = createSelector(
selectUnclaimedRewards,
- unclaimedRewards => unclaimedRewards.filter(reward => reward.reward_type === REWARDS.TYPE_REFERRAL)[0]
+ (unclaimedRewards) => unclaimedRewards.filter((reward) => reward.reward_type === REWARDS.TYPE_REFERRAL)[0]
);
-export const selectHasUnclaimedRefereeReward = createSelector(selectUnclaimedRewards, unclaimedRewards =>
- unclaimedRewards.some(reward => reward.reward_type === REWARDS.TYPE_REFEREE)
+export const selectHasUnclaimedRefereeReward = createSelector(selectUnclaimedRewards, (unclaimedRewards) =>
+ unclaimedRewards.some((reward) => reward.reward_type === REWARDS.TYPE_REFEREE)
);
+
+export const selectIsClaimingInitialRewards = createSelector(selectClaimsPendingByType, (claimsPendingByType) => {
+ return !!(claimsPendingByType[REWARDS.TYPE_NEW_USER] || claimsPendingByType[REWARDS.TYPE_CONFIRM_EMAIL]);
+});
+
+export const selectHasClaimedInitialRewards = createSelector(selectClaimedRewardsById, (claimedRewardsById) => {
+ const claims = Object.values(claimedRewardsById);
+ const newUserClaimed = !!claims.find((claim) => claim && claim.reward_type === REWARDS.TYPE_NEW_USER);
+ const confirmEmailClaimed = !!claims.find((claim) => claim && claim.reward_type === REWARDS.TYPE_CONFIRM_EMAIL);
+ return newUserClaimed && confirmEmailClaimed;
+});
diff --git a/web/component/nag-sunset.jsx b/web/component/nag-sunset.jsx
index 27c60eb44..37cd8a5ce 100644
--- a/web/component/nag-sunset.jsx
+++ b/web/component/nag-sunset.jsx
@@ -4,7 +4,6 @@ import Nag from 'component/common/nag';
import I18nMessage from 'component/i18nMessage';
import * as PAGES from 'constants/pages';
import { useHistory } from 'react-router';
-import Button from '../../ui/component/button';
type Props = {
email?: User,
@@ -21,15 +20,7 @@ export default function NagSunset(props: Props) {
return (
,
- }}
- >
- lbry.tv has been retired (%more%). You have been magically transported to Odysee.com
-
- }
+ message={lbry.tv has been retired. You have been magically transported to odysee.com}
actionText={__('Sign In')}
onClick={!email ? handleOnClick : undefined}
onClose={onClose}
diff --git a/yarn.lock b/yarn.lock
index 9ac3c7109..3206d9f07 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10129,9 +10129,9 @@ lazy-val@^1.0.4:
yargs "^13.2.2"
zstd-codec "^0.1.1"
-lbry-redux@lbryio/lbry-redux#e4d0662100a5f4b28bb1bf3cbc1e51b2eebab5b6:
+lbry-redux@lbryio/lbry-redux#7cc9923ed9ff1940b508842af6be44c8da906a60:
version "0.0.1"
- resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/e4d0662100a5f4b28bb1bf3cbc1e51b2eebab5b6"
+ resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/7cc9923ed9ff1940b508842af6be44c8da906a60"
dependencies:
proxy-polyfill "0.1.6"
reselect "^3.0.0"