diff --git a/native/account/registration/username-selection.react.js b/native/account/registration/username-selection.react.js
index 654fc006f..46f3e5e7d 100644
--- a/native/account/registration/username-selection.react.js
+++ b/native/account/registration/username-selection.react.js
@@ -1,55 +1,185 @@
// @flow
import * as React from 'react';
-import { Text } from 'react-native';
+import { View, Text } from 'react-native';
+
+import {
+ exactSearchUser,
+ exactSearchUserActionTypes,
+} from 'lib/actions/user-actions.js';
+import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
+import { validUsernameRegex } from 'lib/shared/account-utils.js';
+import {
+ useServerCall,
+ useDispatchActionPromise,
+} from 'lib/utils/action-utils.js';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
+import RegistrationTextInput from './registration-text-input.react.js';
import type { CoolOrNerdMode } from './registration-types.js';
import type { NavigationRoute } from '../../navigation/route-names.js';
+import { useSelector } from '../../redux/redux-utils.js';
import { useStyles } from '../../themes/colors.js';
+const exactSearchUserLoadingStatusSelector = createLoadingStatusSelector(
+ exactSearchUserActionTypes,
+);
+
export type UsernameSelectionParams = {
+userSelections: {
+coolOrNerdMode: CoolOrNerdMode,
+keyserverUsername: string,
},
};
+type UsernameError = 'username_invalid' | 'username_taken';
+
type Props = {
+navigation: RegistrationNavigationProp<'UsernameSelection'>,
+route: NavigationRoute<'UsernameSelection'>,
};
// eslint-disable-next-line no-unused-vars
function UsernameSelection(props: Props): React.Node {
- const onProceed = React.useCallback(() => {}, []);
+ const [username, setUsername] = React.useState('');
+ const validUsername = username.search(validUsernameRegex) > -1;
+ const [usernameError, setUsernameError] = React.useState();
const styles = useStyles(unboundStyles);
+ const checkUsernameValidity = React.useCallback(() => {
+ if (validUsername) {
+ return true;
+ }
+ setUsernameError('username_invalid');
+ return false;
+ }, [validUsername]);
+
+ const exactSearchUserCall = useServerCall(exactSearchUser);
+ const dispatchActionPromise = useDispatchActionPromise();
+ const onProceed = React.useCallback(async () => {
+ if (!checkUsernameValidity()) {
+ return;
+ }
+
+ const searchPromise = exactSearchUserCall(username);
+ dispatchActionPromise(exactSearchUserActionTypes, searchPromise);
+ const { userInfo } = await searchPromise;
+
+ if (userInfo) {
+ setUsernameError('username_taken');
+ return;
+ }
+
+ setUsernameError(undefined);
+ }, [
+ checkUsernameValidity,
+ username,
+ exactSearchUserCall,
+ dispatchActionPromise,
+ ]);
+
+ const exactSearchUserCallLoading = useSelector(
+ state => exactSearchUserLoadingStatusSelector(state) === 'loading',
+ );
+ let buttonVariant = 'disabled';
+ if (exactSearchUserCallLoading) {
+ buttonVariant = 'loading';
+ } else if (validUsername) {
+ buttonVariant = 'enabled';
+ }
+
+ let errorText;
+ if (usernameError === 'username_invalid') {
+ errorText = (
+ <>
+ Usernames must:
+
+ {'1. '}
+
+ Be at least one character long.
+
+
+
+ {'2. '}
+
+ Start with either a letter or a number.
+
+
+
+ {'3. '}
+
+ Contain only letters, numbers, or the characters “-” and “_”.
+
+
+ >
+ );
+ } else if (usernameError === 'username_taken') {
+ errorText = (
+
+ Username taken. Please try another one
+
+ );
+ }
+
return (
Pick a username
+
+ {errorText}
);
}
const unboundStyles = {
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
},
+ error: {
+ marginTop: 16,
+ },
+ errorText: {
+ fontFamily: 'Arial',
+ fontSize: 15,
+ lineHeight: 20,
+ color: 'redText',
+ },
+ listItem: {
+ flexDirection: 'row',
+ },
+ listItemNumber: {
+ fontWeight: 'bold',
+ },
+ listItemContent: {
+ flexShrink: 1,
+ },
};
export default UsernameSelection;