diff --git a/app/src/component/AppNavigator.js b/app/src/component/AppNavigator.js index 646d5dea..54eb6d15 100644 --- a/app/src/component/AppNavigator.js +++ b/app/src/component/AppNavigator.js @@ -38,6 +38,7 @@ import { doDeleteCompleteBlobs } from 'redux/actions/file'; import { selectDrawerStack } from 'redux/selectors/drawer'; import { SETTINGS, doDismissToast, doToast, selectToast } from 'lbry-redux'; import { + doUserCheckEmailVerified, doUserEmailVerify, doUserEmailVerifyFailure, selectEmailToVerify, @@ -235,8 +236,10 @@ class AppWithNavigationState extends React.Component { constructor() { super(); + this.emailVerifyCheckInterval = null; this.state = { - emailVerifyDone: false + emailVerifyDone: false, + verifyPending: false }; } @@ -262,15 +265,37 @@ class AppWithNavigationState extends React.Component { } componentDidMount() { + this.emailVerifyCheckInterval = setInterval(() => this.checkEmailVerification(), 5000); Linking.addEventListener('url', this._handleUrl); } + checkEmailVerification = () => { + const { dispatch } = this.props; + AsyncStorage.getItem(Constants.KEY_EMAIL_VERIFY_PENDING).then(pending => { + this.setState({ verifyPending: ('true' === pending) }); + if ('true' === pending) { + dispatch(doUserCheckEmailVerified()); + } + }); + } + componentWillUnmount() { AppState.removeEventListener('change', this._handleAppStateChange); BackHandler.removeEventListener('hardwareBackPress'); Linking.removeEventListener('url', this._handleUrl); } + componentDidUpdate() { + const { user } = this.props; + if (this.state.verifyPending && this.emailVerifyCheckInterval > 0 && user && user.has_verified_email) { + clearInterval(this.emailVerifyCheckInterval); + AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'false'); + this.setState({ verifyPending: false }); + + ToastAndroid.show('Your email address was successfully verified.', ToastAndroid.LONG); + } + } + componentWillUpdate(nextProps) { const { dispatch } = this.props; const { diff --git a/app/src/component/emailRewardSubcard/index.js b/app/src/component/emailRewardSubcard/index.js index b4941ce9..c34b3b5c 100644 --- a/app/src/component/emailRewardSubcard/index.js +++ b/app/src/component/emailRewardSubcard/index.js @@ -1,9 +1,10 @@ import { connect } from 'react-redux'; import { doUserEmailNew, + doUserResendVerificationEmail, selectEmailNewErrorMessage, selectEmailNewIsPending, - selectEmailToVerify + selectEmailToVerify, } from 'lbryinc'; import { doToast } from 'lbry-redux'; import EmailRewardSubcard from './view'; @@ -16,7 +17,8 @@ const select = state => ({ const perform = dispatch => ({ addUserEmail: email => dispatch(doUserEmailNew(email)), - notify: data => dispatch(doToast(data)) + notify: data => dispatch(doToast(data)), + resendVerificationEmail: email => dispatch(doUserResendVerificationEmail(email)) }); export default connect(select, perform)(EmailRewardSubcard); diff --git a/app/src/component/emailRewardSubcard/view.js b/app/src/component/emailRewardSubcard/view.js index fe3ee652..a17303f1 100644 --- a/app/src/component/emailRewardSubcard/view.js +++ b/app/src/component/emailRewardSubcard/view.js @@ -18,6 +18,8 @@ import rewardStyle from '../../styles/reward'; class EmailRewardSubcard extends React.PureComponent { state = { email: null, + emailAlreadySet: false, + previousEmail: null, verfiyStarted: false }; @@ -25,9 +27,9 @@ class EmailRewardSubcard extends React.PureComponent { const { emailToVerify } = this.props; AsyncStorage.getItem(Constants.KEY_FIRST_RUN_EMAIL).then(email => { if (email && email.trim().length > 0) { - this.setState({ email }); + this.setState({ email, emailAlreadySet: true, previousEmail: email }); } else { - this.setState({ email: emailToVerify }); + this.setState({ email: emailToVerify, previousEmail: emailToVerify }); } }); } @@ -41,9 +43,8 @@ class EmailRewardSubcard extends React.PureComponent { notify({ message: String(emailNewErrorMessage), isError: true }); this.setState({ verifyStarted: false }); } else { - notify({ - message: 'Please follow the instructions in the email sent to your address to continue.', - }); + notify({ message: 'Please follow the instructions in the email sent to your address to continue.' }); + AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true'); } } } @@ -59,7 +60,7 @@ class EmailRewardSubcard extends React.PureComponent { return; } - const { addUserEmail, notify } = this.props; + const { addUserEmail, notify, resendVerificationEmail } = this.props; const { email } = this.state; if (!email || email.trim().length === 0 || email.indexOf('@') === -1) { return notify({ @@ -68,6 +69,14 @@ class EmailRewardSubcard extends React.PureComponent { } this.setState({ verifyStarted: true }); + if (this.state.emailAlreadySet && this.state.previousEmail === email) { + // resend verification email if there was one previously set (and it wasn't changed) + resendVerificationEmail(email); + AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true'); + notify({ message: 'Please follow the instructions in the email sent to your address to continue.' }); + return; + } + addUserEmail(email); } diff --git a/app/src/component/rewardSummary/view.js b/app/src/component/rewardSummary/view.js index 9adf6e55..ba0f04af 100644 --- a/app/src/component/rewardSummary/view.js +++ b/app/src/component/rewardSummary/view.js @@ -44,6 +44,10 @@ class RewardSummary extends React.Component { render() { const { fetching, navigation, unclaimedRewardAmount, user } = this.props; + if (!user) { + return null; + } + if (this.state.dismissed || (user && user.is_reward_approved) || this.state.actionsLeft === 0 || diff --git a/app/src/component/suggestedSubscriptions/view.js b/app/src/component/suggestedSubscriptions/view.js index cd2605d7..b51e1af3 100644 --- a/app/src/component/suggestedSubscriptions/view.js +++ b/app/src/component/suggestedSubscriptions/view.js @@ -22,12 +22,12 @@ class SuggestedSubscriptions extends React.PureComponent { return suggested ? ( { console.log(item); return ( + renderItem={ ({item, index, section}) => ( - ); } + ) } renderSectionHeader={ ({section: {title}}) => { diff --git a/app/src/constants.js b/app/src/constants.js index a4298d5a..3949e994 100644 --- a/app/src/constants.js +++ b/app/src/constants.js @@ -1,6 +1,7 @@ const Constants = { KEY_FIRST_RUN_EMAIL: "firstRunEmail", KEY_SHOULD_VERIFY_EMAIL: "shouldVerifyEmail", + KEY_EMAIL_VERIFY_PENDING: "emailVerifyPending", SETTING_ALPHA_UNDERSTANDS_RISKS: "alphaUnderstandRisks", diff --git a/app/src/page/discover/view.js b/app/src/page/discover/view.js index a99277da..30691873 100644 --- a/app/src/page/discover/view.js +++ b/app/src/page/discover/view.js @@ -117,8 +117,8 @@ class DiscoverPage extends React.PureComponent { Fetching content... )} - {hasContent && - ( ({ title: category, data: featuredUris[category] }))} keyExtractor={(item, index) => item} - /> + />) } diff --git a/app/src/page/firstRun/index.js b/app/src/page/firstRun/index.js index c196505e..699d0142 100644 --- a/app/src/page/firstRun/index.js +++ b/app/src/page/firstRun/index.js @@ -1,18 +1,18 @@ import { connect } from 'react-redux'; import { doToast } from 'lbry-redux'; import { - doGenerateAuthToken, + doAuthenticate, doUserEmailNew, selectAuthToken, selectEmailNewErrorMessage, selectEmailNewIsPending, selectEmailToVerify, - selectIsAuthenticating + selectAuthenticationIsPending } from 'lbryinc'; import FirstRun from './view'; const select = (state) => ({ - authenticating: selectIsAuthenticating(state), + authenticating: selectAuthenticationIsPending(state), authToken: selectAuthToken(state), emailToVerify: selectEmailToVerify(state), emailNewErrorMessage: selectEmailNewErrorMessage(state), @@ -21,7 +21,7 @@ const select = (state) => ({ const perform = dispatch => ({ addUserEmail: email => dispatch(doUserEmailNew(email)), - generateAuthToken: installationId => dispatch(doGenerateAuthToken(installationId)), + authenticate: (appVersion, os) => dispatch(doAuthenticate(appVersion, os)), notify: data => dispatch(doToast(data)) }); diff --git a/app/src/page/firstRun/internal/email-collect-page.js b/app/src/page/firstRun/internal/email-collect-page.js index 3b887244..aa69ac87 100644 --- a/app/src/page/firstRun/internal/email-collect-page.js +++ b/app/src/page/firstRun/internal/email-collect-page.js @@ -4,6 +4,8 @@ import { ActivityIndicator, AsyncStorage, Linking, + NativeModules, + Platform, Text, TextInput, View @@ -46,19 +48,21 @@ class EmailCollectPage extends React.PureComponent { } startAuthenticating = () => { - const { generateAuthToken } = this.props; + const { authenticate } = this.props; this.setState({ authenticationStarted: true, authenticationFailed: false }); - Lbry.status().then(info => { - generateAuthToken(info.installation_id) - }).catch(error => { - if (this.state.statusTries >= EmailCollectPage.MAX_STATUS_TRIES) { - this.setState({ authenticationFailed: true }); - } else { - setTimeout(() => { - this.startAuthenticating(); - this.setState({ statusTries: this.state.statusTries + 1 }); - }, 1000); // Retry every second for a maximum of MAX_STATUS_TRIES tries (30 seconds) - } + NativeModules.VersionInfo.getAppVersion().then(appVersion => { + Lbry.status().then(info => { + authenticate(appVersion, Platform.OS) + }).catch(error => { + if (this.state.statusTries >= EmailCollectPage.MAX_STATUS_TRIES) { + this.setState({ authenticationFailed: true }); + } else { + setTimeout(() => { + this.startAuthenticating(); + this.setState({ statusTries: this.state.statusTries + 1 }); + }, 1000); // Retry every second for a maximum of MAX_STATUS_TRIES tries (30 seconds) + } + }); }); } @@ -70,6 +74,7 @@ class EmailCollectPage extends React.PureComponent { onEmailChanged(text); } AsyncStorage.setItem(Constants.KEY_FIRST_RUN_EMAIL, text); + AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true'); } render() { diff --git a/app/src/page/firstRun/view.js b/app/src/page/firstRun/view.js index 7fba3ad7..bfc96aa6 100644 --- a/app/src/page/firstRun/view.js +++ b/app/src/page/firstRun/view.js @@ -160,9 +160,9 @@ class FirstRunScreen extends React.PureComponent { render() { const { + authenticate, authenticating, authToken, - generateAuthToken, emailNewErrorMessage, emailNewPending, emailToVerify @@ -175,7 +175,7 @@ class FirstRunScreen extends React.PureComponent { } else if (this.state.currentPage === 'email-collect') { page = (); }