feat: finished fade animation between steps

moved useState props to redux, fixed back button
pull/3056/head
William Grant 1 year ago
parent f196bab2ea
commit e6dedc83fb

@ -2,7 +2,7 @@ import styled from 'styled-components';
import { useRightOverlayMode } from '../../../hooks/useUI'; import { useRightOverlayMode } from '../../../hooks/useUI';
import { isRtlBody } from '../../../util/i18n'; import { isRtlBody } from '../../../util/i18n';
import { Flex } from '../../basic/Flex'; import { Flex } from '../../basic/Flex';
import { OverlayRightPanelSettings2 } from './overlay/OverlayRightPanelSettings2'; import { OverlayRightPanelSettings } from './overlay/OverlayRightPanelSettings';
import { OverlayDisappearingMessages } from './overlay/disappearing-messages/OverlayDisappearingMessages'; import { OverlayDisappearingMessages } from './overlay/disappearing-messages/OverlayDisappearingMessages';
import { OverlayMessageInfo } from './overlay/message-info/OverlayMessageInfo'; import { OverlayMessageInfo } from './overlay/message-info/OverlayMessageInfo';
@ -107,8 +107,7 @@ const ClosableOverlay = () => {
case 'message_info': case 'message_info':
return <OverlayMessageInfo />; return <OverlayMessageInfo />;
default: default:
// TODO[epic=ses-50] revert to proper right panel settings later return <OverlayRightPanelSettings />;
return <OverlayRightPanelSettings2 />;
} }
}; };

@ -1,108 +0,0 @@
import { useEffect, useState } from 'react';
import { MAX_NAME_LENGTH_BYTES } from '../../../../session/constants';
import { ToastUtils } from '../../../../session/utils';
import { sanitizeSessionUsername } from '../../../../session/utils/String';
import { useSelectedConversationKey } from '../../../../state/selectors/selectedConversation';
import { Flex } from '../../../basic/Flex';
import { SessionButton } from '../../../basic/SessionButton';
import { SpacerLG, SpacerXL } from '../../../basic/Text';
import { SessionInput } from '../../../inputs';
import { SessionProgressBar } from '../../../loading';
import { StyledScrollContainer } from './components';
export const OverlayRightPanelSettings2 = () => {
const selectedConvoKey = useSelectedConversationKey();
// TODO[epic=ses-50] move this into already have an account screen
// #region for testing
const [progress, setProgress] = useState(0);
const [inputValue, setInputValue] = useState('');
const [inputError, setInputError] = useState<string | undefined>(undefined);
function sanitizeDisplayNameOrToast(
displayName: string,
setDisplayName: (sanitized: string) => void,
setDisplayNameError: (error: string | undefined) => void
) {
try {
const sanitizedName = sanitizeSessionUsername(displayName);
const trimName = sanitizedName.trim();
setDisplayName(sanitizedName);
setDisplayNameError(!trimName ? window.i18n('displayNameEmpty') : undefined);
} catch (e) {
setDisplayName(displayName);
setDisplayNameError(window.i18n('displayNameTooLong'));
ToastUtils.pushToastError('toolong', window.i18n('displayNameTooLong'));
}
}
const handleInputChanged = (name: string) => {
sanitizeDisplayNameOrToast(name, setInputValue, setInputError);
if (name.length > 8) {
setInputError(window.i18n('displayNameTooLong'));
}
};
const handleEnterPressed = (name: string) => {
if (name) {
sanitizeDisplayNameOrToast(name, setInputValue, setInputError);
ToastUtils.pushToastSuccess('success', window.i18n('done'));
}
};
useEffect(() => {
const interval = setInterval(() => {
setProgress(oldProgress => {
if (oldProgress === 100) {
clearInterval(interval);
return 100;
}
return Math.min(oldProgress + 10, 100);
});
}, 1000);
return () => clearInterval(interval);
}, []);
// #endregion
if (!selectedConvoKey) {
return null;
}
return (
<StyledScrollContainer>
<Flex container={true} flexDirection={'column'} alignItems={'center'}>
<SessionProgressBar
progress={progress}
width={'320px'}
margin={'var(--margins-lg) auto'}
title={window.i18n('waitOneMoment')}
subtitle={window.i18n('loadAccountProgressMessage')}
showPercentage={true}
/>
<SpacerLG />
<SessionInput
placeholder={window.i18n('enterDisplayName')}
value={inputValue}
error={inputError}
maxLength={MAX_NAME_LENGTH_BYTES}
onValueChanged={handleInputChanged}
onEnterPressed={handleEnterPressed}
ctaButton={
<SessionButton
onClick={() => {
window.log.debug(
`WIP: [OverlayRightPanelSettings] clicked continuing your session! `
);
}}
text={window.i18n('continueYourSession')}
/>
}
/>
<SpacerLG />
<SpacerXL />
</Flex>
</StyledScrollContainer>
);
};

@ -1,23 +1,19 @@
import { shell } from 'electron'; import { shell } from 'electron';
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import { useDispatch } from 'react-redux';
import { useMount } from 'react-use'; import { useMount } from 'react-use';
import styled from 'styled-components'; import styled from 'styled-components';
import { Data } from '../../data/data'; import { Data } from '../../data/data';
import { getConversationController } from '../../session/conversations'; import { getConversationController } from '../../session/conversations';
import { mnDecode } from '../../session/crypto/mnemonic';
import { StringUtils } from '../../session/utils';
import { fromHex } from '../../session/utils/String';
import { import {
AccountCreation,
AccountRestoration,
Onboarding, Onboarding,
setGeneratedRecoveryPhrase,
setHexGeneratedPubKey,
} from '../../state/onboarding/ducks/registration'; } from '../../state/onboarding/ducks/registration';
import { import {
useOnboardGeneratedRecoveryPhrase, useOnboardAccountCreationStep,
useOnboardAccountRestorationStep,
useOnboardStep, useOnboardStep,
} from '../../state/onboarding/selectors/registration'; } from '../../state/onboarding/selectors/registration';
import { generateMnemonic, sessionGenerateKeyPair } from '../../util/accountManager';
import { Storage } from '../../util/storage'; import { Storage } from '../../util/storage';
import { Flex } from '../basic/Flex'; import { Flex } from '../basic/Flex';
import { SpacerLG, SpacerSM } from '../basic/Text'; import { SpacerLG, SpacerSM } from '../basic/Text';
@ -49,33 +45,11 @@ const StyledRegistrationContainer = styled(Flex)`
`; `;
export const RegistrationStages = () => { export const RegistrationStages = () => {
const generatedRecoveryPhrase = useOnboardGeneratedRecoveryPhrase();
const step = useOnboardStep(); const step = useOnboardStep();
const creationStep = useOnboardAccountCreationStep();
const dispatch = useDispatch(); const restorationStep = useOnboardAccountRestorationStep();
const generateMnemonicAndKeyPair = async () => {
if (generatedRecoveryPhrase === '') {
const mnemonic = await generateMnemonic();
let seedHex = mnDecode(mnemonic);
// handle shorter than 32 bytes seeds
const privKeyHexLength = 32 * 2;
if (seedHex.length !== privKeyHexLength) {
seedHex = seedHex.concat('0'.repeat(32));
seedHex = seedHex.substring(0, privKeyHexLength);
}
const seed = fromHex(seedHex);
const keyPair = await sessionGenerateKeyPair(seed);
const newHexPubKey = StringUtils.decode(keyPair.pubKey, 'hex');
dispatch(setGeneratedRecoveryPhrase(mnemonic));
dispatch(setHexGeneratedPubKey(newHexPubKey)); // our 'frontend' sessionID
}
};
useMount(() => { useMount(() => {
void generateMnemonicAndKeyPair();
void resetRegistration(); void resetRegistration();
}); });
@ -117,7 +91,10 @@ export const RegistrationStages = () => {
<Flex container={true} flexDirection="column" alignItems="center"> <Flex container={true} flexDirection="column" alignItems="center">
<SpacerLG /> <SpacerLG />
<OnboardContainer key={'onboarding-container'} animate={true} direction="right"> <OnboardContainer
key={`${Onboarding[step]}-${step === Onboarding.CreateAccount ? AccountCreation[creationStep] : AccountRestoration[restorationStep]}`}
animate={step !== Onboarding.Start}
>
{step === Onboarding.Start ? <Start /> : null} {step === Onboarding.Start ? <Start /> : null}
{step === Onboarding.CreateAccount ? <CreateAccount /> : null} {step === Onboarding.CreateAccount ? <CreateAccount /> : null}
{step === Onboarding.RestoreAccount ? <RestoreAccount /> : null} {step === Onboarding.RestoreAccount ? <RestoreAccount /> : null}

@ -1,13 +1,16 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { import {
AccountCreation,
AccountRestoration, AccountRestoration,
Onboarding, Onboarding,
setAccountCreationStep,
setAccountRestorationStep, setAccountRestorationStep,
setDirection,
setOnboardingStep, setOnboardingStep,
} from '../../../state/onboarding/ducks/registration'; } from '../../../state/onboarding/ducks/registration';
import {
useOnboardAccountRestorationStep,
useOnboardStep,
} from '../../../state/onboarding/selectors/registration';
import { Flex } from '../../basic/Flex'; import { Flex } from '../../basic/Flex';
import { SessionIconButton } from '../../icon'; import { SessionIconButton } from '../../icon';
@ -31,6 +34,9 @@ export const BackButtonWithininContainer = ({
}; };
export const BackButton = ({ callback }: { callback?: () => void }) => { export const BackButton = ({ callback }: { callback?: () => void }) => {
const step = useOnboardStep();
const restorationStep = useOnboardAccountRestorationStep();
const dispatch = useDispatch(); const dispatch = useDispatch();
return ( return (
@ -40,9 +46,19 @@ export const BackButton = ({ callback }: { callback?: () => void }) => {
iconColor="var(--color-text-primary)" iconColor="var(--color-text-primary)"
iconRotation={90} iconRotation={90}
onClick={() => { onClick={() => {
dispatch(setOnboardingStep(Onboarding.Start)); dispatch(setDirection('backward'));
dispatch(setAccountRestorationStep(AccountRestoration.RecoveryPassword)); if (step === Onboarding.CreateAccount) {
dispatch(setAccountCreationStep(AccountCreation.DisplayName)); dispatch(setOnboardingStep(Onboarding.Start));
}
if (step === Onboarding.RestoreAccount) {
if (restorationStep === AccountRestoration.RecoveryPassword) {
dispatch(setOnboardingStep(Onboarding.Start));
} else if (restorationStep === AccountRestoration.DisplayName) {
dispatch(setAccountRestorationStep(AccountRestoration.RecoveryPassword));
}
}
if (callback) { if (callback) {
callback(); callback();
} }

@ -6,21 +6,18 @@ type OnboardContainerProps = {
animate?: boolean; animate?: boolean;
children: ReactNode; children: ReactNode;
key: string; key: string;
direction: 'left' | 'right';
}; };
export const OnboardContainer = (props: OnboardContainerProps) => { export const OnboardContainer = (props: OnboardContainerProps) => {
const { animate = false, children, key, direction: _direction } = props; const { animate = false, children, key } = props;
const OnboardContainerInner = styled(motion.div)` const OnboardContainerInner = styled(motion.div)`
width: 100%; width: 100%;
`; `;
const direction = _direction === 'left' ? -1 : 1;
const fadeSlideVariants = { const fadeSlideVariants = {
initial: { x: 50 * direction, opacity: 0 }, initial: { opacity: 0 },
animate: { x: 0, opacity: 1 }, animate: { opacity: 1 },
exit: { x: -50 * direction, opacity: 0 }, exit: { opacity: 0 },
}; };
return ( return (
@ -30,7 +27,7 @@ export const OnboardContainer = (props: OnboardContainerProps) => {
initial={'initial'} initial={'initial'}
animate={'animate'} animate={'animate'}
exit={'exit'} exit={'exit'}
transition={{ duration: 0.5 }} transition={{ duration: 1 }}
> >
{children} {children}
</OnboardContainerInner> </OnboardContainerInner>

@ -1,4 +1,4 @@
import { Dispatch } from '@reduxjs/toolkit'; import { AnyAction, Dispatch } from '@reduxjs/toolkit';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { ONBOARDING_TIMES } from '../../../session/constants'; import { ONBOARDING_TIMES } from '../../../session/constants';
@ -13,7 +13,7 @@ let interval: NodeJS.Timeout;
type UseRecoveryProgressEffectProps = { type UseRecoveryProgressEffectProps = {
step: AccountRestoration; step: AccountRestoration;
progress: number; progress: number;
setProgress: (progress: number) => void; setProgress: (progress: number) => AnyAction;
displayName: string; displayName: string;
dispatch: Dispatch; dispatch: Dispatch;
}; };
@ -22,7 +22,7 @@ type UseRecoveryProgressEffectProps = {
* Effect to handle the progress rate of the recovery loading animation * Effect to handle the progress rate of the recovery loading animation
* @param step AccountRestoration the onboarding step we are currently on * @param step AccountRestoration the onboarding step we are currently on
* @param progress number the progress of the loading bar * @param progress number the progress of the loading bar
* @param setProgress (progress: number) => void function to set the progress of the loading bar * @param setProgress (progress: number) => AnyAction redux function to set the progress of the loading bar
* @param displayName string the display name of the user * @param displayName string the display name of the user
* @param dispatch * @param dispatch
*/ */
@ -33,7 +33,7 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
if (step === AccountRestoration.Loading) { if (step === AccountRestoration.Loading) {
interval = setInterval(() => { interval = setInterval(() => {
if (progress < 100) { if (progress < 100) {
setProgress(progress + 1); dispatch(setProgress(progress + 1));
} }
window.log.debug( window.log.debug(
`WIP: [continueYourSession] AccountRestoration.Loading Loading progress ${progress}%` `WIP: [continueYourSession] AccountRestoration.Loading Loading progress ${progress}%`
@ -53,7 +53,7 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
if (step === AccountRestoration.Finishing) { if (step === AccountRestoration.Finishing) {
interval = setInterval(() => { interval = setInterval(() => {
if (progress < 100) { if (progress < 100) {
setProgress(progress + 1); dispatch(setProgress(progress + 1));
} }
window.log.debug( window.log.debug(
`WIP: [continueYourSession] AccountRestoration. Finishing progress ${progress}%` `WIP: [continueYourSession] AccountRestoration. Finishing progress ${progress}%`

@ -1,17 +1,29 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useMount } from 'react-use';
import { SettingsKey } from '../../../data/settings-key'; import { SettingsKey } from '../../../data/settings-key';
import { mnDecode } from '../../../session/crypto/mnemonic';
import { StringUtils } from '../../../session/utils';
import { fromHex } from '../../../session/utils/String';
import { trigger } from '../../../shims/events'; import { trigger } from '../../../shims/events';
import { import {
AccountCreation, AccountCreation,
setAccountCreationStep, setAccountCreationStep,
setDisplayName,
setHexGeneratedPubKey,
setRecoveryPassword,
} from '../../../state/onboarding/ducks/registration'; } from '../../../state/onboarding/ducks/registration';
import { import {
useDisplayName,
useOnboardAccountCreationStep, useOnboardAccountCreationStep,
useOnboardGeneratedRecoveryPhrase,
useOnboardHexGeneratedPubKey, useOnboardHexGeneratedPubKey,
useRecoveryPassword,
} from '../../../state/onboarding/selectors/registration'; } from '../../../state/onboarding/selectors/registration';
import { registerSingleDevice } from '../../../util/accountManager'; import {
generateMnemonic,
registerSingleDevice,
sessionGenerateKeyPair,
} from '../../../util/accountManager';
import { Storage, setSignWithRecoveryPhrase } from '../../../util/storage'; import { Storage, setSignWithRecoveryPhrase } from '../../../util/storage';
import { Flex } from '../../basic/Flex'; import { Flex } from '../../basic/Flex';
import { SessionButton, SessionButtonColor } from '../../basic/SessionButton'; import { SessionButton, SessionButtonColor } from '../../basic/SessionButton';
@ -43,16 +55,40 @@ async function signUp(signUpDetails: RecoverDetails) {
export const CreateAccount = () => { export const CreateAccount = () => {
const step = useOnboardAccountCreationStep(); const step = useOnboardAccountCreationStep();
const recoveryPassword = useOnboardGeneratedRecoveryPhrase(); const recoveryPassword = useRecoveryPassword();
const hexGeneratedPubKey = useOnboardHexGeneratedPubKey(); const hexGeneratedPubKey = useOnboardHexGeneratedPubKey();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [displayName, setDisplayName] = useState(''); const displayName = useDisplayName();
const [displayNameError, setDisplayNameError] = useState<undefined | string>(''); const [displayNameError, setDisplayNameError] = useState<undefined | string>('');
const generateMnemonicAndKeyPair = async () => {
if (recoveryPassword === '') {
const mnemonic = await generateMnemonic();
let seedHex = mnDecode(mnemonic);
// handle shorter than 32 bytes seeds
const privKeyHexLength = 32 * 2;
if (seedHex.length !== privKeyHexLength) {
seedHex = seedHex.concat('0'.repeat(32));
seedHex = seedHex.substring(0, privKeyHexLength);
}
const seed = fromHex(seedHex);
const keyPair = await sessionGenerateKeyPair(seed);
const newHexPubKey = StringUtils.decode(keyPair.pubKey, 'hex');
dispatch(setRecoveryPassword(mnemonic));
dispatch(setHexGeneratedPubKey(newHexPubKey)); // our 'frontend' sessionID
}
};
useMount(() => {
void generateMnemonicAndKeyPair();
});
useEffect(() => { useEffect(() => {
if (step === AccountCreation.DisplayName) { if (step === AccountCreation.DisplayName && hexGeneratedPubKey) {
window.Session.setNewSessionID(hexGeneratedPubKey); window.Session.setNewSessionID(hexGeneratedPubKey);
} }
}, [step, hexGeneratedPubKey]); }, [step, hexGeneratedPubKey]);
@ -85,6 +121,8 @@ export const CreateAccount = () => {
<BackButtonWithininContainer <BackButtonWithininContainer
margin={'2px 0 0 -36px'} margin={'2px 0 0 -36px'}
callback={() => { callback={() => {
dispatch(setDisplayName(''));
dispatch(setRecoveryPassword(''));
setDisplayNameError(''); setDisplayNameError('');
}} }}
> >
@ -101,11 +139,13 @@ export const CreateAccount = () => {
<SpacerLG /> <SpacerLG />
<SessionInput <SessionInput
autoFocus={true} autoFocus={true}
disabledOnBlur={true}
type="text" type="text"
placeholder={window.i18n('enterDisplayName')} placeholder={window.i18n('enterDisplayName')}
value={displayName} value={displayName}
onValueChanged={(name: string) => { onValueChanged={(_name: string) => {
sanitizeDisplayNameOrToast(name, setDisplayName, setDisplayNameError); const name = sanitizeDisplayNameOrToast(_name, setDisplayNameError);
dispatch(setDisplayName(name));
}} }}
onEnterPressed={signUpWithDetails} onEnterPressed={signUpWithDetails}
error={displayNameError} error={displayNameError}

@ -9,8 +9,16 @@ import { NotFoundError } from '../../../session/utils/errors';
import { import {
AccountRestoration, AccountRestoration,
setAccountRestorationStep, setAccountRestorationStep,
setDisplayName,
setProgress,
setRecoveryPassword,
} from '../../../state/onboarding/ducks/registration'; } from '../../../state/onboarding/ducks/registration';
import { useOnboardAccountRestorationStep } from '../../../state/onboarding/selectors/registration'; import {
useDisplayName,
useOnboardAccountRestorationStep,
useProgress,
useRecoveryPassword,
} from '../../../state/onboarding/selectors/registration';
import { registerSingleDevice, signInByLinkingDevice } from '../../../util/accountManager'; import { registerSingleDevice, signInByLinkingDevice } from '../../../util/accountManager';
import { setSignInByLinking, setSignWithRecoveryPhrase } from '../../../util/storage'; import { setSignInByLinking, setSignWithRecoveryPhrase } from '../../../util/storage';
import { Flex } from '../../basic/Flex'; import { Flex } from '../../basic/Flex';
@ -99,15 +107,15 @@ async function signInAndFetchDisplayName(
export const RestoreAccount = () => { export const RestoreAccount = () => {
const step = useOnboardAccountRestorationStep(); const step = useOnboardAccountRestorationStep();
const [recoveryPassword, setRecoveryPassword] = useState(''); const recoveryPassword = useRecoveryPassword();
const [recoveryPasswordError, setRecoveryPasswordError] = useState( const [recoveryPasswordError, setRecoveryPasswordError] = useState(
undefined as string | undefined undefined as string | undefined
); );
const [displayName, setDisplayName] = useState(''); const displayName = useDisplayName();
const [displayNameError, setDisplayNameError] = useState<undefined | string>(''); const [displayNameError, setDisplayNameError] = useState<undefined | string>('');
const [progress, setProgress] = useState(0); const progress = useProgress();
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -118,7 +126,7 @@ export const RestoreAccount = () => {
return; return;
} }
setProgress(0); dispatch(setProgress(0));
try { try {
const displayNameFromNetwork = await signInAndFetchDisplayName({ const displayNameFromNetwork = await signInAndFetchDisplayName({
recoveryPassword, recoveryPassword,
@ -129,7 +137,7 @@ export const RestoreAccount = () => {
dispatch(setAccountRestorationStep(AccountRestoration.Loading)); dispatch(setAccountRestorationStep(AccountRestoration.Loading));
}, },
}); });
setDisplayName(displayNameFromNetwork); dispatch(setDisplayName(displayNameFromNetwork));
dispatch(setAccountRestorationStep(AccountRestoration.Finishing)); dispatch(setAccountRestorationStep(AccountRestoration.Finishing));
} catch (e) { } catch (e) {
if (e instanceof NotFoundError) { if (e instanceof NotFoundError) {
@ -161,7 +169,7 @@ export const RestoreAccount = () => {
return; return;
} }
setProgress(0); dispatch(setProgress(0));
try { try {
await signInWithNewDisplayName({ await signInWithNewDisplayName({
displayName, displayName,
@ -186,9 +194,12 @@ export const RestoreAccount = () => {
<BackButtonWithininContainer <BackButtonWithininContainer
margin={'2px 0 0 -36px'} margin={'2px 0 0 -36px'}
callback={() => { callback={() => {
setDisplayNameError(''); dispatch(setRecoveryPassword(''));
dispatch(setDisplayName(''));
dispatch(setProgress(0));
setRecoveryPasswordError(''); setRecoveryPasswordError('');
setProgress(0); setDisplayNameError('');
}} }}
> >
<Flex <Flex
@ -220,7 +231,7 @@ export const RestoreAccount = () => {
placeholder={window.i18n('enterRecoveryPhrase')} placeholder={window.i18n('enterRecoveryPhrase')}
value={recoveryPassword} value={recoveryPassword}
onValueChanged={(seed: string) => { onValueChanged={(seed: string) => {
setRecoveryPassword(seed); dispatch(setRecoveryPassword(seed));
setRecoveryPasswordError( setRecoveryPasswordError(
!seed ? window.i18n('recoveryPhraseEmpty') : undefined !seed ? window.i18n('recoveryPhraseEmpty') : undefined
); );
@ -247,11 +258,13 @@ export const RestoreAccount = () => {
<SpacerLG /> <SpacerLG />
<SessionInput <SessionInput
autoFocus={true} autoFocus={true}
disabledOnBlur={true}
type="text" type="text"
placeholder={window.i18n('enterDisplayName')} placeholder={window.i18n('enterDisplayName')}
value={displayName} value={displayName}
onValueChanged={(name: string) => { onValueChanged={(_name: string) => {
sanitizeDisplayNameOrToast(name, setDisplayName, setDisplayNameError); const name = sanitizeDisplayNameOrToast(_name, setDisplayNameError);
dispatch(setDisplayName(name));
}} }}
onEnterPressed={recoverAndEnterDisplayName} onEnterPressed={recoverAndEnterDisplayName}
error={displayNameError} error={displayNameError}

@ -5,6 +5,7 @@ import {
Onboarding, Onboarding,
setAccountCreationStep, setAccountCreationStep,
setAccountRestorationStep, setAccountRestorationStep,
setDirection,
setOnboardingStep, setOnboardingStep,
} from '../../../state/onboarding/ducks/registration'; } from '../../../state/onboarding/ducks/registration';
import { SessionButton, SessionButtonColor } from '../../basic/SessionButton'; import { SessionButton, SessionButtonColor } from '../../basic/SessionButton';
@ -19,6 +20,7 @@ export const Start = () => {
<SessionButton <SessionButton
buttonColor={SessionButtonColor.White} buttonColor={SessionButtonColor.White}
onClick={() => { onClick={() => {
dispatch(setDirection('forward'));
dispatch(setAccountCreationStep(AccountCreation.DisplayName)); dispatch(setAccountCreationStep(AccountCreation.DisplayName));
dispatch(setOnboardingStep(Onboarding.CreateAccount)); dispatch(setOnboardingStep(Onboarding.CreateAccount));
}} }}
@ -28,6 +30,7 @@ export const Start = () => {
<SessionButton <SessionButton
buttonColor={SessionButtonColor.White} buttonColor={SessionButtonColor.White}
onClick={() => { onClick={() => {
dispatch(setDirection('forward'));
dispatch(setOnboardingStep(Onboarding.RestoreAccount)); dispatch(setOnboardingStep(Onboarding.RestoreAccount));
dispatch(setAccountRestorationStep(AccountRestoration.RecoveryPassword)); dispatch(setAccountRestorationStep(AccountRestoration.RecoveryPassword));
}} }}

@ -2,17 +2,16 @@ import { sanitizeSessionUsername } from '../../../session/utils/String';
export function sanitizeDisplayNameOrToast( export function sanitizeDisplayNameOrToast(
displayName: string, displayName: string,
setDisplayName: (sanitized: string) => void,
setDisplayNameError: (error: string | undefined) => void setDisplayNameError: (error: string | undefined) => void
) { ) {
try { try {
const sanitizedName = sanitizeSessionUsername(displayName); const sanitizedName = sanitizeSessionUsername(displayName);
const trimName = sanitizedName.trim(); const trimName = sanitizedName.trim();
setDisplayName(sanitizedName);
setDisplayNameError(!trimName ? window.i18n('displayNameEmpty') : undefined); setDisplayNameError(!trimName ? window.i18n('displayNameEmpty') : undefined);
return sanitizedName;
} catch (e) { } catch (e) {
setDisplayName(displayName);
setDisplayNameError(window.i18n('displayNameErrorDescriptionShorter')); setDisplayNameError(window.i18n('displayNameErrorDescriptionShorter'));
return displayName;
} }
} }

@ -31,32 +31,46 @@ export enum AccountRestoration {
Complete, Complete,
} }
export type OnboardDirection = 'backward' | 'forward';
export type OnboardingState = { export type OnboardingState = {
generatedRecoveryPhrase: string; recoveryPassword: string;
hexGeneratedPubKey: string; hexGeneratedPubKey: string;
displayName: string;
progress: number;
step: Onboarding; step: Onboarding;
accountCreationStep: AccountCreation; accountCreationStep: AccountCreation;
accountRestorationStep: AccountRestoration; accountRestorationStep: AccountRestoration;
direction: OnboardDirection;
}; };
const initialState: OnboardingState = { const initialState: OnboardingState = {
generatedRecoveryPhrase: '', recoveryPassword: '',
hexGeneratedPubKey: '', hexGeneratedPubKey: '',
displayName: '',
progress: 0,
step: Onboarding.Start, step: Onboarding.Start,
accountRestorationStep: AccountRestoration.RecoveryPassword, accountRestorationStep: AccountRestoration.RecoveryPassword,
accountCreationStep: AccountCreation.DisplayName, accountCreationStep: AccountCreation.DisplayName,
direction: 'forward',
}; };
export const registrationSlice = createSlice({ export const registrationSlice = createSlice({
name: 'registration', name: 'registration',
initialState, initialState,
reducers: { reducers: {
setGeneratedRecoveryPhrase(state, action: PayloadAction<string>) { setRecoveryPassword(state, action: PayloadAction<string>) {
return { ...state, generatedRecoveryPhrase: action.payload }; return { ...state, recoveryPassword: action.payload };
}, },
setHexGeneratedPubKey(state, action: PayloadAction<string>) { setHexGeneratedPubKey(state, action: PayloadAction<string>) {
return { ...state, hexGeneratedPubKey: action.payload }; return { ...state, hexGeneratedPubKey: action.payload };
}, },
setDisplayName(state, action: PayloadAction<string>) {
return { ...state, displayName: action.payload };
},
setProgress(state, action: PayloadAction<number>) {
return { ...state, progress: action.payload };
},
setOnboardingStep(state, action: PayloadAction<Onboarding>) { setOnboardingStep(state, action: PayloadAction<Onboarding>) {
return { ...state, step: action.payload }; return { ...state, step: action.payload };
}, },
@ -66,14 +80,20 @@ export const registrationSlice = createSlice({
setAccountRestorationStep(state, action: PayloadAction<AccountRestoration>) { setAccountRestorationStep(state, action: PayloadAction<AccountRestoration>) {
return { ...state, accountRestorationStep: action.payload }; return { ...state, accountRestorationStep: action.payload };
}, },
setDirection(state, action: PayloadAction<OnboardDirection>) {
return { ...state, direction: action.payload };
},
}, },
}); });
export const { export const {
setGeneratedRecoveryPhrase, setRecoveryPassword,
setHexGeneratedPubKey, setHexGeneratedPubKey,
setDisplayName,
setProgress,
setOnboardingStep, setOnboardingStep,
setAccountCreationStep, setAccountCreationStep,
setAccountRestorationStep, setAccountRestorationStep,
setDirection,
} = registrationSlice.actions; } = registrationSlice.actions;
export default registrationSlice.reducer; export default registrationSlice.reducer;

@ -3,6 +3,7 @@ import { useSelector } from 'react-redux';
import { import {
AccountCreation, AccountCreation,
AccountRestoration, AccountRestoration,
OnboardDirection,
Onboarding, Onboarding,
OnboardingState, OnboardingState,
} from '../ducks/registration'; } from '../ducks/registration';
@ -13,9 +14,9 @@ const getRegistration = (state: OnboardingStoreState): OnboardingState => {
return state.registration; return state.registration;
}; };
const getGeneratedRecoveryPhrase = createSelector( const getRecoveryPassword = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): string => state.generatedRecoveryPhrase (state: OnboardingState): string => state.recoveryPassword
); );
const getHexGeneratedPubKey = createSelector( const getHexGeneratedPubKey = createSelector(
@ -23,6 +24,16 @@ const getHexGeneratedPubKey = createSelector(
(state: OnboardingState): string => state.hexGeneratedPubKey (state: OnboardingState): string => state.hexGeneratedPubKey
); );
const getDisplayName = createSelector(
getRegistration,
(state: OnboardingState): string => state.displayName
);
const getProgress = createSelector(
getRegistration,
(state: OnboardingState): number => state.progress
);
const getOnboardingStep = createSelector( const getOnboardingStep = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): Onboarding => state.step (state: OnboardingState): Onboarding => state.step
@ -37,17 +48,30 @@ const getAccountRestorationStep = createSelector(
getRegistration, getRegistration,
(state: OnboardingState): AccountRestoration => state.accountRestorationStep (state: OnboardingState): AccountRestoration => state.accountRestorationStep
); );
const getDirection = createSelector(
getRegistration,
(state: OnboardingState): OnboardDirection => state.direction
);
// #endregion // #endregion
// #region Hooks // #region Hooks
export const useOnboardGeneratedRecoveryPhrase = () => { export const useRecoveryPassword = () => {
return useSelector(getGeneratedRecoveryPhrase); return useSelector(getRecoveryPassword);
}; };
export const useOnboardHexGeneratedPubKey = () => { export const useOnboardHexGeneratedPubKey = () => {
return useSelector(getHexGeneratedPubKey); return useSelector(getHexGeneratedPubKey);
}; };
export const useDisplayName = () => {
return useSelector(getDisplayName);
};
export const useProgress = () => {
return useSelector(getProgress);
};
export const useOnboardStep = () => { export const useOnboardStep = () => {
return useSelector(getOnboardingStep); return useSelector(getOnboardingStep);
}; };
@ -59,4 +83,8 @@ export const useOnboardAccountCreationStep = () => {
export const useOnboardAccountRestorationStep = () => { export const useOnboardAccountRestorationStep = () => {
return useSelector(getAccountRestorationStep); return useSelector(getAccountRestorationStep);
}; };
export const useOnboardDirection = () => {
return useSelector(getDirection);
};
// #endregion // #endregion

Loading…
Cancel
Save