Password flow #88

Merged
akinwale merged 2 commits from password-flow into master 2019-12-03 15:02:34 +01:00
5 changed files with 77 additions and 12 deletions

View file

@ -3,7 +3,7 @@ import { doSetClientSetting } from 'redux/actions/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doToast } from 'lbry-redux'; import { doToast } from 'lbry-redux';
import { selectUserEmail } from 'lbryinc'; import { selectUserEmail } from 'lbryinc';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import WalletSyncDriver from './view'; import WalletSyncDriver from './view';
const select = state => ({ const select = state => ({

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { Alert, NativeModules, Switch, Text, View } from 'react-native'; import { Alert, NativeModules, Switch, Text, View } from 'react-native';
import Button from 'component/button'; import Button from 'component/button';
import Constants from 'constants'; import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
import Link from 'component/link'; import Link from 'component/link';
import walletStyle from 'styles/wallet'; import walletStyle from 'styles/wallet';
@ -43,7 +43,7 @@ class WalletSyncDriver extends React.PureComponent<Props> {
<Text style={walletStyle.labelText}>Sync status</Text> <Text style={walletStyle.labelText}>Sync status</Text>
</View> </View>
<View style={walletStyle.tableColRow}> <View style={walletStyle.tableColRow}>
<Text selectable={true} style={walletStyle.valueText}> <Text selectable style={walletStyle.valueText}>
{deviceWalletSynced ? 'On' : 'Off'} {deviceWalletSynced ? 'On' : 'Off'}
</Text> </Text>
<Switch <Switch
@ -59,8 +59,8 @@ class WalletSyncDriver extends React.PureComponent<Props> {
<Text style={walletStyle.labelText}>Connected email</Text> <Text style={walletStyle.labelText}>Connected email</Text>
</View> </View>
<View style={walletStyle.tableCol}> <View style={walletStyle.tableCol}>
<Text selectable={true} style={walletStyle.valueText}> <Text selectable style={walletStyle.valueText} numberOfLines={1}>
{userEmail ? userEmail : 'No connected email'} {userEmail || 'No connected email'}
</Text> </Text>
</View> </View>
</View> </View>

View file

@ -28,12 +28,32 @@ class WalletPage extends React.PureComponent {
walletReady: false, walletReady: false,
hasCheckedSync: false, hasCheckedSync: false,
revealPassword: false, revealPassword: false,
autoPassword: false,
autoLoginAttempted: false,
}; };
componentDidMount() { componentDidMount() {
this.checkWalletReady(); this.checkWalletReady();
} }
componentDidUpdate() {
const { hasSyncedWallet, getSyncIsPending, onPasswordChanged, autoLogin } = this.props;
if (this.state.walletReady && this.state.hasCheckedSync && !getSyncIsPending) {
if (!hasSyncedWallet && !this.state.autoPassword) {
// new account, in which case, don't ask for a password, and act as the final first run step
this.setState({ password: '', autoPassword: true });
if (onPasswordChanged) {
onPasswordChanged('', true);
}
}
if (hasSyncedWallet && !this.state.autoLoginAttempted && autoLogin) {
autoLogin();
this.setState({ autoLoginAttempted: true });
}
}
}
checkWalletReady = () => { checkWalletReady = () => {
// make sure the sdk wallet component is ready // make sure the sdk wallet component is ready
Lbry.status() Lbry.status()
@ -69,6 +89,7 @@ class WalletPage extends React.PureComponent {
hasSyncedWallet, hasSyncedWallet,
syncApplyIsPending, syncApplyIsPending,
syncApplyStarted, syncApplyStarted,
syncApplyCompleted,
} = this.props; } = this.props;
let content; let content;
@ -79,14 +100,15 @@ class WalletPage extends React.PureComponent {
<Text style={firstRunStyle.paragraph}>Retrieving your account information...</Text> <Text style={firstRunStyle.paragraph}>Retrieving your account information...</Text>
</View> </View>
); );
} else if (syncApplyStarted || syncApplyIsPending) { } else if (syncApplyStarted || syncApplyIsPending || syncApplyCompleted) {
content = ( content = (
<View style={firstRunStyle.centered}> <View style={firstRunStyle.centered}>
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} /> <ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
<Text style={firstRunStyle.paragraph}>{syncApplyIsPending ? 'Validating password' : 'Synchronizing'}...</Text> <Text style={firstRunStyle.paragraph}>{syncApplyIsPending ? 'Validating password' : 'Synchronizing'}...</Text>
</View> </View>
); );
} else { } else if (hasSyncedWallet && this.state.autoLoginAttempted) {
// only display this view if it's not a new user (or auto-login has been attempted once)
content = ( content = (
<View onLayout={onWalletViewLayout}> <View onLayout={onWalletViewLayout}>
<Text style={firstRunStyle.title}>Password</Text> <Text style={firstRunStyle.title}>Password</Text>

View file

@ -35,6 +35,7 @@ class FirstRunScreen extends React.PureComponent {
showBottomContainer: false, showBottomContainer: false,
walletPassword: '', walletPassword: '',
syncApplyStarted: false, syncApplyStarted: false,
syncApplyCompleted: false,
}; };
componentDidMount() { componentDidMount() {
@ -78,8 +79,9 @@ class FirstRunScreen extends React.PureComponent {
if (this.state.syncApplyStarted && !syncApplyIsPending) { if (this.state.syncApplyStarted && !syncApplyIsPending) {
if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) { if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) {
notify({ message: syncApplyErrorMessage, isError: true }); notify({ message: syncApplyErrorMessage, isError: true });
this.setState({ showBottomContainer: true, syncApplyStarted: false }); this.setState({ showBottomContainer: true, syncApplyStarted: false, syncApplyCompleted: false });
} else { } else {
this.setState({ syncApplyCompleted: true });
// password successfully verified // password successfully verified
NativeModules.UtilityModule.setSecureValue( NativeModules.UtilityModule.setSecureValue(
Constants.KEY_WALLET_PASSWORD, Constants.KEY_WALLET_PASSWORD,
@ -160,6 +162,13 @@ class FirstRunScreen extends React.PureComponent {
}); });
}; };
autoLogin = () => {
const { hasSyncedWallet } = this.props;
if (hasSyncedWallet && !this.state.syncApplyStarted) {
this.checkWalletPassword();
}
};
handleContinuePressed = () => { handleContinuePressed = () => {
const { notify, user, hasSyncedWallet } = this.props; const { notify, user, hasSyncedWallet } = this.props;
const pageIndex = FirstRunScreen.pages.indexOf(this.state.currentPage); const pageIndex = FirstRunScreen.pages.indexOf(this.state.currentPage);
@ -265,8 +274,12 @@ class FirstRunScreen extends React.PureComponent {
this.setState({ showBottomContainer: true, showSkip: true }); this.setState({ showBottomContainer: true, showSkip: true });
}; };
onWalletPasswordChanged = password => { onWalletPasswordChanged = (password, finalStep) => {
this.setState({ walletPassword: password !== null ? password : '' }); this.setState({ walletPassword: password !== null ? password : '' });
if (finalStep) {
// final step for a new user
this.setFreshPassword();
}
}; };
onWalletViewLayout = () => { onWalletViewLayout = () => {
@ -372,8 +385,10 @@ class FirstRunScreen extends React.PureComponent {
getSyncIsPending={getSyncIsPending} getSyncIsPending={getSyncIsPending}
syncApplyIsPending={syncApplyIsPending} syncApplyIsPending={syncApplyIsPending}
syncApplyStarted={this.state.syncApplyStarted} syncApplyStarted={this.state.syncApplyStarted}
syncApplyCompleted={this.state.syncApplyCompleted}
onWalletViewLayout={this.onWalletViewLayout} onWalletViewLayout={this.onWalletViewLayout}
onPasswordChanged={this.onWalletPasswordChanged} onPasswordChanged={this.onWalletPasswordChanged}
autoLogin={this.autoLogin}
/> />
); );
break; break;

View file

@ -16,8 +16,12 @@ class SyncVerifyPage extends React.PureComponent {
password: null, password: null,
placeholder: 'password', placeholder: 'password',
syncApplyStarted: false, syncApplyStarted: false,
syncApplyCompleted: false,
syncChecked: false, syncChecked: false,
revealPassword: false, revealPassword: false,
autoPassword: false,
autoLoginAttempted: false,
autoLoginFlow: true,
}; };
componentDidMount() { componentDidMount() {
@ -64,9 +68,11 @@ class SyncVerifyPage extends React.PureComponent {
if (this.state.syncApplyStarted && !syncApplyIsPending) { if (this.state.syncApplyStarted && !syncApplyIsPending) {
if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) { if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) {
notify({ message: syncApplyErrorMessage, isError: true }); notify({ message: syncApplyErrorMessage, isError: true });
this.setState({ syncApplyStarted: false }); this.setState({ syncApplyStarted: false, autoLoginFlow: false });
} else { } else {
// password successfully verified // password successfully verified
this.setState({ syncApplyCompleted: true });
if (NativeModules.UtilityModule) { if (NativeModules.UtilityModule) {
NativeModules.UtilityModule.setSecureValue( NativeModules.UtilityModule.setSecureValue(
Constants.KEY_WALLET_PASSWORD, Constants.KEY_WALLET_PASSWORD,
@ -79,6 +85,19 @@ class SyncVerifyPage extends React.PureComponent {
} }
} }
componentDidUpdate() {
const { hasSyncedWallet } = this.props;
if (this.state.syncChecked && !this.state.autoPassword && !hasSyncedWallet) {
// new user sync, don't prompt for a password
this.setState({ password: '', autoPassword: true });
this.onEnableSyncPressed();
}
if (this.state.syncChecked && hasSyncedWallet && !this.state.autoLoginAttempted) {
this.setState({ autoLoginAttempted: true, password: '' }, () => this.onEnableSyncPressed());
}
}
finishSync = (notifyUnlockFailed = false) => { finishSync = (notifyUnlockFailed = false) => {
const { navigation, notify, setClientSetting } = this.props; const { navigation, notify, setClientSetting } = this.props;
@ -133,7 +152,16 @@ class SyncVerifyPage extends React.PureComponent {
<Text style={firstRunStyle.paragraph}>Retrieving your account information...</Text> <Text style={firstRunStyle.paragraph}>Retrieving your account information...</Text>
</View> </View>
); );
} else { } else if (this.state.autoLoginFlow && (syncApplyIsPending || this.state.syncApplyCompleted)) {
// first attempt at auto-login, only display activity indicator
content = (
<View>
<View style={firstRunStyle.centerInside}>
<ActivityIndicator size={'small'} color={Colors.White} />
</View>
</View>
);
} else if (hasSyncedWallet && this.state.autoLoginAttempted) {
content = ( content = (
<View> <View>
<Text style={rewardStyle.verificationTitle}>Wallet Sync</Text> <Text style={rewardStyle.verificationTitle}>Wallet Sync</Text>
@ -198,7 +226,7 @@ class SyncVerifyPage extends React.PureComponent {
onPress={this.onEnableSyncPressed} onPress={this.onEnableSyncPressed}
/> />
)} )}
{syncApplyIsPending && ( {(syncApplyIsPending || this.state.syncApplyCompleted) && (
<View style={firstRunStyle.centerInside}> <View style={firstRunStyle.centerInside}>
<ActivityIndicator size={'small'} color={Colors.White} /> <ActivityIndicator size={'small'} color={Colors.White} />
</View> </View>