You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			198 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			198 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			TypeScript
		
	
| import React, { useContext, useState } from 'react';
 | |
| import { Flex } from '../../basic/Flex';
 | |
| import { SpacerLG } from '../../basic/Text';
 | |
| import { SessionButton, SessionButtonColor, SessionButtonType } from '../SessionButton';
 | |
| import { SessionSpinner } from '../SessionSpinner';
 | |
| import { RegistrationContext, RegistrationPhase, signInWithLinking, signInWithRecovery } from './RegistrationStages';
 | |
| import { RegistrationUserDetails } from './RegistrationUserDetails';
 | |
| import { TermsAndConditions } from './TermsAndConditions';
 | |
| 
 | |
| export enum SignInMode {
 | |
|   Default,
 | |
|   UsingRecoveryPhrase,
 | |
|   LinkDevice,
 | |
| }
 | |
| // tslint:disable: use-simple-attributes
 | |
| // tslint:disable: react-unused-props-and-state
 | |
| 
 | |
| const LinkDeviceButton = (props: { onLinkDeviceButtonClicked: () => any }) => {
 | |
|   return (
 | |
|     <SessionButton
 | |
|       onClick={props.onLinkDeviceButtonClicked}
 | |
|       buttonType={SessionButtonType.BrandOutline}
 | |
|       buttonColor={SessionButtonColor.Green}
 | |
|       text={window.i18n('linkDevice')}
 | |
|     />
 | |
|   );
 | |
| };
 | |
| 
 | |
| const RestoreUsingRecoveryPhraseButton = (props: { onRecoveryButtonClicked: () => any }) => {
 | |
|   return (
 | |
|     <SessionButton
 | |
|       onClick={props.onRecoveryButtonClicked}
 | |
|       buttonType={SessionButtonType.BrandOutline}
 | |
|       buttonColor={SessionButtonColor.Green}
 | |
|       text={window.i18n('restoreUsingRecoveryPhrase')}
 | |
|     />
 | |
|   );
 | |
| };
 | |
| 
 | |
| const ContinueYourSessionButton = (props: {
 | |
|   handleContinueYourSessionClick: () => any;
 | |
|   disabled: boolean;
 | |
| }) => {
 | |
|   return (
 | |
|     <SessionButton
 | |
|       onClick={props.handleContinueYourSessionClick}
 | |
|       buttonType={SessionButtonType.Brand}
 | |
|       buttonColor={SessionButtonColor.Green}
 | |
|       text={window.i18n('continueYourSession')}
 | |
|       disabled={props.disabled}
 | |
|     />
 | |
|   );
 | |
| };
 | |
| 
 | |
| const SignInContinueButton = (props: {
 | |
|   signInMode: SignInMode;
 | |
|   disabled: boolean;
 | |
|   handleContinueYourSessionClick: () => any;
 | |
| }) => {
 | |
|   if (props.signInMode === SignInMode.Default) {
 | |
|     return <></>;
 | |
|   }
 | |
|   return (
 | |
|     <ContinueYourSessionButton
 | |
|       handleContinueYourSessionClick={props.handleContinueYourSessionClick}
 | |
|       disabled={props.disabled}
 | |
|     />
 | |
|   );
 | |
| };
 | |
| 
 | |
| const SignInButtons = (props: {
 | |
|   signInMode: SignInMode;
 | |
|   onRecoveryButtonClicked: () => any;
 | |
|   onLinkDeviceButtonClicked: () => any;
 | |
| }) => {
 | |
|   if (props.signInMode !== SignInMode.Default) {
 | |
|     return <></>;
 | |
|   }
 | |
|   return (
 | |
|     <div>
 | |
|       <RestoreUsingRecoveryPhraseButton onRecoveryButtonClicked={props.onRecoveryButtonClicked} />
 | |
|       <SpacerLG />
 | |
|       <LinkDeviceButton onLinkDeviceButtonClicked={props.onLinkDeviceButtonClicked} />
 | |
|     </div>
 | |
|   );
 | |
| };
 | |
| 
 | |
| export const SignInTab = () => {
 | |
|   const { setRegistrationPhase } = useContext(RegistrationContext);
 | |
| 
 | |
|   const [signInMode, setSignInMode] = useState(SignInMode.Default);
 | |
|   const [recoveryPhrase, setRecoveryPhrase] = useState('');
 | |
|   const [recoveryPhraseError, setRecoveryPhraseError] = useState(undefined as string | undefined);
 | |
|   const [displayName, setDisplayName] = useState('');
 | |
|   const [displayNameError, setDisplayNameError] = useState('');
 | |
|   const [loading, setIsLoading] = useState(false);
 | |
| 
 | |
|   const isRecovery = signInMode === SignInMode.UsingRecoveryPhrase;
 | |
|   const isLinking = signInMode === SignInMode.LinkDevice;
 | |
|   const showTermsAndConditions = signInMode !== SignInMode.Default;
 | |
| 
 | |
|   // show display name input only if we are trying to recover from seed.
 | |
|   // We don't need a display name when we link a device, as the display name
 | |
|   // from the configuration message will be used.
 | |
|   const showDisplayNameField = isRecovery;
 | |
| 
 | |
|   // Display name is required only on isRecoveryMode
 | |
|   const displayNameOK = (isRecovery && !displayNameError && !!displayName) || isLinking;
 | |
| 
 | |
|   // Seed is mandatory no matter which mode
 | |
|   const seedOK = recoveryPhrase && !recoveryPhraseError;
 | |
| 
 | |
|   const activateContinueButton = seedOK && displayNameOK && !loading;
 | |
| 
 | |
|   const continueYourSession = async () => {
 | |
|     if (isRecovery) {
 | |
|       await signInWithRecovery({
 | |
|         displayName,
 | |
|         userRecoveryPhrase: recoveryPhrase,
 | |
|       });
 | |
|     } else if (isLinking) {
 | |
|       setIsLoading(true);
 | |
|       await signInWithLinking({
 | |
|         userRecoveryPhrase: recoveryPhrase,
 | |
|       });
 | |
|       setIsLoading(false);
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   return (
 | |
|     <div className="session-registration__content">
 | |
|       {signInMode !== SignInMode.Default && (
 | |
|         <RegistrationUserDetails
 | |
|           showDisplayNameField={showDisplayNameField}
 | |
|           showSeedField={true}
 | |
|           displayName={displayName}
 | |
|           handlePressEnter={continueYourSession}
 | |
|           onDisplayNameChanged={(name: string) => {
 | |
|             const sanitizedName = name.replace(window.displayNameRegex, '');
 | |
|             const trimName = sanitizedName.trim();
 | |
|             setDisplayName(sanitizedName);
 | |
|             setDisplayNameError(!trimName ? window.i18n('displayNameEmpty') : undefined);
 | |
|           }}
 | |
|           onSeedChanged={(seed: string) => {
 | |
|             setRecoveryPhrase(seed);
 | |
|             setRecoveryPhraseError(!seed ? window.i18n('recoveryPhraseEmpty') : undefined);
 | |
|           }}
 | |
|           recoveryPhrase={recoveryPhrase}
 | |
|           stealAutoFocus={true}
 | |
|         />
 | |
|       )}
 | |
| 
 | |
|       <SignInButtons
 | |
|         signInMode={signInMode}
 | |
|         onRecoveryButtonClicked={() => {
 | |
|           setRegistrationPhase(RegistrationPhase.SignIn);
 | |
|           setSignInMode(SignInMode.UsingRecoveryPhrase);
 | |
|           setRecoveryPhrase('');
 | |
|           setDisplayName('');
 | |
|           setIsLoading(false);
 | |
|         }}
 | |
|         onLinkDeviceButtonClicked={() => {
 | |
|           setRegistrationPhase(RegistrationPhase.SignIn);
 | |
|           setSignInMode(SignInMode.LinkDevice);
 | |
|           setRecoveryPhrase('');
 | |
|           setDisplayName('');
 | |
|           setIsLoading(false);
 | |
|         }}
 | |
|       />
 | |
|       <SignInContinueButton
 | |
|         signInMode={signInMode}
 | |
|         handleContinueYourSessionClick={continueYourSession}
 | |
|         disabled={!activateContinueButton}
 | |
|       />
 | |
|       {loading && (
 | |
|         <Flex
 | |
|           container={true}
 | |
|           justifyContent="center"
 | |
|           alignItems="center"
 | |
|           style={{
 | |
|             position: 'absolute',
 | |
|             top: 0,
 | |
|             bottom: 0,
 | |
|             left: 0,
 | |
|             right: 0,
 | |
|             pointerEvents: 'all',
 | |
|             backgroundColor: '#00000088',
 | |
|           }}
 | |
|         >
 | |
|           <SessionSpinner loading={true} />
 | |
|         </Flex>
 | |
|       )}
 | |
| 
 | |
|       {showTermsAndConditions && <TermsAndConditions />}
 | |
|     </div>
 | |
|   );
 | |
| };
 |