commit
b054bc096e
45 changed files with 200 additions and 1347 deletions
|
@ -17,10 +17,10 @@ module.name_mapper='^types\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/types\1'
|
|||
module.name_mapper='^component\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/component\1'
|
||||
module.name_mapper='^page\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/page\1'
|
||||
module.name_mapper='^lbry\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/lbry\1'
|
||||
module.name_mapper='^rewards\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/rewards\1'
|
||||
module.name_mapper='^modal\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/modal\1'
|
||||
module.name_mapper='^app\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/app\1'
|
||||
module.name_mapper='^native\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/native\1'
|
||||
module.name_mapper='^analytics\(.*\)$' -> '<PROJECT_ROOT>/src/renderer/analytics\1'
|
||||
|
||||
|
||||
[strict]
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"hast-util-sanitize": "^1.1.2",
|
||||
"keytar": "^4.2.1",
|
||||
"lbry-redux": "lbryio/lbry-redux#d1cee82af119c0c5f98ec27f94b2e7f61e34b54c",
|
||||
"lbryinc": "lbryio/lbryinc#c09aa2645ecccb33c83e9a9545ff119232910f6f",
|
||||
"localforage": "^1.7.1",
|
||||
"mammoth": "^1.4.6",
|
||||
"mime": "^2.3.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import mixpanel from 'mixpanel-browser';
|
||||
import Lbryio from 'lbryio';
|
||||
import { Lbryio } from 'lbryinc';
|
||||
import isDev from 'electron-is-dev';
|
||||
|
||||
if (isDev) {
|
||||
|
|
|
@ -38,4 +38,7 @@ global.__ = i18n.__;
|
|||
global.__n = i18n.__n;
|
||||
global.app = app;
|
||||
|
||||
// Lbryinc needs access to the redux store for dispatching auth-releated actions
|
||||
global.store = app.store;
|
||||
|
||||
export default app;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectPageTitle, selectHistoryIndex, selectActiveHistoryEntry } from 'lbry-redux';
|
||||
import { doRecordScroll } from 'redux/actions/navigation';
|
||||
import { selectUser } from 'redux/selectors/user';
|
||||
import { selectUser } from 'lbryinc';
|
||||
import { doAlertError } from 'redux/actions/app';
|
||||
import App from './view';
|
||||
|
||||
|
@ -17,4 +17,7 @@ const perform = dispatch => ({
|
|||
recordScroll: scrollPosition => dispatch(doRecordScroll(scrollPosition)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(App);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(App);
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectUserEmail } from 'redux/selectors/user';
|
||||
import { selectUserEmail } from 'lbryinc';
|
||||
import CardVerify from './view';
|
||||
|
||||
const select = state => ({
|
||||
email: selectUserEmail(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({});
|
||||
const perform = () => ({});
|
||||
|
||||
export default connect(select, perform)(CardVerify);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(CardVerify);
|
||||
|
|
|
@ -3,6 +3,7 @@ import * as settings from 'constants/settings';
|
|||
import { doChangeVolume } from 'redux/actions/app';
|
||||
import { selectVolume } from 'redux/selectors/app';
|
||||
import { doPlayUri, doSetPlayingUri, savePosition } from 'redux/actions/content';
|
||||
import { doClaimEligiblePurchaseRewards } from 'lbryinc';
|
||||
import {
|
||||
makeSelectMetadataForUri,
|
||||
makeSelectContentTypeForUri,
|
||||
|
@ -13,7 +14,6 @@ import {
|
|||
makeSelectDownloadingForUri,
|
||||
selectSearchBarFocused,
|
||||
} from 'lbry-redux';
|
||||
import { doClaimEligiblePurchaseRewards } from 'redux/actions/rewards';
|
||||
import { makeSelectClientSetting, selectShowNsfw } from 'redux/selectors/settings';
|
||||
import { selectPlayingUri, makeSelectContentPositionForUri } from 'redux/selectors/content';
|
||||
import { selectFileInfoErrors } from 'redux/selectors/file_info';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectUserInvitees, selectUserInviteStatusIsPending } from 'redux/selectors/user';
|
||||
import { selectUserInvitees, selectUserInviteStatusIsPending } from 'lbryinc';
|
||||
import InviteList from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -8,6 +7,9 @@ const select = state => ({
|
|||
isPending: selectUserInviteStatusIsPending(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({});
|
||||
const perform = () => ({});
|
||||
|
||||
export default connect(select, perform)(InviteList);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(InviteList);
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import Icon from 'component/common/icon';
|
||||
import RewardLink from 'component/rewardLink';
|
||||
import rewards from 'rewards.js';
|
||||
import { rewards } from 'lbryinc';
|
||||
import * as icons from 'constants/icons';
|
||||
|
||||
class InviteList extends React.PureComponent {
|
||||
type Props = {
|
||||
invitees: ?Array<{
|
||||
email: string,
|
||||
invite_accepted: boolean,
|
||||
invite_reward_claimed: boolean,
|
||||
invite_reward_claimable: boolean,
|
||||
}>,
|
||||
};
|
||||
|
||||
class InviteList extends React.PureComponent<Props> {
|
||||
render() {
|
||||
const { invitees } = this.props;
|
||||
|
||||
|
@ -31,8 +41,8 @@ class InviteList extends React.PureComponent {
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{invitees.map((invitee, index) => (
|
||||
<tr key={index}>
|
||||
{invitees.map(invitee => (
|
||||
<tr key={invitee.email}>
|
||||
<td>{invitee.email}</td>
|
||||
<td className="text-center">
|
||||
{invitee.invite_accepted ? (
|
||||
|
|
|
@ -3,8 +3,8 @@ import {
|
|||
selectUserInvitesRemaining,
|
||||
selectUserInviteNewIsPending,
|
||||
selectUserInviteNewErrorMessage,
|
||||
} from 'redux/selectors/user';
|
||||
import { doUserInviteNew } from 'redux/actions/user';
|
||||
doUserInviteNew,
|
||||
} from 'lbryinc';
|
||||
import InviteNew from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -17,4 +17,7 @@ const perform = dispatch => ({
|
|||
inviteNew: email => dispatch(doUserInviteNew(email)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(InviteNew);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(InviteNew);
|
||||
|
|
|
@ -3,9 +3,10 @@ import {
|
|||
makeSelectClaimRewardError,
|
||||
makeSelectRewardByType,
|
||||
makeSelectIsRewardClaimPending,
|
||||
} from 'redux/selectors/rewards';
|
||||
doClaimRewardType,
|
||||
doClaimRewardClearError,
|
||||
} from 'lbryinc';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { doClaimRewardType, doClaimRewardClearError } from 'redux/actions/rewards';
|
||||
import RewardLink from './view';
|
||||
|
||||
const makeSelect = () => {
|
||||
|
@ -28,4 +29,7 @@ const perform = dispatch => ({
|
|||
navigate: path => dispatch(doNavigate(path)),
|
||||
});
|
||||
|
||||
export default connect(makeSelect, perform)(RewardLink);
|
||||
export default connect(
|
||||
makeSelect,
|
||||
perform
|
||||
)(RewardLink);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectClaimedRewards } from 'redux/selectors/rewards';
|
||||
import { selectClaimedRewards } from 'lbryinc';
|
||||
import RewardListClaimed from './view';
|
||||
|
||||
const select = state => ({
|
||||
rewards: selectClaimedRewards(state),
|
||||
});
|
||||
|
||||
export default connect(select, null)(RewardListClaimed);
|
||||
export default connect(
|
||||
select,
|
||||
null
|
||||
)(RewardListClaimed);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectUnclaimedRewardValue, selectFetchingRewards } from 'redux/selectors/rewards';
|
||||
import { doRewardList } from 'redux/actions/rewards';
|
||||
import { selectUnclaimedRewardValue, selectFetchingRewards, doRewardList } from 'lbryinc';
|
||||
import { doFetchRewardedContent } from 'redux/actions/content';
|
||||
import RewardSummary from './view';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import Icon from 'component/common/icon';
|
||||
import RewardLink from 'component/rewardLink';
|
||||
import Button from 'component/button';
|
||||
import rewards from 'rewards';
|
||||
import { rewards } from 'lbryinc';
|
||||
import * as icons from 'constants/icons';
|
||||
|
||||
type Props = {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { selectClaimedRewardsByTransactionId } from 'redux/selectors/rewards';
|
||||
import { selectClaimedRewardsByTransactionId } from 'lbryinc';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { doNotify } from 'lbry-redux';
|
||||
import { selectAllMyClaimsByOutpoint } from 'lbry-redux';
|
||||
import { selectAllMyClaimsByOutpoint, doNotify } from 'lbry-redux';
|
||||
import TransactionList from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -15,4 +14,7 @@ const perform = dispatch => ({
|
|||
openModal: (modal, props) => dispatch(doNotify(modal, props)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(TransactionList);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(TransactionList);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { doUserEmailNew, doUserInviteNew } from 'redux/actions/user';
|
||||
import { selectEmailNewIsPending, selectEmailNewErrorMessage } from 'redux/selectors/user';
|
||||
import { selectEmailNewIsPending, selectEmailNewErrorMessage, doUserEmailNew } from 'lbryinc';
|
||||
import UserEmailNew from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -13,4 +11,7 @@ const perform = dispatch => ({
|
|||
addUserEmail: email => dispatch(doUserEmailNew(email)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(UserEmailNew);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(UserEmailNew);
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doUserEmailVerify,
|
||||
doUserEmailVerifyFailure,
|
||||
doUserResendVerificationEmail,
|
||||
} from 'redux/actions/user';
|
||||
import {
|
||||
selectEmailVerifyIsPending,
|
||||
selectEmailToVerify,
|
||||
selectEmailVerifyErrorMessage,
|
||||
} from 'redux/selectors/user';
|
||||
doUserEmailVerify,
|
||||
doUserEmailVerifyFailure,
|
||||
doUserResendVerificationEmail,
|
||||
} from 'lbryinc';
|
||||
import UserEmailVerify from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -23,4 +21,7 @@ const perform = dispatch => ({
|
|||
resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(UserEmailVerify);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(UserEmailVerify);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { doUserPhoneNew } from 'redux/actions/user';
|
||||
import { selectPhoneNewErrorMessage } from 'redux/selectors/user';
|
||||
import { selectPhoneNewErrorMessage, doUserPhoneNew } from 'lbryinc';
|
||||
import UserPhoneNew from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -9,7 +7,10 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
addUserPhone: (phone, country_code) => dispatch(doUserPhoneNew(phone, country_code)),
|
||||
addUserPhone: (phone, countryCode) => dispatch(doUserPhoneNew(phone, countryCode)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(UserPhoneNew);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(UserPhoneNew);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { doUserPhoneVerify, doUserPhoneReset } from 'redux/actions/user';
|
||||
import {
|
||||
doUserPhoneVerify,
|
||||
doUserPhoneReset,
|
||||
selectPhoneToVerify,
|
||||
selectPhoneVerifyErrorMessage,
|
||||
selectUserCountryCode,
|
||||
} from 'redux/selectors/user';
|
||||
} from 'lbryinc';
|
||||
import UserPhoneVerify from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -19,4 +19,7 @@ const perform = dispatch => ({
|
|||
verifyUserPhone: code => dispatch(doUserPhoneVerify(code)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(UserPhoneVerify);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(UserPhoneVerify);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doNotify, MODALS } from 'lbry-redux';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { doUserIdentityVerify } from 'redux/actions/user';
|
||||
import rewards from 'rewards';
|
||||
import { makeSelectRewardByType } from 'redux/selectors/rewards';
|
||||
import {
|
||||
doUserIdentityVerify,
|
||||
rewards,
|
||||
makeSelectRewardByType,
|
||||
selectIdentityVerifyIsPending,
|
||||
selectIdentityVerifyErrorMessage,
|
||||
} from 'redux/selectors/user';
|
||||
} from 'lbryinc';
|
||||
import UserVerify from './view';
|
||||
|
||||
const select = state => {
|
||||
|
@ -26,4 +26,7 @@ const perform = dispatch => ({
|
|||
verifyPhone: () => dispatch(doNotify({ id: MODALS.PHONE_COLLECTION })),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(UserVerify);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(UserVerify);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import * as React from 'react';
|
||||
import Button from 'component/button';
|
||||
import CardVerify from 'component/cardVerify';
|
||||
import lbryio from 'lbryio';
|
||||
import Lbryio from 'lbryinc';
|
||||
import * as icons from 'constants/icons';
|
||||
|
||||
type Props = {
|
||||
|
@ -51,7 +51,7 @@ class UserVerify extends React.PureComponent<Props> {
|
|||
label={__('Perform Card Verification')}
|
||||
disabled={isPending}
|
||||
token={this.onToken}
|
||||
stripeKey={lbryio.getStripeToken()}
|
||||
stripeKey={Lbryio.getStripeToken()}
|
||||
/>
|
||||
</div>
|
||||
<div className="card__content">
|
||||
|
|
|
@ -11,9 +11,10 @@ import { doConditionalAuthNavigate, doDaemonReady, doAutoUpdate } from 'redux/ac
|
|||
import { doNotify, doBlackListedOutpointsSubscribe, isURIValid } from 'lbry-redux';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { doDownloadLanguages, doUpdateIsNightAsync } from 'redux/actions/settings';
|
||||
import { doUserEmailVerify, doAuthenticate } from 'redux/actions/user';
|
||||
import { doUserEmailVerify, doAuthenticate, Lbryio } from 'lbryinc';
|
||||
import 'scss/all.scss';
|
||||
import store from 'store';
|
||||
import pjson from 'package.json';
|
||||
import app from './app';
|
||||
import analytics from './analytics';
|
||||
import doLogWarningConsoleMessage from './logWarningConsoleMessage';
|
||||
|
@ -23,6 +24,40 @@ const APPPAGEURL = 'lbry://?';
|
|||
|
||||
autoUpdater.logger = remote.require('electron-log');
|
||||
|
||||
// We need to override Lbryio for getting/setting the authToken
|
||||
// We interect with ipcRenderer to get the auth key from a users keyring
|
||||
Lbryio.setOverride('setAuthToken', status => {
|
||||
Lbryio.call(
|
||||
'user',
|
||||
'new',
|
||||
{
|
||||
auth_token: '',
|
||||
language: 'en',
|
||||
app_id: status.installation_id,
|
||||
},
|
||||
'post'
|
||||
).then(response => {
|
||||
if (!response.auth_token) {
|
||||
throw new Error(__('auth_token is missing from response'));
|
||||
}
|
||||
|
||||
ipcRenderer.send('set-auth-token', response.auth_token);
|
||||
});
|
||||
});
|
||||
|
||||
Lbryio.setOverride(
|
||||
'getAuthToken',
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
ipcRenderer.once('auth-token-response', (event, token) => {
|
||||
Lbryio.authToken = token;
|
||||
resolve(token);
|
||||
});
|
||||
|
||||
ipcRenderer.send('get-auth-token');
|
||||
})
|
||||
);
|
||||
|
||||
ipcRenderer.on('open-uri-requested', (event, uri, newSession) => {
|
||||
if (uri && uri.startsWith('lbry://')) {
|
||||
if (uri.startsWith('lbry://?verify=')) {
|
||||
|
@ -156,7 +191,7 @@ const init = () => {
|
|||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<SplashScreen
|
||||
authenticate={() => app.store.dispatch(doAuthenticate())}
|
||||
authenticate={() => app.store.dispatch(doAuthenticate(pjson.version))}
|
||||
onReadyToLaunch={onDaemonReady}
|
||||
/>
|
||||
</Provider>,
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
import { ipcRenderer } from 'electron';
|
||||
import { Lbry } from 'lbry-redux';
|
||||
import querystring from 'querystring';
|
||||
|
||||
const Lbryio = {
|
||||
enabled: true,
|
||||
authenticationPromise: null,
|
||||
};
|
||||
|
||||
const CONNECTION_STRING = process.env.LBRY_APP_API_URL
|
||||
? process.env.LBRY_APP_API_URL.replace(/\/*$/, '/') // exactly one slash at the end
|
||||
: 'https://api.lbry.io/';
|
||||
|
||||
Lbryio.call = (resource, action, params = {}, method = 'get') => {
|
||||
if (!Lbryio.enabled) {
|
||||
console.log(__('Internal API disabled'));
|
||||
return Promise.reject(new Error(__('LBRY internal API is disabled')));
|
||||
}
|
||||
|
||||
if (!(method === 'get' || method === 'post')) {
|
||||
return Promise.reject(new Error(__('Invalid method')));
|
||||
}
|
||||
|
||||
function checkAndParse(response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response.json();
|
||||
}
|
||||
return response.json().then(json => {
|
||||
let error;
|
||||
if (json.error) {
|
||||
error = new Error(json.error);
|
||||
} else {
|
||||
error = new Error('Unknown API error signature');
|
||||
}
|
||||
error.response = response; // This is primarily a hack used in actions/user.js
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
||||
function makeRequest(url, options) {
|
||||
return fetch(url, options).then(checkAndParse);
|
||||
}
|
||||
|
||||
return Lbryio.getAuthToken().then(token => {
|
||||
const fullParams = { auth_token: token, ...params };
|
||||
const qs = querystring.stringify(fullParams);
|
||||
let url = `${CONNECTION_STRING}${resource}/${action}?${qs}`;
|
||||
|
||||
let options = {
|
||||
method: 'GET',
|
||||
};
|
||||
|
||||
if (method === 'post') {
|
||||
options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: qs,
|
||||
};
|
||||
url = `${CONNECTION_STRING}${resource}/${action}`;
|
||||
}
|
||||
|
||||
return makeRequest(url, options).then(response => response.data);
|
||||
});
|
||||
};
|
||||
|
||||
Lbryio.authToken = null;
|
||||
|
||||
Lbryio.getAuthToken = () =>
|
||||
new Promise(resolve => {
|
||||
if (Lbryio.authToken) {
|
||||
resolve(Lbryio.authToken);
|
||||
} else {
|
||||
ipcRenderer.once('auth-token-response', (event, token) => {
|
||||
Lbryio.authToken = token;
|
||||
return resolve(token);
|
||||
});
|
||||
ipcRenderer.send('get-auth-token');
|
||||
}
|
||||
});
|
||||
|
||||
Lbryio.setAuthToken = token => {
|
||||
Lbryio.authToken = token ? token.toString().trim() : null;
|
||||
ipcRenderer.send('set-auth-token', token);
|
||||
};
|
||||
|
||||
Lbryio.getCurrentUser = () => Lbryio.call('user', 'me');
|
||||
|
||||
Lbryio.authenticate = () => {
|
||||
if (!Lbryio.enabled) {
|
||||
return new Promise(resolve => {
|
||||
resolve({
|
||||
id: 1,
|
||||
language: 'en',
|
||||
primary_email: 'disabled@lbry.io',
|
||||
has_verified_email: true,
|
||||
is_identity_verified: true,
|
||||
is_reward_approved: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (Lbryio.authenticationPromise === null) {
|
||||
Lbryio.authenticationPromise = new Promise((resolve, reject) => {
|
||||
Lbryio.getAuthToken()
|
||||
.then(token => {
|
||||
if (!token || token.length > 60) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check that token works
|
||||
return Lbryio.getCurrentUser()
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
})
|
||||
.then(isTokenValid => {
|
||||
if (isTokenValid) {
|
||||
return reject;
|
||||
}
|
||||
|
||||
return Lbry.status()
|
||||
.then(status =>
|
||||
Lbryio.call(
|
||||
'user',
|
||||
'new',
|
||||
{
|
||||
auth_token: '',
|
||||
language: 'en',
|
||||
app_id: status.installation_id,
|
||||
},
|
||||
'post'
|
||||
)
|
||||
)
|
||||
.then(response => {
|
||||
if (!response.auth_token) {
|
||||
throw new Error(__('auth_token is missing from response'));
|
||||
}
|
||||
return Lbryio.setAuthToken(response.auth_token);
|
||||
});
|
||||
})
|
||||
.then(Lbryio.getCurrentUser)
|
||||
.then(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
return Lbryio.authenticationPromise;
|
||||
};
|
||||
|
||||
Lbryio.getStripeToken = () =>
|
||||
CONNECTION_STRING.startsWith('http://localhost:')
|
||||
? 'pk_test_NoL1JWL7i1ipfhVId5KfDZgo'
|
||||
: 'pk_live_e8M4dRNnCCbmpZzduEUZBgJO';
|
||||
|
||||
export default Lbryio;
|
|
@ -1,9 +1,8 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { selectUserIsRewardApproved } from 'redux/selectors/user';
|
||||
import { selectUserIsRewardApproved, selectUnclaimedRewardValue } from 'lbryinc';
|
||||
import { selectBalance, doHideNotification } from 'lbry-redux';
|
||||
import { selectUnclaimedRewardValue } from 'redux/selectors/rewards';
|
||||
import * as settings from 'constants/settings';
|
||||
import ModalCreditIntro from './view';
|
||||
|
||||
|
@ -25,4 +24,7 @@ const perform = dispatch => () => ({
|
|||
},
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ModalCreditIntro);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(ModalCreditIntro);
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as settings from 'constants/settings';
|
|||
import { connect } from 'react-redux';
|
||||
import { doHideNotification } from 'lbry-redux';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { selectEmailToVerify, selectUser } from 'redux/selectors/user';
|
||||
import { selectEmailToVerify, selectUser } from 'lbryinc';
|
||||
import ModalEmailCollection from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -17,4 +17,7 @@ const perform = dispatch => () => ({
|
|||
},
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ModalEmailCollection);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(ModalEmailCollection);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import rewards from 'rewards';
|
||||
import { rewards, makeSelectRewardByType } from 'lbryinc';
|
||||
import { connect } from 'react-redux';
|
||||
import { doHideNotification } from 'lbry-redux';
|
||||
import { makeSelectRewardByType } from 'redux/selectors/rewards';
|
||||
import ModalFirstReward from './view';
|
||||
|
||||
const select = state => {
|
||||
|
@ -16,4 +15,7 @@ const perform = dispatch => ({
|
|||
closeModal: () => dispatch(doHideNotification()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ModalFirstReward);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(ModalFirstReward);
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import React from 'react';
|
||||
import * as settings from 'constants/settings';
|
||||
import { connect } from 'react-redux';
|
||||
import { doHideNotification } from 'lbry-redux';
|
||||
import { doSetClientSetting } from 'redux/actions/settings';
|
||||
import { selectPhoneToVerify, selectUser } from 'redux/selectors/user';
|
||||
import { selectPhoneToVerify, selectUser } from 'lbryinc';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import ModalPhoneCollection from './view';
|
||||
|
||||
|
@ -19,4 +16,7 @@ const perform = dispatch => () => ({
|
|||
},
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ModalPhoneCollection);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(ModalPhoneCollection);
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
selectNotificationProps,
|
||||
} from 'lbry-redux';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { selectUser, selectUserIsVerificationCandidate } from 'redux/selectors/user';
|
||||
import { selectUser, selectUserIsVerificationCandidate } from 'lbryinc';
|
||||
|
||||
import ModalRouter from './view';
|
||||
|
||||
|
@ -32,4 +32,7 @@ const perform = dispatch => ({
|
|||
openModal: notification => dispatch(doNotify(notification)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(ModalRouter);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(ModalRouter);
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
selectUser,
|
||||
selectUserIsPending,
|
||||
selectIdentityVerifyIsPending,
|
||||
} from 'redux/selectors/user';
|
||||
} from 'lbryinc';
|
||||
import AuthPage from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
@ -26,4 +26,7 @@ const perform = dispatch => ({
|
|||
navigate: path => dispatch(doNavigate(path)),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(AuthPage);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(AuthPage);
|
||||
|
|
|
@ -21,7 +21,7 @@ type Props = {
|
|||
navigate: (string, ?{}) => void,
|
||||
};
|
||||
|
||||
export class AuthPage extends React.PureComponent<Props> {
|
||||
class AuthPage extends React.PureComponent<Props> {
|
||||
componentWillMount() {
|
||||
this.navigateIfAuthenticated(this.props);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doAuthNavigate } from 'redux/actions/navigation';
|
||||
import { doFetchAccessToken } from 'redux/actions/user';
|
||||
import { doFetchAccessToken, selectAccessToken, selectUser } from 'lbryinc';
|
||||
import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import { selectAccessToken, selectUser } from 'redux/selectors/user';
|
||||
import HelpPage from './view';
|
||||
|
||||
const select = state => ({
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import InvitePage from './view';
|
||||
import { doFetchInviteStatus } from 'redux/actions/user';
|
||||
import {
|
||||
doFetchInviteStatus,
|
||||
selectUserInviteStatusFailed,
|
||||
selectUserInviteStatusIsPending,
|
||||
} from 'redux/selectors/user';
|
||||
} from 'lbryinc';
|
||||
import InvitePage from './view';
|
||||
|
||||
const select = state => ({
|
||||
isFailed: selectUserInviteStatusFailed(state),
|
||||
|
@ -16,4 +15,7 @@ const perform = dispatch => ({
|
|||
fetchInviteStatus: () => dispatch(doFetchInviteStatus()),
|
||||
});
|
||||
|
||||
export default connect(select, perform)(InvitePage);
|
||||
export default connect(
|
||||
select,
|
||||
perform
|
||||
)(InvitePage);
|
||||
|
|
|
@ -3,10 +3,10 @@ import {
|
|||
selectFetchingRewards,
|
||||
selectUnclaimedRewards,
|
||||
selectClaimedRewards,
|
||||
} from 'redux/selectors/rewards';
|
||||
import { selectUser } from 'redux/selectors/user';
|
||||
selectUser,
|
||||
doRewardList,
|
||||
} from 'lbryinc';
|
||||
import { doAuthNavigate, doNavigate } from 'redux/actions/navigation';
|
||||
import { doRewardList } from 'redux/actions/rewards';
|
||||
import { selectDaemonSettings } from 'redux/selectors/settings';
|
||||
import RewardsPage from './view';
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import Native from 'native';
|
|||
import { doFetchRewardedContent } from 'redux/actions/content';
|
||||
import { doFetchDaemonSettings } from 'redux/actions/settings';
|
||||
import { doAuthNavigate } from 'redux/actions/navigation';
|
||||
import { doAuthenticate } from 'redux/actions/user';
|
||||
import { doCheckSubscriptionsInit } from 'redux/actions/subscriptions';
|
||||
import {
|
||||
selectIsUpgradeSkipped,
|
||||
|
@ -28,7 +27,8 @@ import {
|
|||
selectRemoteVersion,
|
||||
selectUpgradeTimer,
|
||||
} from 'redux/selectors/app';
|
||||
import { lbrySettings as config } from 'package.json';
|
||||
import { doAuthenticate } from 'lbryinc';
|
||||
import { lbrySettings as config, version as appVersion } from 'package.json';
|
||||
|
||||
const { autoUpdater } = remote.require('electron-updater');
|
||||
const { download } = remote.require('electron-dl');
|
||||
|
@ -333,7 +333,7 @@ export function doDaemonReady() {
|
|||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
||||
dispatch(doAuthenticate());
|
||||
dispatch(doAuthenticate(appVersion));
|
||||
dispatch({ type: ACTIONS.DAEMON_READY });
|
||||
dispatch(doFetchDaemonSettings());
|
||||
dispatch(doBalanceSubscribe());
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import Lbryio from 'lbryio';
|
||||
import { doAlertError } from 'redux/actions/app';
|
||||
import { doNavigate } from 'redux/actions/navigation';
|
||||
import {
|
||||
|
@ -32,6 +31,7 @@ import { makeSelectClientSetting, selectosNotificationsEnabled } from 'redux/sel
|
|||
import setBadge from 'util/setBadge';
|
||||
import setProgressBar from 'util/setProgressBar';
|
||||
import analytics from 'analytics';
|
||||
import { Lbryio } from 'lbryinc';
|
||||
|
||||
const DOWNLOAD_POLL_INTERVAL = 250;
|
||||
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbryio from 'lbryio';
|
||||
import { doNotify, MODALS } from 'lbry-redux';
|
||||
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
|
||||
import { selectUserIsRewardApproved } from 'redux/selectors/user';
|
||||
import rewards from 'rewards';
|
||||
|
||||
export function doRewardList() {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_REWARDS_STARTED,
|
||||
});
|
||||
|
||||
Lbryio.call('reward', 'list', { multiple_rewards_per_type: true })
|
||||
.then(userRewards => {
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_REWARDS_COMPLETED,
|
||||
data: { userRewards },
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_REWARDS_COMPLETED,
|
||||
data: { userRewards: [] },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doClaimRewardType(rewardType, options) {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const unclaimedRewards = selectUnclaimedRewards(state);
|
||||
const reward = unclaimedRewards.find(ur => ur.reward_type === rewardType);
|
||||
const userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||
|
||||
if (!reward || reward.transaction_id) {
|
||||
// already claimed or doesn't exist, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userIsRewardApproved && rewardType !== rewards.TYPE_CONFIRM_EMAIL) {
|
||||
if (!options || !options.failSilently) {
|
||||
const action = doNotify({
|
||||
id: MODALS.REWARD_APPROVAL_REQUIRED,
|
||||
isError: false,
|
||||
});
|
||||
dispatch(action);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.CLAIM_REWARD_STARTED,
|
||||
data: { reward },
|
||||
});
|
||||
|
||||
const success = successReward => {
|
||||
dispatch(doRewardList());
|
||||
dispatch({
|
||||
type: ACTIONS.CLAIM_REWARD_SUCCESS,
|
||||
data: {
|
||||
reward: successReward,
|
||||
},
|
||||
});
|
||||
if (successReward.reward_type === rewards.TYPE_NEW_USER) {
|
||||
const action = doNotify({
|
||||
id: MODALS.FIRST_REWARD,
|
||||
isError: false,
|
||||
});
|
||||
dispatch(action);
|
||||
}
|
||||
};
|
||||
|
||||
const failure = error => {
|
||||
dispatch({
|
||||
type: ACTIONS.CLAIM_REWARD_FAILURE,
|
||||
data: {
|
||||
reward,
|
||||
error: !options || !options.failSilently ? error : undefined,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
rewards.claimReward(rewardType).then(success, failure);
|
||||
};
|
||||
}
|
||||
|
||||
export function doClaimEligiblePurchaseRewards() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const unclaimedRewards = selectUnclaimedRewards(state);
|
||||
const userIsRewardApproved = selectUserIsRewardApproved(state);
|
||||
|
||||
if (!userIsRewardApproved || !Lbryio.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (unclaimedRewards.find(ur => ur.reward_type === rewards.TYPE_FIRST_STREAM)) {
|
||||
dispatch(doClaimRewardType(rewards.TYPE_FIRST_STREAM));
|
||||
} else {
|
||||
[rewards.TYPE_MANY_DOWNLOADS, rewards.TYPE_FEATURED_DOWNLOAD].forEach(type => {
|
||||
dispatch(doClaimRewardType(type, { failSilently: true }));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function doClaimRewardClearError(reward) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.CLAIM_REWARD_CLEAR_ERROR,
|
||||
data: { reward },
|
||||
});
|
||||
};
|
||||
}
|
|
@ -2,16 +2,14 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import * as NOTIFICATION_TYPES from 'constants/notification_types';
|
||||
import * as SETTINGS from 'constants/settings';
|
||||
import rewards from 'rewards';
|
||||
import { Lbryio, rewards, doClaimRewardType } from 'lbryinc';
|
||||
import type { Dispatch, SubscriptionNotifications } from 'redux/reducers/subscriptions';
|
||||
import type { Subscription } from 'types/subscription';
|
||||
import { selectSubscriptions } from 'redux/selectors/subscriptions';
|
||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||
import { Lbry, buildURI, parseURI, selectCurrentPage } from 'lbry-redux';
|
||||
import { doPurchaseUri, doFetchClaimsByChannel } from 'redux/actions/content';
|
||||
import { doClaimRewardType } from 'redux/actions/rewards';
|
||||
import Promise from 'bluebird';
|
||||
import Lbryio from 'lbryio';
|
||||
|
||||
const CHECK_SUBSCRIPTIONS_INTERVAL = 15 * 60 * 1000;
|
||||
const SUBSCRIPTION_DOWNLOAD_LIMIT = 1;
|
||||
|
@ -246,7 +244,7 @@ export const doChannelSubscribe = (subscription: Subscription) => (
|
|||
claim_id: claimId,
|
||||
});
|
||||
|
||||
dispatch(doClaimRewardType(rewards.SUBSCRIPTION, { failSilently: true }));
|
||||
dispatch(doClaimRewardType(rewards.TYPE_SUBSCRIPTION, { failSilently: true }));
|
||||
}
|
||||
|
||||
dispatch(doCheckSubscription(subscription.uri, true));
|
||||
|
|
|
@ -1,360 +0,0 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
import Lbryio from 'lbryio';
|
||||
import { Lbry, doNotify, MODALS, doHideNotification } from 'lbry-redux';
|
||||
import { doClaimRewardType, doRewardList } from 'redux/actions/rewards';
|
||||
import {
|
||||
selectEmailToVerify,
|
||||
selectPhoneToVerify,
|
||||
selectUserCountryCode,
|
||||
} from 'redux/selectors/user';
|
||||
import rewards from 'rewards';
|
||||
import analytics from 'analytics';
|
||||
import pjson from 'package.json';
|
||||
|
||||
export function doFetchInviteStatus() {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_STATUS_FETCH_STARTED,
|
||||
});
|
||||
|
||||
Lbryio.call('user', 'invite_status')
|
||||
.then(status => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS,
|
||||
data: {
|
||||
invitesRemaining: status.invites_remaining ? status.invites_remaining : 0,
|
||||
invitees: status.invitees,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doInstallNew() {
|
||||
const payload = { app_version: pjson.version };
|
||||
Lbry.status().then(status => {
|
||||
payload.app_id = status.installation_id;
|
||||
if (status.dht) payload.node_id = status.dht.node_id;
|
||||
Lbry.version().then(version => {
|
||||
payload.daemon_version = version.lbrynet_version;
|
||||
payload.operating_system = version.os_system;
|
||||
payload.platform = version.platform;
|
||||
Lbryio.call('install', 'new', payload);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function doAuthenticate() {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.AUTHENTICATION_STARTED,
|
||||
});
|
||||
Lbryio.authenticate()
|
||||
.then(user => {
|
||||
analytics.setUser(user);
|
||||
dispatch({
|
||||
type: ACTIONS.AUTHENTICATION_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
dispatch(doRewardList());
|
||||
dispatch(doFetchInviteStatus());
|
||||
doInstallNew();
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch(doNotify({ id: MODALS.AUTHENTICATION_FAILURE }));
|
||||
dispatch({
|
||||
type: ACTIONS.AUTHENTICATION_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserFetch() {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_FETCH_STARTED,
|
||||
});
|
||||
Lbryio.getCurrentUser()
|
||||
.then(user => {
|
||||
analytics.setUser(user);
|
||||
dispatch(doRewardList());
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.USER_FETCH_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_FETCH_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserPhoneReset() {
|
||||
return {
|
||||
type: ACTIONS.USER_PHONE_RESET,
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserPhoneNew(phone, countryCode) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_PHONE_NEW_STARTED,
|
||||
data: { phone, country_code: countryCode },
|
||||
});
|
||||
|
||||
const success = () => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_PHONE_NEW_SUCCESS,
|
||||
data: { phone },
|
||||
});
|
||||
};
|
||||
|
||||
const failure = error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_PHONE_NEW_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
};
|
||||
|
||||
Lbryio.call(
|
||||
'user',
|
||||
'phone_number_new',
|
||||
{ phone_number: phone, country_code: countryCode },
|
||||
'post'
|
||||
).then(success, failure);
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserPhoneVerifyFailure(error) {
|
||||
return {
|
||||
type: ACTIONS.USER_PHONE_VERIFY_FAILURE,
|
||||
data: { error },
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserPhoneVerify(verificationCode) {
|
||||
return (dispatch, getState) => {
|
||||
const phoneNumber = selectPhoneToVerify(getState());
|
||||
const countryCode = selectUserCountryCode(getState());
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.USER_PHONE_VERIFY_STARTED,
|
||||
code: verificationCode,
|
||||
});
|
||||
|
||||
Lbryio.call(
|
||||
'user',
|
||||
'phone_number_confirm',
|
||||
{
|
||||
verification_code: verificationCode,
|
||||
phone_number: phoneNumber,
|
||||
country_code: countryCode,
|
||||
},
|
||||
'post'
|
||||
)
|
||||
.then(user => {
|
||||
if (user.is_identity_verified) {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_PHONE_VERIFY_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
dispatch(doHideNotification());
|
||||
dispatch(doClaimRewardType(rewards.TYPE_NEW_USER));
|
||||
}
|
||||
})
|
||||
.catch(error => dispatch(doUserPhoneVerifyFailure(error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserEmailNew(email) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_NEW_STARTED,
|
||||
email,
|
||||
});
|
||||
|
||||
const success = () => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_NEW_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
dispatch(doUserFetch());
|
||||
};
|
||||
|
||||
const failure = error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_NEW_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
};
|
||||
|
||||
Lbryio.call('user_email', 'new', { email, send_verification_email: true }, 'post')
|
||||
.catch(error => {
|
||||
if (error.response && error.response.status === 409) {
|
||||
return Lbryio.call(
|
||||
'user_email',
|
||||
'resend_token',
|
||||
{ email, only_if_expired: true },
|
||||
'post'
|
||||
).then(success, failure);
|
||||
}
|
||||
throw error;
|
||||
})
|
||||
.then(success, failure);
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserResendVerificationEmail(email) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_RETRY,
|
||||
email,
|
||||
});
|
||||
|
||||
const success = () => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_NEW_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
dispatch(doUserFetch());
|
||||
};
|
||||
|
||||
const failure = error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_NEW_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
};
|
||||
|
||||
Lbryio.call('user_email', 'resend_token', { email }, 'post')
|
||||
.catch(error => {
|
||||
if (error.response && error.response.status === 409) {
|
||||
throw error;
|
||||
}
|
||||
})
|
||||
.then(success, failure);
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserEmailVerifyFailure(error) {
|
||||
return {
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_FAILURE,
|
||||
data: { error },
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserEmailVerify(verificationToken, recaptcha) {
|
||||
return (dispatch, getState) => {
|
||||
const email = selectEmailToVerify(getState());
|
||||
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_STARTED,
|
||||
code: verificationToken,
|
||||
recaptcha,
|
||||
});
|
||||
|
||||
Lbryio.call(
|
||||
'user_email',
|
||||
'confirm',
|
||||
{
|
||||
verification_token: verificationToken,
|
||||
email,
|
||||
recaptcha,
|
||||
},
|
||||
'post'
|
||||
)
|
||||
.then(userEmail => {
|
||||
if (userEmail.is_verified) {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_EMAIL_VERIFY_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
dispatch(doUserFetch());
|
||||
} else {
|
||||
throw new Error('Your email is still not verified.'); // shouldn't happen
|
||||
}
|
||||
})
|
||||
.catch(error => dispatch(doUserEmailVerifyFailure(error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserIdentityVerify(stripeToken) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_IDENTITY_VERIFY_STARTED,
|
||||
token: stripeToken,
|
||||
});
|
||||
|
||||
Lbryio.call('user', 'verify_identity', { stripe_token: stripeToken }, 'post')
|
||||
.then(user => {
|
||||
if (user.is_identity_verified) {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_IDENTITY_VERIFY_SUCCESS,
|
||||
data: { user },
|
||||
});
|
||||
dispatch(doClaimRewardType(rewards.TYPE_NEW_USER));
|
||||
} else {
|
||||
throw new Error('Your identity is still not verified. This should not happen.'); // shouldn't happen
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_IDENTITY_VERIFY_FAILURE,
|
||||
data: { error: error.toString() },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function doFetchAccessToken() {
|
||||
return dispatch => {
|
||||
const success = token =>
|
||||
dispatch({
|
||||
type: ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS,
|
||||
data: { token },
|
||||
});
|
||||
Lbryio.getAuthToken().then(success);
|
||||
};
|
||||
}
|
||||
|
||||
export function doUserInviteNew(email) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_NEW_STARTED,
|
||||
});
|
||||
|
||||
Lbryio.call('user', 'invite', { email }, 'post')
|
||||
.then(() => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_NEW_SUCCESS,
|
||||
data: { email },
|
||||
});
|
||||
|
||||
dispatch(
|
||||
doNotify({
|
||||
displayType: ['snackbar'],
|
||||
message: __('Invite sent to %s', email),
|
||||
})
|
||||
);
|
||||
|
||||
dispatch(doFetchInviteStatus());
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({
|
||||
type: ACTIONS.USER_INVITE_NEW_FAILURE,
|
||||
data: { error },
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
const defaultState = {
|
||||
fetching: false,
|
||||
claimedRewardsById: {}, // id => reward
|
||||
unclaimedRewards: [],
|
||||
claimPendingByType: {},
|
||||
claimErrorsByType: {},
|
||||
};
|
||||
|
||||
reducers[ACTIONS.FETCH_REWARDS_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
fetching: true,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.FETCH_REWARDS_COMPLETED] = (state, action) => {
|
||||
const { userRewards } = action.data;
|
||||
|
||||
const unclaimedRewards = [];
|
||||
const claimedRewards = {};
|
||||
userRewards.forEach(reward => {
|
||||
if (reward.transaction_id) {
|
||||
claimedRewards[reward.id] = reward;
|
||||
} else {
|
||||
unclaimedRewards.push(reward);
|
||||
}
|
||||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
claimedRewardsById: claimedRewards,
|
||||
unclaimedRewards,
|
||||
fetching: false,
|
||||
});
|
||||
};
|
||||
|
||||
function setClaimRewardState(state, reward, isClaiming, errorMessage = '') {
|
||||
const newClaimPendingByType = Object.assign({}, state.claimPendingByType);
|
||||
const newClaimErrorsByType = Object.assign({}, state.claimErrorsByType);
|
||||
if (isClaiming) {
|
||||
newClaimPendingByType[reward.reward_type] = isClaiming;
|
||||
} else {
|
||||
delete newClaimPendingByType[reward.reward_type];
|
||||
}
|
||||
if (errorMessage) {
|
||||
newClaimErrorsByType[reward.reward_type] = errorMessage;
|
||||
} else {
|
||||
delete newClaimErrorsByType[reward.reward_type];
|
||||
}
|
||||
|
||||
return Object.assign({}, state, {
|
||||
claimPendingByType: newClaimPendingByType,
|
||||
claimErrorsByType: newClaimErrorsByType,
|
||||
});
|
||||
}
|
||||
|
||||
reducers[ACTIONS.CLAIM_REWARD_STARTED] = (state, action) => {
|
||||
const { reward } = action.data;
|
||||
|
||||
return setClaimRewardState(state, reward, true, '');
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLAIM_REWARD_SUCCESS] = (state, action) => {
|
||||
const { reward } = action.data;
|
||||
const { unclaimedRewards } = state;
|
||||
|
||||
const index = unclaimedRewards.findIndex(ur => ur.reward_type === reward.reward_type);
|
||||
unclaimedRewards.splice(index, 1);
|
||||
|
||||
const { claimedRewardsById } = state;
|
||||
claimedRewardsById[reward.id] = reward;
|
||||
|
||||
const newState = {
|
||||
...state,
|
||||
unclaimedRewards: [...unclaimedRewards],
|
||||
claimedRewardsById: { ...claimedRewardsById },
|
||||
};
|
||||
|
||||
return setClaimRewardState(newState, reward, false, '');
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLAIM_REWARD_FAILURE] = (state, action) => {
|
||||
const { reward, error } = action.data;
|
||||
|
||||
return setClaimRewardState(state, reward, false, error ? error.message : '');
|
||||
};
|
||||
|
||||
reducers[ACTIONS.CLAIM_REWARD_CLEAR_ERROR] = (state, action) => {
|
||||
const { reward } = action.data;
|
||||
|
||||
return setClaimRewardState(state, reward, state.claimPendingByType[reward.reward_type], '');
|
||||
};
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
const handler = reducers[action.type];
|
||||
if (handler) return handler(state, action);
|
||||
return state;
|
||||
}
|
|
@ -1,222 +0,0 @@
|
|||
import * as ACTIONS from 'constants/action_types';
|
||||
|
||||
const reducers = {};
|
||||
|
||||
const defaultState = {
|
||||
authenticationIsPending: false,
|
||||
userIsPending: false,
|
||||
emailNewIsPending: false,
|
||||
emailNewErrorMessage: '',
|
||||
emailToVerify: '',
|
||||
inviteNewErrorMessage: '',
|
||||
inviteNewIsPending: false,
|
||||
inviteStatusIsPending: false,
|
||||
invitesRemaining: undefined,
|
||||
invitees: undefined,
|
||||
user: undefined,
|
||||
};
|
||||
|
||||
reducers[ACTIONS.AUTHENTICATION_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
authenticationIsPending: true,
|
||||
userIsPending: true,
|
||||
user: defaultState.user,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.AUTHENTICATION_SUCCESS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
authenticationIsPending: false,
|
||||
userIsPending: false,
|
||||
user: action.data.user,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.AUTHENTICATION_FAILURE] = state =>
|
||||
Object.assign({}, state, {
|
||||
authenticationIsPending: false,
|
||||
userIsPending: false,
|
||||
user: null,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_FETCH_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
userIsPending: true,
|
||||
user: defaultState.user,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_FETCH_SUCCESS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
userIsPending: false,
|
||||
user: action.data.user,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_FETCH_FAILURE] = state =>
|
||||
Object.assign({}, state, {
|
||||
userIsPending: true,
|
||||
user: null,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_NEW_STARTED] = (state, action) => {
|
||||
const user = Object.assign({}, state.user);
|
||||
user.country_code = action.data.country_code;
|
||||
return Object.assign({}, state, {
|
||||
phoneNewIsPending: true,
|
||||
phoneNewErrorMessage: '',
|
||||
user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_NEW_SUCCESS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
phoneToVerify: action.data.phone,
|
||||
phoneNewIsPending: false,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_RESET] = state =>
|
||||
Object.assign({}, state, {
|
||||
phoneToVerify: null,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_NEW_FAILURE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
phoneNewIsPending: false,
|
||||
phoneNewErrorMessage: action.data.error,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_VERIFY_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
phoneVerifyIsPending: true,
|
||||
phoneVerifyErrorMessage: '',
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_VERIFY_SUCCESS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
phoneToVerify: '',
|
||||
phoneVerifyIsPending: false,
|
||||
user: action.data.user,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_PHONE_VERIFY_FAILURE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
phoneVerifyIsPending: false,
|
||||
phoneVerifyErrorMessage: action.data.error,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
emailNewIsPending: true,
|
||||
emailNewErrorMessage: '',
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_SUCCESS] = (state, action) => {
|
||||
const user = Object.assign({}, state.user);
|
||||
user.primary_email = action.data.email;
|
||||
return Object.assign({}, state, {
|
||||
emailToVerify: action.data.email,
|
||||
emailNewIsPending: false,
|
||||
user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_EXISTS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
emailToVerify: action.data.email,
|
||||
emailNewIsPending: false,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_NEW_FAILURE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
emailNewIsPending: false,
|
||||
emailNewErrorMessage: action.data.error,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_VERIFY_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
emailVerifyIsPending: true,
|
||||
emailVerifyErrorMessage: '',
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_VERIFY_SUCCESS] = (state, action) => {
|
||||
const user = Object.assign({}, state.user);
|
||||
user.primary_email = action.data.email;
|
||||
return Object.assign({}, state, {
|
||||
emailToVerify: '',
|
||||
emailVerifyIsPending: false,
|
||||
user,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.USER_EMAIL_VERIFY_FAILURE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
emailVerifyIsPending: false,
|
||||
emailVerifyErrorMessage: action.data.error,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_IDENTITY_VERIFY_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
identityVerifyIsPending: true,
|
||||
identityVerifyErrorMessage: '',
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_IDENTITY_VERIFY_SUCCESS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
identityVerifyIsPending: false,
|
||||
identityVerifyErrorMessage: '',
|
||||
user: action.data.user,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_IDENTITY_VERIFY_FAILURE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
identityVerifyIsPending: false,
|
||||
identityVerifyErrorMessage: action.data.error,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.FETCH_ACCESS_TOKEN_SUCCESS] = (state, action) => {
|
||||
const { token } = action.data;
|
||||
|
||||
return Object.assign({}, state, {
|
||||
accessToken: token,
|
||||
});
|
||||
};
|
||||
|
||||
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
inviteStatusIsPending: true,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_SUCCESS] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
inviteStatusIsPending: false,
|
||||
invitesRemaining: action.data.invitesRemaining,
|
||||
invitees: action.data.invitees,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_INVITE_NEW_STARTED] = state =>
|
||||
Object.assign({}, state, {
|
||||
inviteNewIsPending: true,
|
||||
inviteNewErrorMessage: '',
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_INVITE_NEW_SUCCESS] = state =>
|
||||
Object.assign({}, state, {
|
||||
inviteNewIsPending: false,
|
||||
inviteNewErrorMessage: '',
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_INVITE_NEW_FAILURE] = (state, action) =>
|
||||
Object.assign({}, state, {
|
||||
inviteNewIsPending: false,
|
||||
inviteNewErrorMessage: action.data.error.message,
|
||||
});
|
||||
|
||||
reducers[ACTIONS.USER_INVITE_STATUS_FETCH_FAILURE] = state =>
|
||||
Object.assign({}, state, {
|
||||
inviteStatusIsPending: false,
|
||||
invitesRemaining: null,
|
||||
invitees: null,
|
||||
});
|
||||
|
||||
export default function reducer(state = defaultState, action) {
|
||||
const handler = reducers[action.type];
|
||||
if (handler) return handler(state, action);
|
||||
return state;
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
import { createSelector } from 'reselect';
|
||||
|
||||
const selectState = state => state.rewards || {};
|
||||
|
||||
export const selectUnclaimedRewardsByType = createSelector(
|
||||
selectState,
|
||||
state => state.unclaimedRewardsByType
|
||||
);
|
||||
|
||||
export const selectClaimedRewardsById = createSelector(
|
||||
selectState,
|
||||
state => state.claimedRewardsById
|
||||
);
|
||||
|
||||
export const selectClaimedRewards = createSelector(
|
||||
selectClaimedRewardsById,
|
||||
byId => Object.values(byId) || []
|
||||
);
|
||||
|
||||
export const selectClaimedRewardsByTransactionId = createSelector(selectClaimedRewards, rewards =>
|
||||
rewards.reduce((mapParam, reward) => {
|
||||
const map = mapParam;
|
||||
map[reward.transaction_id] = reward;
|
||||
return map;
|
||||
}, {})
|
||||
);
|
||||
|
||||
export const selectUnclaimedRewards = createSelector(selectState, state => state.unclaimedRewards);
|
||||
|
||||
export const selectFetchingRewards = createSelector(selectState, state => !!state.fetching);
|
||||
|
||||
export const selectUnclaimedRewardValue = createSelector(selectUnclaimedRewards, rewards =>
|
||||
rewards.reduce((sum, reward) => sum + reward.reward_amount, 0)
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
const selectRewardByType = (state, rewardType) =>
|
||||
selectUnclaimedRewards(state).find(reward => reward.reward_type === rewardType);
|
||||
|
||||
export const makeSelectRewardByType = () => createSelector(selectRewardByType, reward => reward);
|
||||
|
||||
export const makeSelectRewardAmountByType = () =>
|
||||
createSelector(selectRewardByType, reward => (reward ? reward.reward_amount : 0));
|
|
@ -1,118 +0,0 @@
|
|||
import { createSelector } from 'reselect';
|
||||
|
||||
export const selectState = state => state.user || {};
|
||||
|
||||
export const selectAuthenticationIsPending = createSelector(
|
||||
selectState,
|
||||
state => state.authenticationIsPending
|
||||
);
|
||||
|
||||
export const selectUserIsPending = createSelector(selectState, state => state.userIsPending);
|
||||
|
||||
export const selectUser = createSelector(selectState, state => state.user);
|
||||
|
||||
export const selectUserEmail = createSelector(
|
||||
selectUser,
|
||||
user => (user ? user.primary_email : null)
|
||||
);
|
||||
|
||||
export const selectUserPhone = createSelector(
|
||||
selectUser,
|
||||
user => (user ? user.phone_number : null)
|
||||
);
|
||||
|
||||
export const selectUserCountryCode = createSelector(
|
||||
selectUser,
|
||||
user => (user ? user.country_code : null)
|
||||
);
|
||||
|
||||
export const selectEmailToVerify = createSelector(
|
||||
selectState,
|
||||
selectUserEmail,
|
||||
(state, userEmail) => state.emailToVerify || userEmail
|
||||
);
|
||||
|
||||
export const selectPhoneToVerify = createSelector(
|
||||
selectState,
|
||||
selectUserPhone,
|
||||
(state, userPhone) => state.phoneToVerify || userPhone
|
||||
);
|
||||
|
||||
export const selectUserIsRewardApproved = createSelector(
|
||||
selectUser,
|
||||
user => user && user.is_reward_approved
|
||||
);
|
||||
|
||||
export const selectEmailNewIsPending = createSelector(
|
||||
selectState,
|
||||
state => state.emailNewIsPending
|
||||
);
|
||||
|
||||
export const selectEmailNewErrorMessage = createSelector(
|
||||
selectState,
|
||||
state => state.emailNewErrorMessage
|
||||
);
|
||||
|
||||
export const selectPhoneNewErrorMessage = createSelector(
|
||||
selectState,
|
||||
state => state.phoneNewErrorMessage
|
||||
);
|
||||
|
||||
export const selectEmailVerifyIsPending = createSelector(
|
||||
selectState,
|
||||
state => state.emailVerifyIsPending
|
||||
);
|
||||
|
||||
export const selectEmailVerifyErrorMessage = createSelector(
|
||||
selectState,
|
||||
state => state.emailVerifyErrorMessage
|
||||
);
|
||||
|
||||
export const selectPhoneVerifyErrorMessage = createSelector(
|
||||
selectState,
|
||||
state => state.phoneVerifyErrorMessage
|
||||
);
|
||||
|
||||
export const selectIdentityVerifyIsPending = createSelector(
|
||||
selectState,
|
||||
state => state.identityVerifyIsPending
|
||||
);
|
||||
|
||||
export const selectIdentityVerifyErrorMessage = createSelector(
|
||||
selectState,
|
||||
state => state.identityVerifyErrorMessage
|
||||
);
|
||||
|
||||
export const selectUserIsVerificationCandidate = createSelector(
|
||||
selectUser,
|
||||
user => user && (!user.has_verified_email || !user.is_identity_verified)
|
||||
);
|
||||
|
||||
export const selectAccessToken = createSelector(selectState, state => state.accessToken);
|
||||
|
||||
export const selectUserInviteStatusIsPending = createSelector(
|
||||
selectState,
|
||||
state => state.inviteStatusIsPending
|
||||
);
|
||||
|
||||
export const selectUserInvitesRemaining = createSelector(
|
||||
selectState,
|
||||
state => state.invitesRemaining
|
||||
);
|
||||
|
||||
export const selectUserInvitees = createSelector(selectState, state => state.invitees);
|
||||
|
||||
export const selectUserInviteStatusFailed = createSelector(
|
||||
selectUserInvitesRemaining,
|
||||
() => selectUserInvitesRemaining === null
|
||||
);
|
||||
|
||||
export const selectUserInviteNewIsPending = createSelector(
|
||||
selectState,
|
||||
state => state.inviteNewIsPending
|
||||
);
|
||||
|
||||
export const selectUserInviteNewErrorMessage = createSelector(
|
||||
selectState,
|
||||
state => state.inviteNewErrorMessage
|
||||
);
|
|
@ -1,113 +0,0 @@
|
|||
import { Lbry, doNotify } from 'lbry-redux';
|
||||
import Lbryio from 'lbryio';
|
||||
|
||||
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.SUBSCRIPTION = 'subscription';
|
||||
|
||||
rewards.claimReward = type => {
|
||||
function requestReward(resolve, reject, params) {
|
||||
if (!Lbryio.enabled) {
|
||||
reject(new Error(__('Rewards are not enabled.')));
|
||||
return;
|
||||
}
|
||||
Lbryio.call('reward', 'new', params, 'post').then(reward => {
|
||||
const message =
|
||||
reward.reward_notification || `You have claimed a ${reward.reward_amount} LBC reward.`;
|
||||
|
||||
// Display global notice
|
||||
const action = doNotify({
|
||||
message,
|
||||
linkText: __('Show All'),
|
||||
linkTarget: '/rewards',
|
||||
isError: false,
|
||||
displayType: ['snackbar'],
|
||||
});
|
||||
window.app.store.dispatch(action);
|
||||
|
||||
// Add more events here to display other places
|
||||
|
||||
resolve(reward);
|
||||
}, reject);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
Lbry.wallet_unused_address().then(address => {
|
||||
const params = {
|
||||
reward_type: type,
|
||||
wallet_address: address,
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case rewards.TYPE_FIRST_CHANNEL:
|
||||
Lbry.claim_list_mine()
|
||||
.then(claims => {
|
||||
const claim = claims
|
||||
.reverse()
|
||||
.find(
|
||||
foundClaim =>
|
||||
foundClaim.name.length &&
|
||||
foundClaim.name[0] === '@' &&
|
||||
foundClaim.txid.length &&
|
||||
foundClaim.category === 'claim'
|
||||
);
|
||||
if (claim) {
|
||||
params.transaction_id = claim.txid;
|
||||
requestReward(resolve, reject, params);
|
||||
} else {
|
||||
reject(new Error(__('Please create a channel identity first.')));
|
||||
}
|
||||
})
|
||||
.catch(reject);
|
||||
break;
|
||||
|
||||
case rewards.TYPE_FIRST_PUBLISH:
|
||||
Lbry.claim_list_mine()
|
||||
.then(claims => {
|
||||
const claim = claims
|
||||
.reverse()
|
||||
.find(
|
||||
foundClaim =>
|
||||
foundClaim.name.length &&
|
||||
foundClaim.name[0] !== '@' &&
|
||||
foundClaim.txid.length &&
|
||||
foundClaim.category === 'claim'
|
||||
);
|
||||
if (claim) {
|
||||
params.transaction_id = claim.txid;
|
||||
requestReward(resolve, reject, params);
|
||||
} else {
|
||||
reject(
|
||||
claims.length
|
||||
? new Error(
|
||||
__(
|
||||
'Please publish something and wait for confirmation by the network to claim this reward.'
|
||||
)
|
||||
)
|
||||
: new Error(__('Please publish something to claim this reward.'))
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(reject);
|
||||
break;
|
||||
|
||||
case rewards.TYPE_FIRST_STREAM:
|
||||
case rewards.TYPE_NEW_USER:
|
||||
default:
|
||||
requestReward(resolve, reject, params);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default rewards;
|
|
@ -12,9 +12,8 @@ import {
|
|||
blacklistReducer,
|
||||
} from 'lbry-redux';
|
||||
import navigationReducer from 'redux/reducers/navigation';
|
||||
import rewardsReducer from 'redux/reducers/rewards';
|
||||
import settingsReducer from 'redux/reducers/settings';
|
||||
import userReducer from 'redux/reducers/user';
|
||||
import { userReducer, rewardsReducer } from 'lbryinc';
|
||||
import shapeShiftReducer from 'redux/reducers/shape_shift';
|
||||
import subscriptionsReducer from 'redux/reducers/subscriptions';
|
||||
import publishReducer from 'redux/reducers/publish';
|
||||
|
|
14
yarn.lock
14
yarn.lock
|
@ -5655,6 +5655,13 @@ lazy-val@^1.0.3:
|
|||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/a8e81949837171e94e649fce6f7c7a8b7faadd51"
|
||||
dependencies:
|
||||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
||||
lbry-redux@lbryio/lbry-redux#d1cee82af119c0c5f98ec27f94b2e7f61e34b54c:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/d1cee82af119c0c5f98ec27f94b2e7f61e34b54c"
|
||||
|
@ -5662,6 +5669,13 @@ lbry-redux@lbryio/lbry-redux#d1cee82af119c0c5f98ec27f94b2e7f61e34b54c:
|
|||
proxy-polyfill "0.1.6"
|
||||
reselect "^3.0.0"
|
||||
|
||||
lbryinc@lbryio/lbryinc#c09aa2645ecccb33c83e9a9545ff119232910f6f:
|
||||
version "0.0.1"
|
||||
resolved "https://codeload.github.com/lbryio/lbryinc/tar.gz/c09aa2645ecccb33c83e9a9545ff119232910f6f"
|
||||
dependencies:
|
||||
lbry-redux lbryio/lbry-redux
|
||||
reselect "^3.0.0"
|
||||
|
||||
lcid@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
|
||||
|
|
Loading…
Reference in a new issue