Page MenuHomePhabricator

D8154.diff
No OneTemporary

D8154.diff

diff --git a/native/account/registration/avatar-selection.react.js b/native/account/registration/avatar-selection.react.js
--- a/native/account/registration/avatar-selection.react.js
+++ b/native/account/registration/avatar-selection.react.js
@@ -10,10 +10,11 @@
import RegistrationContentContainer from './registration-content-container.react.js';
import { RegistrationContext } from './registration-context.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
-import type {
- CoolOrNerdMode,
- AccountSelection,
- AvatarData,
+import {
+ type CoolOrNerdMode,
+ type AccountSelection,
+ type AvatarData,
+ ensAvatarSelection,
} from './registration-types.js';
import {
EditUserAvatarContext,
@@ -31,12 +32,6 @@
},
};
-const ensDefaultSelection = {
- needsUpload: false,
- updateUserAvatarRequest: { type: 'ens' },
- clientAvatar: { type: 'ens' },
-};
-
type Props = {
+navigation: RegistrationNavigationProp<'AvatarSelection'>,
+route: NavigationRoute<'AvatarSelection'>,
@@ -44,11 +39,16 @@
function AvatarSelection(props: Props): React.Node {
const { userSelections } = props.route.params;
const { accountSelection } = userSelections;
- const username =
+ const usernameOrETHAddress =
accountSelection.accountType === 'username'
? accountSelection.username
: accountSelection.address;
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { cachedSelections, setCachedSelections, register } =
+ registrationContext;
+
const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext should be set');
const { setRegistrationMode } = editUserAvatarContext;
@@ -58,35 +58,53 @@
? accountSelection.avatarURI
: undefined;
- const [avatarData, setAvatarData] = React.useState<?AvatarData>(
- prefetchedAvatarURI ? ensDefaultSelection : undefined,
- );
+ let initialAvatarData = cachedSelections.avatarData;
+ if (!initialAvatarData && prefetchedAvatarURI) {
+ initialAvatarData = ensAvatarSelection;
+ }
+
+ const [avatarData, setAvatarData] =
+ React.useState<?AvatarData>(initialAvatarData);
const setClientAvatarFromSelection = React.useCallback(
(selection: UserAvatarSelection) => {
if (selection.needsUpload) {
- setAvatarData({
+ const newAvatarData = {
...selection,
clientAvatar: {
type: 'image',
uri: selection.mediaSelection.uri,
},
- });
+ };
+ setAvatarData(newAvatarData);
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ avatarData: newAvatarData,
+ }));
} else if (selection.updateUserAvatarRequest.type !== 'remove') {
const clientRequest = selection.updateUserAvatarRequest;
invariant(
clientRequest.type !== 'image',
'image avatars need to be uploaded',
);
- setAvatarData({
+ const newAvatarData = {
...selection,
clientAvatar: clientRequest,
- });
+ };
+ setAvatarData(newAvatarData);
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ avatarData: newAvatarData,
+ }));
} else {
setAvatarData(undefined);
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ avatarData: undefined,
+ }));
}
},
- [],
+ [setCachedSelections],
);
const [registrationInProgress, setRegistrationInProgress] =
@@ -109,10 +127,6 @@
setClientAvatarFromSelection,
]);
- const registrationContext = React.useContext(RegistrationContext);
- invariant(registrationContext, 'registrationContext should be set');
- const { register } = registrationContext;
-
const onProceed = React.useCallback(async () => {
setRegistrationInProgress(true);
try {
@@ -128,10 +142,10 @@
const clientAvatar = avatarData?.clientAvatar;
const userInfoOverride = React.useMemo(
() => ({
- username,
+ username: usernameOrETHAddress,
avatar: clientAvatar,
}),
- [username, clientAvatar],
+ [usernameOrETHAddress, clientAvatar],
);
const styles = useStyles(unboundStyles);
diff --git a/native/account/registration/connect-ethereum.react.js b/native/account/registration/connect-ethereum.react.js
--- a/native/account/registration/connect-ethereum.react.js
+++ b/native/account/registration/connect-ethereum.react.js
@@ -1,5 +1,6 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import { Text, View } from 'react-native';
@@ -19,8 +20,12 @@
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
+import { RegistrationContext } from './registration-context.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
-import type { CoolOrNerdMode } from './registration-types.js';
+import {
+ type CoolOrNerdMode,
+ ensAvatarSelection,
+} from './registration-types.js';
import {
type NavigationRoute,
ExistingEthereumAccountRouteName,
@@ -52,6 +57,11 @@
function ConnectEthereum(props: Props): React.Node {
const { params } = props.route;
const { userSelections } = props.route.params;
+
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { setCachedSelections } = registrationContext;
+
const isNerdMode = userSelections.coolOrNerdMode === 'nerd';
const styles = useStyles(unboundStyles);
@@ -157,13 +167,29 @@
const avatarURI = await avatarURIPromise;
+ const ethereumAccount = {
+ accountType: 'ethereum',
+ ...result,
+ avatarURI,
+ };
+
+ setCachedSelections(oldUserSelections => {
+ const base = {
+ ...oldUserSelections,
+ ethereumAccount,
+ };
+ if (base.avatarData || !avatarURI) {
+ return base;
+ }
+ return {
+ ...base,
+ avatarData: ensAvatarSelection,
+ };
+ });
+
const newUserSelections = {
...userSelections,
- accountSelection: {
- accountType: 'ethereum',
- ...result,
- avatarURI,
- },
+ accountSelection: ethereumAccount,
};
navigate<'AvatarSelection'>({
name: AvatarSelectionRouteName,
@@ -174,6 +200,7 @@
userSelections,
exactSearchUserCall,
dispatchActionPromise,
+ setCachedSelections,
navigate,
ensCache,
],
diff --git a/native/account/registration/cool-or-nerd-mode-selection.react.js b/native/account/registration/cool-or-nerd-mode-selection.react.js
--- a/native/account/registration/cool-or-nerd-mode-selection.react.js
+++ b/native/account/registration/cool-or-nerd-mode-selection.react.js
@@ -8,6 +8,7 @@
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
+import { RegistrationContext } from './registration-context.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import {
RegistrationTile,
@@ -25,14 +26,27 @@
+route: NavigationRoute<'CoolOrNerdModeSelection'>,
};
function CoolOrNerdModeSelection(props: Props): React.Node {
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { cachedSelections, setCachedSelections } = registrationContext;
+
const [currentSelection, setCurrentSelection] =
- React.useState<?CoolOrNerdMode>();
+ React.useState<?CoolOrNerdMode>(cachedSelections.coolOrNerdMode);
+
const selectCool = React.useCallback(() => {
setCurrentSelection('cool');
- }, []);
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ coolOrNerdMode: 'cool',
+ }));
+ }, [setCachedSelections]);
const selectNerd = React.useCallback(() => {
setCurrentSelection('nerd');
- }, []);
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ coolOrNerdMode: 'nerd',
+ }));
+ }, [setCachedSelections]);
const { navigate } = props.navigation;
const onSubmit = React.useCallback(() => {
diff --git a/native/account/registration/keyserver-selection.react.js b/native/account/registration/keyserver-selection.react.js
--- a/native/account/registration/keyserver-selection.react.js
+++ b/native/account/registration/keyserver-selection.react.js
@@ -1,5 +1,6 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import { Text } from 'react-native';
@@ -7,6 +8,7 @@
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
+import { RegistrationContext } from './registration-context.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import RegistrationTextInput from './registration-text-input.react.js';
import {
@@ -33,12 +35,26 @@
+navigation: RegistrationNavigationProp<'KeyserverSelection'>,
+route: NavigationRoute<'KeyserverSelection'>,
};
-// eslint-disable-next-line no-unused-vars
function KeyserverSelection(props: Props): React.Node {
- const [customKeyserver, setCustomKeyserver] = React.useState('');
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { cachedSelections, setCachedSelections } = registrationContext;
+
+ const initialKeyserverUsername = cachedSelections.keyserverUsername;
+ const [customKeyserver, setCustomKeyserver] = React.useState(
+ initialKeyserverUsername === 'ashoat' ? '' : initialKeyserverUsername,
+ );
const customKeyserverTextInputRef = React.useRef();
- const [currentSelection, setCurrentSelection] = React.useState<?Selection>();
+ let initialSelection;
+ if (initialKeyserverUsername === 'ashoat') {
+ initialSelection = 'ashoat';
+ } else if (initialKeyserverUsername) {
+ initialSelection = 'custom';
+ }
+
+ const [currentSelection, setCurrentSelection] =
+ React.useState<?Selection>(initialSelection);
const selectAshoat = React.useCallback(() => {
setCurrentSelection('ashoat');
customKeyserverTextInputRef.current?.blur();
@@ -69,11 +85,15 @@
if (!keyserverUsername) {
return;
}
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ keyserverUsername,
+ }));
navigate<'ConnectEthereum'>({
name: ConnectEthereumRouteName,
params: { userSelections: { coolOrNerdMode, keyserverUsername } },
});
- }, [navigate, coolOrNerdMode, keyserverUsername]);
+ }, [navigate, coolOrNerdMode, keyserverUsername, setCachedSelections]);
const styles = useStyles(unboundStyles);
const colors = useColors();
diff --git a/native/account/registration/password-selection.react.js b/native/account/registration/password-selection.react.js
--- a/native/account/registration/password-selection.react.js
+++ b/native/account/registration/password-selection.react.js
@@ -1,5 +1,6 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import { View, Text, Platform } from 'react-native';
@@ -9,6 +10,7 @@
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
+import { RegistrationContext } from './registration-context.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import RegistrationTextInput from './registration-text-input.react.js';
import type { CoolOrNerdMode } from './registration-types.js';
@@ -34,8 +36,16 @@
+route: NavigationRoute<'PasswordSelection'>,
};
function PasswordSelection(props: Props): React.Node {
- const [password, setPassword] = React.useState('');
- const [confirmPassword, setConfirmPassword] = React.useState('');
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { cachedSelections, setCachedSelections } = registrationContext;
+
+ const [password, setPassword] = React.useState(
+ cachedSelections.password ?? '',
+ );
+ const [confirmPassword, setConfirmPassword] = React.useState(
+ cachedSelections.password ?? '',
+ );
const passwordsMatch = password === confirmPassword;
const passwordIsEmpty = password === '';
@@ -76,11 +86,21 @@
password,
},
};
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ password,
+ }));
navigate<'AvatarSelection'>({
name: AvatarSelectionRouteName,
params: { userSelections: newUserSelections },
});
- }, [checkPasswordValidity, userSelections, password, navigate]);
+ }, [
+ checkPasswordValidity,
+ userSelections,
+ password,
+ setCachedSelections,
+ navigate,
+ ]);
const styles = useStyles(unboundStyles);
let errorText;
@@ -142,6 +162,8 @@
[passwordLength, confirmPasswordEmpty],
);
+ const shouldAutoFocus = React.useRef(!cachedSelections.password);
+
/* eslint-disable react-hooks/rules-of-hooks */
if (Platform.OS === 'android') {
// It's okay to call this hook conditionally because
@@ -149,12 +171,16 @@
React.useEffect(() => {
(async () => {
await sleep(250);
- passwordInputRef.current?.focus();
+ if (shouldAutoFocus.current) {
+ passwordInputRef.current?.focus();
+ }
})();
}, []);
}
/* eslint-enable react-hooks/rules-of-hooks */
+ const autoFocus = Platform.OS !== 'android' && shouldAutoFocus.current;
+
return (
<RegistrationContainer>
<RegistrationContentContainer>
@@ -163,10 +189,7 @@
value={password}
onChangeText={onChangePasswordInput}
placeholder="Password"
- autoFocus={Platform.select({
- android: false,
- default: true,
- })}
+ autoFocus={autoFocus}
secureTextEntry={true}
textContentType="newPassword"
autoComplete="password-new"
diff --git a/native/account/registration/registration-context-provider.react.js b/native/account/registration/registration-context-provider.react.js
--- a/native/account/registration/registration-context-provider.react.js
+++ b/native/account/registration/registration-context-provider.react.js
@@ -4,17 +4,25 @@
import { RegistrationContext } from './registration-context.js';
import { useRegistrationServerCall } from './registration-server-call.js';
+import type { CachedUserSelections } from './registration-types.js';
+
+const emptyObj: CachedUserSelections = Object.freeze({});
type Props = {
+children: React.Node,
};
function RegistrationContextProvider(props: Props): React.Node {
+ const [cachedSelections, setCachedSelections] =
+ React.useState<CachedUserSelections>(emptyObj);
+
const registrationServerCall = useRegistrationServerCall();
const contextValue = React.useMemo(
() => ({
register: registrationServerCall,
+ cachedSelections,
+ setCachedSelections,
}),
- [registrationServerCall],
+ [registrationServerCall, cachedSelections],
);
return (
diff --git a/native/account/registration/registration-context.js b/native/account/registration/registration-context.js
--- a/native/account/registration/registration-context.js
+++ b/native/account/registration/registration-context.js
@@ -2,10 +2,17 @@
import * as React from 'react';
-import type { RegistrationServerCallInput } from './registration-types.js';
+import type { SetState } from 'lib/types/hook-types.js';
+
+import type {
+ RegistrationServerCallInput,
+ CachedUserSelections,
+} from './registration-types.js';
export type RegistrationContextType = {
+register: RegistrationServerCallInput => Promise<void>,
+ +cachedSelections: CachedUserSelections,
+ +setCachedSelections: SetState<CachedUserSelections>,
};
const RegistrationContext: React.Context<?RegistrationContextType> =
diff --git a/native/account/registration/registration-types.js b/native/account/registration/registration-types.js
--- a/native/account/registration/registration-types.js
+++ b/native/account/registration/registration-types.js
@@ -43,3 +43,18 @@
+accountSelection: AccountSelection,
+avatarData: ?AvatarData,
};
+
+export type CachedUserSelections = {
+ +coolOrNerdMode?: CoolOrNerdMode,
+ +keyserverUsername?: string,
+ +username?: string,
+ +password?: string,
+ +avatarData?: ?AvatarData,
+ +ethereumAccount?: EthereumAccountSelection,
+};
+
+export const ensAvatarSelection: AvatarData = {
+ needsUpload: false,
+ updateUserAvatarRequest: { type: 'ens' },
+ clientAvatar: { type: 'ens' },
+};
diff --git a/native/account/registration/username-selection.react.js b/native/account/registration/username-selection.react.js
--- a/native/account/registration/username-selection.react.js
+++ b/native/account/registration/username-selection.react.js
@@ -1,5 +1,6 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import { View, Text } from 'react-native';
@@ -18,6 +19,7 @@
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
+import { RegistrationContext } from './registration-context.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import RegistrationTextInput from './registration-text-input.react.js';
import type { CoolOrNerdMode } from './registration-types.js';
@@ -46,7 +48,13 @@
+route: NavigationRoute<'UsernameSelection'>,
};
function UsernameSelection(props: Props): React.Node {
- const [username, setUsername] = React.useState('');
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { cachedSelections, setCachedSelections } = registrationContext;
+
+ const [username, setUsername] = React.useState(
+ cachedSelections.username ?? '',
+ );
const validUsername = username.search(validUsernameRegex) > -1;
const [usernameError, setUsernameError] = React.useState<?UsernameError>();
@@ -78,6 +86,10 @@
}
setUsernameError(undefined);
+ setCachedSelections(oldUserSelections => ({
+ ...oldUserSelections,
+ username,
+ }));
navigate<'PasswordSelection'>({
name: PasswordSelectionRouteName,
params: {
@@ -92,6 +104,7 @@
username,
exactSearchUserCall,
dispatchActionPromise,
+ setCachedSelections,
navigate,
userSelections,
]);
@@ -140,6 +153,7 @@
);
}
+ const shouldAutoFocus = React.useRef(!cachedSelections.username);
return (
<RegistrationContainer>
<RegistrationContentContainer>
@@ -148,7 +162,7 @@
value={username}
onChangeText={setUsername}
placeholder="Username"
- autoFocus={true}
+ autoFocus={shouldAutoFocus.current}
autoCorrect={false}
autoCapitalize="none"
keyboardType="ascii-capable"

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 12:04 PM (20 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2588187
Default Alt Text
D8154.diff (19 KB)

Event Timeline