Refactor unclaimed rewards as array to keep order from api.lbry.io. Display reward notification message through snackbar with fallback for rewards without a message.

This commit is contained in:
Travis Eden 2018-05-17 16:31:49 -04:00
parent ea4c7d9d15
commit ef3ea8c319
7 changed files with 29 additions and 78 deletions

View file

@ -16,7 +16,7 @@ const makeSelect = () => {
const select = (state, props) => ({ const select = (state, props) => ({
errorMessage: selectError(state, props), errorMessage: selectError(state, props),
isPending: selectIsPending(state, props), isPending: selectIsPending(state, props),
reward: selectReward(state, props), reward: selectReward(state, props.reward_type),
}); });
return select; return select;

View file

@ -1,4 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doNotify, MODALS } from 'lbry-redux';
import { doNavigate } from 'redux/actions/navigation'; import { doNavigate } from 'redux/actions/navigation';
import { doUserIdentityVerify } from 'redux/actions/user'; import { doUserIdentityVerify } from 'redux/actions/user';
import rewards from 'rewards'; import rewards from 'rewards';
@ -8,15 +9,14 @@ import {
selectIdentityVerifyErrorMessage, selectIdentityVerifyErrorMessage,
} from 'redux/selectors/user'; } from 'redux/selectors/user';
import UserVerify from './view'; import UserVerify from './view';
import { doNotify, MODALS } from 'lbry-redux';
const select = (state, props) => { const select = state => {
const selectReward = makeSelectRewardByType(); const selectReward = makeSelectRewardByType();
return { return {
isPending: selectIdentityVerifyIsPending(state), isPending: selectIdentityVerifyIsPending(state),
errorMessage: selectIdentityVerifyErrorMessage(state), errorMessage: selectIdentityVerifyErrorMessage(state),
reward: selectReward(state, { reward_type: rewards.TYPE_NEW_USER }), reward: selectReward(state, rewards.TYPE_NEW_USER),
}; };
}; };

View file

@ -8,7 +8,7 @@ const select = state => {
const selectReward = makeSelectRewardByType(); const selectReward = makeSelectRewardByType();
return { return {
reward: selectReward(state, { reward_type: rewards.TYPE_NEW_USER }), reward: selectReward(state, rewards.TYPE_NEW_USER),
}; };
}; };

View file

@ -1,7 +1,7 @@
import * as ACTIONS from 'constants/action_types'; import * as ACTIONS from 'constants/action_types';
import Lbryio from 'lbryio'; import Lbryio from 'lbryio';
import { doNotify, MODALS } from 'lbry-redux'; import { doNotify, MODALS } from 'lbry-redux';
import { selectUnclaimedRewardsByType } from 'redux/selectors/rewards'; import { selectUnclaimedRewards } from 'redux/selectors/rewards';
import { selectUserIsRewardApproved } from 'redux/selectors/user'; import { selectUserIsRewardApproved } from 'redux/selectors/user';
import rewards from 'rewards'; import rewards from 'rewards';
@ -30,8 +30,8 @@ export function doRewardList() {
export function doClaimRewardType(rewardType) { export function doClaimRewardType(rewardType) {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const rewardsByType = selectUnclaimedRewardsByType(state); const unclaimedRewards = selectUnclaimedRewards(state);
const reward = rewardsByType[rewardType]; const reward = unclaimedRewards.find(ur => ur.reward_type === rewardType);
const userIsRewardApproved = selectUserIsRewardApproved(state); const userIsRewardApproved = selectUserIsRewardApproved(state);
if (!reward || reward.transaction_id) { if (!reward || reward.transaction_id) {
@ -84,14 +84,14 @@ export function doClaimRewardType(rewardType) {
export function doClaimEligiblePurchaseRewards() { export function doClaimEligiblePurchaseRewards() {
return (dispatch, getState) => { return (dispatch, getState) => {
const state = getState(); const state = getState();
const rewardsByType = selectUnclaimedRewardsByType(state); const unclaimedRewards = selectUnclaimedRewards(state);
const userIsRewardApproved = selectUserIsRewardApproved(state); const userIsRewardApproved = selectUserIsRewardApproved(state);
if (!userIsRewardApproved || !Lbryio.enabled) { if (!userIsRewardApproved || !Lbryio.enabled) {
return; return;
} }
if (rewardsByType[rewards.TYPE_FIRST_STREAM]) { if (unclaimedRewards.find(ur => ur.reward_type === rewards.TYPE_FIRST_STREAM)) {
dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM)); dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
} else { } else {
[rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => { [rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => {

View file

@ -4,7 +4,7 @@ const reducers = {};
const defaultState = { const defaultState = {
fetching: false, fetching: false,
claimedRewardsById: {}, // id => reward claimedRewardsById: {}, // id => reward
unclaimedRewardsByType: {}, unclaimedRewards: [],
claimPendingByType: {}, claimPendingByType: {},
claimErrorsByType: {}, claimErrorsByType: {},
}; };
@ -17,19 +17,19 @@ reducers[ACTIONS.FETCH_REWARDS_STARTED] = state =>
reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = (state, action) => { reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = (state, action) => {
const { userRewards } = action.data; const { userRewards } = action.data;
const unclaimedRewards = {}; const unclaimedRewards = [];
const claimedRewards = {}; const claimedRewards = {};
userRewards.forEach(reward => { userRewards.forEach(reward => {
if (reward.transaction_id) { if (reward.transaction_id) {
claimedRewards[reward.id] = reward; claimedRewards[reward.id] = reward;
} else { } else {
unclaimedRewards[reward.reward_type] = reward; unclaimedRewards.push(reward);
} }
}); });
return Object.assign({}, state, { return Object.assign({}, state, {
claimedRewardsById: claimedRewards, claimedRewardsById: claimedRewards,
unclaimedRewardsByType: unclaimedRewards, unclaimedRewards,
fetching: false, fetching: false,
}); });
}; };
@ -62,24 +62,21 @@ reducers[ACTIONS.CLAIM_REWARD_STARTED] = (state, action) => {
reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = (state, action) => { reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = (state, action) => {
const { reward } = action.data; const { reward } = action.data;
let { unclaimedRewards } = state;
const unclaimedRewardsByType = Object.assign({}, state.unclaimedRewardsByType); const index = unclaimedRewards.findIndex(ur => ur.reward_type === reward.reward_type);
const existingReward = unclaimedRewardsByType[reward.reward_type]; unclaimedRewards = unclaimedRewards.slice(0, index).concat(unclaimedRewards.slice(index + 1));
const newReward = Object.assign({}, reward, { const { claimedRewardsById } = state;
reward_title: existingReward.reward_title, claimedRewardsById[reward.id] = reward;
reward_description: existingReward.reward_description,
});
const claimedRewardsById = Object.assign({}, state.claimedRewardsById); const newState = {
claimedRewardsById[reward.id] = newReward; ...state,
unclaimedRewards,
const newState = Object.assign({}, state, {
unclaimedRewardsByType,
claimedRewardsById, claimedRewardsById,
}); };
return setClaimRewardState(newState, newReward, false, ''); return setClaimRewardState(newState, reward, false, '');
}; };
reducers[ACTIONS.CLAIM_REWARD_FAILURE] = (state, action) => { reducers[ACTIONS.CLAIM_REWARD_FAILURE] = (state, action) => {

View file

@ -1,5 +1,4 @@
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import REWARDS from 'rewards';
const selectState = state => state.rewards || {}; const selectState = state => state.rewards || {};
@ -26,16 +25,7 @@ export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedR
}, {}) }, {})
); );
export const selectUnclaimedRewards = createSelector( export const selectUnclaimedRewards = createSelector(selectState, state => state.unclaimedRewards);
selectUnclaimedRewardsByType,
byType =>
Object.values(byType).sort(
(a, b) =>
REWARDS.SORT_ORDER.indexOf(a.reward_type) < REWARDS.SORT_ORDER.indexOf(b.reward_type)
? -1
: 1
) || []
);
export const selectFetchingRewards = createSelector(selectState, state => !!state.fetching); export const selectFetchingRewards = createSelector(selectState, state => !!state.fetching);
@ -65,7 +55,8 @@ const selectClaimRewardError = (state, props) =>
export const makeSelectClaimRewardError = () => export const makeSelectClaimRewardError = () =>
createSelector(selectClaimRewardError, errorMessage => errorMessage); createSelector(selectClaimRewardError, errorMessage => errorMessage);
const selectRewardByType = (state, props) => selectUnclaimedRewardsByType(state)[props.reward_type]; const selectRewardByType = (state, rewardType) =>
selectUnclaimedRewards(state).find(reward => reward.reward_type === rewardType);
export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward); export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward);

View file

@ -1,46 +1,8 @@
import { Lbry, doNotify } from 'lbry-redux'; import { Lbry, doNotify } from 'lbry-redux';
import Lbryio from 'lbryio'; import Lbryio from 'lbryio';
function rewardMessage(type, amount) {
return {
new_developer: __('You earned %s for registering as a new developer.', amount),
new_user: __('You earned %s LBC new user reward.', amount),
verified_email: __('You earned %s LBC for verifying your email address.', amount),
new_channel: __('You earned %s LBC for creating a publisher identity.', amount),
first_stream: __('You earned %s LBC for streaming your first video.', amount),
many_downloads: __('You earned %s LBC for downloading a bunch of things.', amount),
first_publish: __('You earned %s LBC for making your first publication.', amount),
featured_download: __('You earned %s LBC for watching a featured download.', amount),
referral: __('You earned %s LBC for referring someone.', amount),
youtube_creator: __('You earned %s LBC for syncing your YouTube channel.', amount),
}[type];
}
const rewards = {}; const rewards = {};
rewards.TYPE_NEW_DEVELOPER = 'new_developer';
rewards.TYPE_NEW_USER = 'new_user';
rewards.TYPE_CONFIRM_EMAIL = 'verified_email';
rewards.TYPE_FIRST_CHANNEL = 'new_channel';
rewards.TYPE_FIRST_STREAM = 'first_stream';
rewards.TYPE_MANY_DOWNLOADS = 'many_downloads';
rewards.TYPE_FIRST_PUBLISH = 'first_publish';
rewards.TYPE_FEATURED_DOWNLOAD = 'featured_download';
rewards.TYPE_REFERRAL = 'referral';
rewards.YOUTUBE_CREATOR = 'youtube_creator';
rewards.SORT_ORDER = [
rewards.TYPE_NEW_USER,
rewards.TYPE_CONFIRM_EMAIL,
rewards.TYPE_FIRST_STREAM,
rewards.TYPE_FIRST_CHANNEL,
rewards.TYPE_FIRST_PUBLISH,
rewards.TYPE_FEATURED_DOWNLOAD,
rewards.TYPE_MANY_DOWNLOADS,
rewards.TYPE_REFERRAL,
rewards.TYPE_NEW_DEVELOPER,
rewards.YOUTUBE_CREATOR,
];
rewards.claimReward = type => { rewards.claimReward = type => {
function requestReward(resolve, reject, params) { function requestReward(resolve, reject, params) {
if (!Lbryio.enabled) { if (!Lbryio.enabled) {
@ -48,7 +10,8 @@ rewards.claimReward = type => {
return; return;
} }
Lbryio.call('reward', 'new', params, 'post').then(reward => { Lbryio.call('reward', 'new', params, 'post').then(reward => {
const message = rewardMessage(type, reward.reward_amount); const message =
reward.reward_notification || `You have claimed a ${reward.reward_amount} LBC reward.`;
// Display global notice // Display global notice
const action = doNotify({ const action = doNotify({