fix: fixed animation for different steps

flatten the loading callback as well
pull/3056/head
William Grant 1 year ago
parent a3841d1210
commit a38555c03e

@ -25,6 +25,8 @@ const StyledTitle = styled(StyledText)`
`;
type Props = {
/** a percentage value */
initialValue: number;
/** a percentage value */
progress: number;
color?: string;
@ -39,6 +41,7 @@ type Props = {
export function SessionProgressBar(props: Props) {
const {
initialValue,
progress,
width = '100%',
backgroundColor = 'var(--border-color)',
@ -71,7 +74,7 @@ export function SessionProgressBar(props: Props) {
<ProgressContainer color={backgroundColor} style={{ width }} data-testid="loading-animation">
<Progress
color={color}
initial={{ width: 0 }}
initial={{ width: `${initialValue}%` }}
animate={{ width: `${progress}%` }}
transition={{ duration: 0.5 }}
/>

@ -3,13 +3,11 @@ import { isEmpty } from 'lodash';
import { useCallback, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { ONBOARDING_TIMES } from '../../../session/constants';
import { trigger } from '../../../shims/events';
import {
AccountRestoration,
setAccountRestorationStep,
} from '../../../state/onboarding/ducks/registration';
import { registrationDone } from '../../../util/accountManager';
import { setSignWithRecoveryPhrase } from '../../../util/storage';
import { finishRestore } from '../stages/RestoreAccount';
let interval: NodeJS.Timeout;
@ -36,18 +34,14 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
const dispatch = useDispatch();
const recoveryComplete = useCallback(async () => {
await setSignWithRecoveryPhrase(true);
await registrationDone(ourPubkey, displayName);
window.log.debug(`WIP: [onboarding] restore account: logging in for ${displayName}`);
trigger('openInbox');
await finishRestore(ourPubkey, displayName);
}, [displayName, ourPubkey]);
useEffect(() => {
if (step === AccountRestoration.Loading) {
interval = setInterval(() => {
window.log.debug(
`WIP: [onboarding] restore account: progress ${progress} state ${AccountRestoration[step]}`
`WIP: [onboarding] restore account: ${AccountRestoration[step]} ${progress}%`
);
if (progress < totalProgress) {
@ -57,9 +51,6 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
if (progress >= totalProgress) {
clearInterval(interval);
// if we didn't get the display name in time, we need to enter it manually
window.log.debug(
`WIP: [onboarding] restore account: We failed with a time out when fetching a display name, so we restored manually`
);
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
}
}, ONBOARDING_TIMES.RECOVERY_TIMEOUT / totalProgress);
@ -67,6 +58,10 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
if (step === AccountRestoration.Finishing) {
interval = setInterval(() => {
window.log.debug(
`WIP: [onboarding] restore account: ${AccountRestoration[step]} ${progress}%`
);
if (progress < totalProgress) {
dispatch(setProgress(progress + 1));
}
@ -80,19 +75,24 @@ export const useRecoveryProgressEffect = (props: UseRecoveryProgressEffectProps)
if (step === AccountRestoration.Finished) {
interval = setInterval(() => {
window.log.debug(
`WIP: [onboarding] restore account: ${AccountRestoration[step]} ${progress}%`
);
clearInterval(interval);
if (!isEmpty(displayName)) {
dispatch(setAccountRestorationStep(AccountRestoration.Complete));
} else {
window.log.debug(
`WIP: [onboarding] restore account: We failed with an error when fetching a display name, so we restored manually`
);
// if we didn't get the display name in time, we need to enter it manually
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
}
}, ONBOARDING_TIMES.RECOVERY_FINISHED);
}
if (step === AccountRestoration.Complete) {
window.log.debug(
`WIP: [onboarding] restore account: ${AccountRestoration[step]} ${progress}%`
);
clearInterval(interval);
if (!isEmpty(ourPubkey) && !isEmpty(displayName)) {
void recoveryComplete();

@ -5,6 +5,7 @@ import { InvalidWordsError, NotEnoughWordsError } from '../../../session/crypto/
import { PromiseUtils } from '../../../session/utils';
import { TaskTimedOutError } from '../../../session/utils/Promise';
import { NotFoundError } from '../../../session/utils/errors';
import { trigger } from '../../../shims/events';
import {
AccountRestoration,
setAccountRestorationStep,
@ -24,8 +25,12 @@ import {
useRecoveryPassword,
useRecoveryPasswordError,
} from '../../../state/onboarding/selectors/registration';
import { registerSingleDevice, signInByLinkingDevice } from '../../../util/accountManager';
import { setSignInByLinking } from '../../../util/storage';
import {
registerSingleDevice,
registrationDone,
signInByLinkingDevice,
} from '../../../util/accountManager';
import { setSignInByLinking, setSignWithRecoveryPhrase } from '../../../util/storage';
import { Flex } from '../../basic/Flex';
import { SessionButton, SessionButtonColor } from '../../basic/SessionButton';
import { SpacerLG, SpacerSM } from '../../basic/Text';
@ -38,59 +43,26 @@ import { useRecoveryProgressEffect } from '../hooks';
import { displayNameIsValid, resetRegistration, sanitizeDisplayNameOrToast } from '../utils';
import { AccountDetails } from './CreateAccount';
type AccountRestoreDetails = AccountDetails & { dispatch: Dispatch };
type AccountRestoreDetails = AccountDetails & { dispatch: Dispatch; abortSignal?: AbortSignal };
/**
* Sign in/restore from seed.
* Ask for a display name, as we will drop incoming ConfigurationMessages if any are saved on the swarm.
* We will handle a ConfigurationMessage
*/
async function signInWithNewDisplayName(args: AccountRestoreDetails) {
const { displayName, recoveryPassword, dispatch } = args;
export async function finishRestore(pubkey: string, displayName: string) {
await setSignWithRecoveryPhrase(true);
await registrationDone(pubkey, displayName);
try {
const validDisplayName = displayNameIsValid(displayName);
await resetRegistration();
await registerSingleDevice(
recoveryPassword,
'english',
validDisplayName,
async (pubkey: string) => {
dispatch(setHexGeneratedPubKey(pubkey));
dispatch(setDisplayName(validDisplayName));
dispatch(setAccountRestorationStep(AccountRestoration.Finishing));
}
);
} catch (e) {
await resetRegistration();
throw e;
}
window.log.debug(`WIP: [onboarding] restore account: logging in for ${displayName}`);
trigger('openInbox');
}
/**
* This will try to sign in with the user recovery password.
* If no ConfigurationMessage is received within ONBOARDING_RECOVERY_TIMEOUT, the user will be asked to enter a display name.
*/
async function signInAndFetchDisplayName(
args: AccountRestoreDetails & {
/** this is used to trigger the loading animation further down the registration pipeline */
loadingAnimationCallback: () => void;
abortSignal: AbortSignal;
}
) {
const { recoveryPassword, loadingAnimationCallback, dispatch, abortSignal } = args;
async function signInAndFetchDisplayName(args: AccountRestoreDetails) {
const { recoveryPassword, dispatch, abortSignal } = args;
try {
await resetRegistration();
const promiseLink = signInByLinkingDevice(
recoveryPassword,
'english',
loadingAnimationCallback,
abortSignal
);
const promiseLink = signInByLinkingDevice(recoveryPassword, 'english', abortSignal);
const promiseWait = PromiseUtils.waitForTask(done => {
window.Whisper.events.on(
'configurationMessageReceived',
@ -112,6 +84,34 @@ async function signInAndFetchDisplayName(
}
}
/**
* Sign in/restore from seed.
* Ask for a display name, as we will drop incoming ConfigurationMessages if any are saved on the swarm.
* We will handle a ConfigurationMessage
*/
async function signInWithNewDisplayName(args: AccountRestoreDetails) {
const { displayName, recoveryPassword, dispatch } = args;
try {
const validDisplayName = displayNameIsValid(displayName);
await resetRegistration();
await registerSingleDevice(
recoveryPassword,
'english',
validDisplayName,
async (pubkey: string) => {
dispatch(setHexGeneratedPubKey(pubkey));
dispatch(setDisplayName(validDisplayName));
await finishRestore(pubkey, validDisplayName);
}
);
} catch (e) {
await resetRegistration();
throw e;
}
}
export const RestoreAccount = () => {
const step = useOnboardAccountRestorationStep();
const recoveryPassword = useRecoveryPassword();
@ -142,23 +142,21 @@ export const RestoreAccount = () => {
`WIP: [onboarding] restore account: recoverAndFetchDisplayName() is starting recoveryPassword: ${recoveryPassword}`
);
dispatch(setProgress(0));
dispatch(setAccountRestorationStep(AccountRestoration.Loading));
await signInAndFetchDisplayName({
recoveryPassword,
loadingAnimationCallback: () => {
dispatch(setAccountRestorationStep(AccountRestoration.Loading));
},
dispatch,
abortSignal: abortController.signal,
});
} catch (e) {
window.log.debug(
`WIP: [onboarding] restore account: restoration failed! Error: ${e.message || e}`
);
if (e instanceof NotFoundError || e instanceof TaskTimedOutError) {
// abort the loading animation or display name polling if we get these errors. Now we enter a display name manually
abortController.abort();
dispatch(setAccountRestorationStep(AccountRestoration.DisplayName));
// abort display name polling if we get either error
if (!abortController.signal.aborted) {
abortController.abort();
}
window.log.debug(
`WIP: [onboarding] restore account: We failed when fetching a display name, so we will enter it manually. Error: ${e.message || e} `
);
return;
}
@ -169,6 +167,9 @@ export const RestoreAccount = () => {
} else {
dispatch(setRecoveryPasswordError(window.i18n('recoveryPasswordErrorMessageGeneric')));
}
window.log.debug(
`WIP: [onboarding] restore account: there is a problem with the display nam. Error: ${e.message || e}`
);
dispatch(setAccountRestorationStep(AccountRestoration.RecoveryPassword));
}
};
@ -182,7 +183,6 @@ export const RestoreAccount = () => {
window.log.debug(
`WIP: [onboarding] restore account: recoverAndEnterDisplayName() is starting recoveryPassword: ${recoveryPassword} displayName: ${displayName}`
);
dispatch(setProgress(0));
await signInWithNewDisplayName({
displayName,
recoveryPassword,
@ -206,7 +206,6 @@ export const RestoreAccount = () => {
dispatch(setRecoveryPassword(''));
dispatch(setDisplayName(''));
dispatch(setProgress(0));
dispatch(setRecoveryPasswordError(undefined));
dispatch(setDisplayNameError(undefined));
}}
@ -305,6 +304,9 @@ export const RestoreAccount = () => {
alignItems="flex-start"
>
<SessionProgressBar
initialValue={
step !== AccountRestoration.Finished && step !== AccountRestoration.Complete ? 0 : 100
}
progress={progress}
margin={'0'}
title={window.i18n('waitOneMoment')}

@ -66,8 +66,7 @@ const generateKeypair = async (
export async function signInByLinkingDevice(
mnemonic: string,
mnemonicLanguage: string,
loadingAnimationCallback: () => void,
abortSignal: AbortSignal
abortSignal?: AbortSignal
) {
if (isEmpty(mnemonic)) {
throw new Error('Session always needs a mnemonic. Either generated or given by the user');
@ -79,7 +78,6 @@ export async function signInByLinkingDevice(
const identityKeyPair = await generateKeypair(mnemonic, mnemonicLanguage);
await setSignInByLinking(true);
loadingAnimationCallback();
await createAccount(identityKeyPair);
await saveRecoveryPhrase(mnemonic);
@ -99,12 +97,13 @@ export async function signInByLinkingDevice(
* @param mnemonic The mnemonic generated on first app loading and to use for this brand new user
* @param mnemonicLanguage only 'english' is supported
* @param displayName the display name to register, character limit is MAX_NAME_LENGTH_BYTES
* @param registerCallback when restoring an account, registration completion is handled elsewhere so we need to pass the pubkey back up to the caller
*/
export async function registerSingleDevice(
generatedMnemonic: string,
mnemonicLanguage: string,
displayName: string,
restoreCallback?: (pubkey: string) => Promise<void>
registerCallback?: (pubkey: string) => Promise<void>
) {
if (isEmpty(generatedMnemonic)) {
throw new Error('Session always need a mnemonic. Either generated or given by the user');
@ -126,9 +125,8 @@ export async function registerSingleDevice(
throw new Error("We don't have a pubkey from the recovery password...");
}
if (restoreCallback) {
// when restoring an account completing the registration is handled by the RestoreAccount component
await restoreCallback(pubKeyString);
if (registerCallback) {
await registerCallback(pubKeyString);
} else {
await registrationDone(pubKeyString, displayName);
}

Loading…
Cancel
Save