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
@@ -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 type {
CoolOrNerdMode,
@@ -88,7 +89,13 @@
[],
);
+ const [registrationInProgress, setRegistrationInProgress] =
+ React.useState(false);
+
React.useEffect(() => {
+ if (registrationInProgress) {
+ return undefined;
+ }
setRegistrationMode({
registrationMode: 'on',
successCallback: setClientAvatarFromSelection,
@@ -96,9 +103,27 @@
return () => {
setRegistrationMode({ registrationMode: 'off' });
};
- }, [setRegistrationMode, setClientAvatarFromSelection]);
+ }, [
+ registrationInProgress,
+ setRegistrationMode,
+ setClientAvatarFromSelection,
+ ]);
+
+ const registrationContext = React.useContext(RegistrationContext);
+ invariant(registrationContext, 'registrationContext should be set');
+ const { register } = registrationContext;
- const onProceed = React.useCallback(() => {}, []);
+ const onProceed = React.useCallback(async () => {
+ setRegistrationInProgress(true);
+ try {
+ await register({
+ ...userSelections,
+ avatarData,
+ });
+ } finally {
+ setRegistrationInProgress(false);
+ }
+ }, [register, userSelections, avatarData]);
const clientAvatar = avatarData?.clientAvatar;
const userInfoOverride = React.useMemo(
@@ -118,7 +143,7 @@
@@ -128,7 +153,7 @@
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
@@ -3,12 +3,20 @@
import * as React from 'react';
import { RegistrationContext } from './registration-context.js';
+import { useRegistrationServerCall } from './registration-server-call.js';
type Props = {
+children: React.Node,
};
function RegistrationContextProvider(props: Props): React.Node {
- const contextValue = React.useMemo(() => ({}), []);
+ const registrationServerCall = useRegistrationServerCall();
+ const contextValue = React.useMemo(
+ () => ({
+ register: registrationServerCall,
+ }),
+ [registrationServerCall],
+ );
+
return (
{props.children}
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,7 +2,11 @@
import * as React from 'react';
-export type RegistrationContextType = {};
+import type { RegistrationServerCallInput } from './registration-types.js';
+
+export type RegistrationContextType = {
+ +register: RegistrationServerCallInput => Promise,
+};
const RegistrationContext: React.Context =
React.createContext();
diff --git a/native/account/registration/registration-server-call.js b/native/account/registration/registration-server-call.js
new file mode 100644
--- /dev/null
+++ b/native/account/registration/registration-server-call.js
@@ -0,0 +1,126 @@
+// @flow
+
+import * as React from 'react';
+import { Alert, Platform } from 'react-native';
+import { useDispatch } from 'react-redux';
+
+import { setDataLoadedActionType } from 'lib/actions/client-db-store-actions.js';
+import { registerActionTypes, register } from 'lib/actions/user-actions.js';
+import type { LogInStartingPayload } from 'lib/types/account-types.js';
+import {
+ useServerCall,
+ useDispatchActionPromise,
+} from 'lib/utils/action-utils.js';
+
+import type {
+ RegistrationServerCallInput,
+ UsernameAccountSelection,
+ EthereumAccountSelection,
+} from './registration-types.js';
+import { NavContext } from '../../navigation/navigation-context.js';
+import { useSelector } from '../../redux/redux-utils.js';
+import { nativeLogInExtraInfoSelector } from '../../selectors/account-selectors.js';
+import { setNativeCredentials } from '../native-credentials.js';
+import { useSIWEServerCall } from '../siwe-hooks.js';
+
+function useRegistrationServerCall(): RegistrationServerCallInput => Promise {
+ const navContext = React.useContext(NavContext);
+ const logInExtraInfo = useSelector(state =>
+ nativeLogInExtraInfoSelector({
+ redux: state,
+ navContext,
+ }),
+ );
+
+ const dispatchActionPromise = useDispatchActionPromise();
+ const callRegister = useServerCall(register);
+
+ const registerUsernameAccount = React.useCallback(
+ async (accountSelection: UsernameAccountSelection) => {
+ const extraInfo = await logInExtraInfo();
+ const registerPromise = (async () => {
+ try {
+ const result = await callRegister({
+ ...extraInfo,
+ username: accountSelection.username,
+ password: accountSelection.password,
+ });
+ await setNativeCredentials({
+ username: result.currentUserInfo.username,
+ password: accountSelection.password,
+ });
+ return result;
+ } catch (e) {
+ if (e.message === 'username_reserved') {
+ Alert.alert(
+ 'Username reserved',
+ 'This username is currently reserved. Please contact support@' +
+ 'comm.app if you would like to claim this account.',
+ );
+ } else if (e.message === 'username_taken') {
+ Alert.alert(
+ 'Username taken',
+ 'An account with that username already exists',
+ );
+ } else if (e.message === 'client_version_unsupported') {
+ const app = Platform.select({
+ ios: 'App Store',
+ android: 'Play Store',
+ });
+ Alert.alert(
+ 'App out of date',
+ 'Your app version is pretty old, and the server doesn’t know how ' +
+ `to speak to it anymore. Please use the ${app} app to update!`,
+ );
+ } else {
+ Alert.alert('Unknown error', 'Uhh... try again?');
+ }
+ throw e;
+ }
+ })();
+ dispatchActionPromise(
+ registerActionTypes,
+ registerPromise,
+ undefined,
+ ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload),
+ );
+ await registerPromise;
+ },
+ [logInExtraInfo, callRegister, dispatchActionPromise],
+ );
+
+ const siweServerCallParams = React.useMemo(() => {
+ const onServerCallFailure = () => {
+ Alert.alert('Unknown error', 'Uhh... try again?');
+ };
+ return { onFailure: onServerCallFailure };
+ }, []);
+ const siweServerCall = useSIWEServerCall(siweServerCallParams);
+
+ const registerEthereumAccount = React.useCallback(
+ (accountSelection: EthereumAccountSelection) => {
+ return siweServerCall(accountSelection);
+ },
+ [siweServerCall],
+ );
+
+ const dispatch = useDispatch();
+ return React.useCallback(
+ async (input: RegistrationServerCallInput) => {
+ if (input.accountSelection.accountType === 'username') {
+ await registerUsernameAccount(input.accountSelection);
+ } else {
+ await registerEthereumAccount(input.accountSelection);
+ }
+ dispatch({
+ type: setDataLoadedActionType,
+ payload: {
+ dataLoaded: true,
+ },
+ });
+ },
+ [registerUsernameAccount, registerEthereumAccount, dispatch],
+ );
+}
+
+export { useRegistrationServerCall };
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
@@ -36,3 +36,10 @@
+updateUserAvatarRequest: UpdateUserAvatarRequest,
+clientAvatar: ClientAvatar,
};
+
+export type RegistrationServerCallInput = {
+ +coolOrNerdMode: CoolOrNerdMode,
+ +keyserverUsername: string,
+ +accountSelection: AccountSelection,
+ +avatarData: ?AvatarData,
+};