/* * Wire * Copyright (C) 2021 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import React, {FormEvent, useState} from 'react'; import cx from 'classnames'; import {t} from 'Util/LocalizerUtil'; import {AccountInput, useInputDone} from './AccountInput'; import {UserError} from '../../../../../error/UserError'; import {validateHandle} from '../../../../../user/UserHandleGenerator'; import {UserRepository} from '../../../../../user/UserRepository'; enum UserNameState { AVAILABLE = 'AVAILABLE', TAKEN = 'TAKEN', } interface UsernameInputProps { canEditProfile: boolean; domain?: string; username: string; userRepository: UserRepository; } const UsernameInput: React.FC = ({username, domain, userRepository, canEditProfile}) => { const [errorState, setErrorState] = useState(null); const [isEditing, setIsEditing] = useState(false); const [requestedName, setRequestedName] = useState(null); const [submittedName, setSubmittedName] = useState(null); const usernameInputDone = useInputDone(); const verifyUsername = (enteredUsername: string): void => { const usernameTooShort = enteredUsername.length < UserRepository.CONFIG.MINIMUM_USERNAME_LENGTH; const usernameUnchanged = enteredUsername === username; if (usernameTooShort || usernameUnchanged) { return setErrorState(null); } setRequestedName(enteredUsername); if (validateHandle(enteredUsername)) { userRepository .verifyUserHandle(enteredUsername) .then(() => { const isCurrentRequest = requestedName === enteredUsername; if (isCurrentRequest) { setErrorState(UserNameState.AVAILABLE); } }) .catch(error => { const isUsernameTaken = error.type === UserError.TYPE.USERNAME_TAKEN; const isCurrentRequest = requestedName === enteredUsername; if (isUsernameTaken && isCurrentRequest) { setErrorState(UserNameState.TAKEN); } }); } }; const changeUsername = async (newUsername: string): Promise => { const normalizedUsername = newUsername.toLowerCase(); setRequestedName(normalizedUsername); const isUnchanged = normalizedUsername === username; if (isUnchanged) { usernameInputDone.done(); return; } const isInvalidName = normalizedUsername.length < UserRepository.CONFIG.MINIMUM_USERNAME_LENGTH; if (isInvalidName) { setErrorState(null); return; } setSubmittedName(normalizedUsername); try { await userRepository.changeUsername(normalizedUsername); const isCurrentRequest = requestedName === submittedName; if (isCurrentRequest) { setErrorState(null); usernameInputDone.done(); } } catch (error) { if (error instanceof UserError) { const isUsernameTaken = error.type === UserError.TYPE.USERNAME_TAKEN; const isCurrentRequest = requestedName === submittedName; if (isUsernameTaken && isCurrentRequest) { setErrorState(UserNameState.TAKEN); } } } }; return (
verifyUsername((target as HTMLInputElement).value)} readOnly={!canEditProfile} prefix="@" suffix={domain && `@${domain}`} setIsEditing={setIsEditing} isDone={usernameInputDone.isDone} onValueChange={changeUsername} maxLength={256 - (domain?.length ?? 0)} allowedChars="0-9a-zA-Z_.-" fieldName="username" /> {canEditProfile && (

{isEditing && ( <> {errorState === UserNameState.AVAILABLE && t('preferencesAccountUsernameAvailable')} {errorState === UserNameState.TAKEN && t('preferencesAccountUsernameErrorTaken')} {!errorState && t('preferencesAccountUsernameHint')} )}

)}
); }; export {UsernameInput};