handle new email verification links (#426)
* handle new email verification links * some updates to work with new auth flow
This commit is contained in:
parent
c8de700460
commit
9638ad4f06
10 changed files with 78 additions and 32 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -22,12 +22,12 @@ class SuggestedSubscriptions extends React.PureComponent {
|
|||
|
||||
return suggested ? (
|
||||
<SectionList style={subscriptionsStyle.scrollContainer}
|
||||
renderItem={ ({item, index, section}) => { console.log(item); return (
|
||||
renderItem={ ({item, index, section}) => (
|
||||
<SuggestedSubscriptionItem
|
||||
key={item}
|
||||
categoryLink={normalizeURI(item)}
|
||||
navigation={navigation} />
|
||||
); }
|
||||
)
|
||||
}
|
||||
renderSectionHeader={
|
||||
({section: {title}}) => {
|
||||
|
|
|
@ -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",
|
||||
|
||||
|
|
|
@ -117,8 +117,8 @@ class DiscoverPage extends React.PureComponent {
|
|||
<Text style={discoverStyle.title}>Fetching content...</Text>
|
||||
</View>
|
||||
)}
|
||||
{hasContent &&
|
||||
<SectionList style={discoverStyle.scrollContainer}
|
||||
{(!!hasContent) &&
|
||||
(<SectionList style={discoverStyle.scrollContainer}
|
||||
renderItem={ ({item, index, section}) => (
|
||||
<FileItem
|
||||
style={discoverStyle.fileItem}
|
||||
|
@ -135,7 +135,7 @@ class DiscoverPage extends React.PureComponent {
|
|||
}
|
||||
sections={Object.keys(featuredUris).map(category => ({ title: category, data: featuredUris[category] }))}
|
||||
keyExtractor={(item, index) => item}
|
||||
/>
|
||||
/>)
|
||||
}
|
||||
<FloatingWalletBalance navigation={navigation} />
|
||||
<UriBar navigation={navigation} />
|
||||
|
|
|
@ -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))
|
||||
});
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 = (<EmailCollectPage authenticating={authenticating}
|
||||
authToken={authToken}
|
||||
generateAuthToken={generateAuthToken}
|
||||
authenticate={authenticate}
|
||||
onEmailChanged={this.onEmailChanged}
|
||||
onEmailViewLayout={this.onEmailViewLayout} />);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue