From 2146843e93b040720f878380fdf4e0ae570c5b98 Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Wed, 18 Jan 2023 14:15:35 +0100 Subject: [PATCH] fix(@desktop/onboarding): back button actions fixed part 1/2 --- src/app/modules/startup/controller.nim | 3 + .../internal/keycard_create_pin_state.nim | 4 - .../internal/keycard_enter_pin_state.nim | 13 +++ .../keycard_enter_seed_phrase_words_state.nim | 3 +- .../internal/keycard_repeat_pin_state.nim | 19 ++--- .../internal/keycard_wrong_pin_state.nim | 9 +++ ...actory_state_onboarding_implementation.nim | 80 +++++++++++-------- .../internal/user_profile_create_state.nim | 3 +- .../user_profile_enter_seed_phrase_state.nim | 2 +- src/app/modules/startup/module.nim | 16 ++-- .../Onboarding/views/KeysMainView.qml | 2 +- 11 files changed, 98 insertions(+), 56 deletions(-) diff --git a/src/app/modules/startup/controller.nim b/src/app/modules/startup/controller.nim index d412bf1115..13487af958 100644 --- a/src/app/modules/startup/controller.nim +++ b/src/app/modules/startup/controller.nim @@ -178,6 +178,9 @@ proc getImportedAccount*(self: Controller): GeneratedAccountDto = proc getPasswordStrengthScore*(self: Controller, password, userName: string): int = return self.generalService.getPasswordStrengthScore(password, userName) +proc clearImage*(self: Controller) = + self.tmpProfileImageDetails = ProfileImageDetails() + proc generateImage*(self: Controller, imageUrl: string, aX: int, aY: int, bX: int, bY: int): string = let formatedImg = singletonInstance.utils.formatImagePath(imageUrl) let images = self.generalService.generateImages(formatedImg, aX, aY, bX, bY) diff --git a/src/app/modules/startup/internal/keycard_create_pin_state.nim b/src/app/modules/startup/internal/keycard_create_pin_state.nim index 1b12981395..f9f80d76fb 100644 --- a/src/app/modules/startup/internal/keycard_create_pin_state.nim +++ b/src/app/modules/startup/internal/keycard_create_pin_state.nim @@ -13,10 +13,6 @@ proc delete*(self: KeycardCreatePinState) = method executeBackCommand*(self: KeycardCreatePinState, controller: Controller) = controller.setPin("") controller.setPinMatch(false) - if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys or - self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or - self.flowType == FlowType.FirstRunOldUserKeycardImport: - controller.cancelCurrentFlow() method getNextPrimaryState*(self: KeycardCreatePinState, controller: Controller): State = if not self.pinValid: diff --git a/src/app/modules/startup/internal/keycard_enter_pin_state.nim b/src/app/modules/startup/internal/keycard_enter_pin_state.nim index b3b3c41601..1f7a45d8ee 100644 --- a/src/app/modules/startup/internal/keycard_enter_pin_state.nim +++ b/src/app/modules/startup/internal/keycard_enter_pin_state.nim @@ -40,6 +40,19 @@ method resolveKeycardNextState*(self: KeycardEnterPinState, keycardFlowType: str if keycardEvent.pinRetries > 0: return createState(StateType.KeycardWrongPin, self.flowType, self.getBackState) return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState) + if keycardFlowType == ResponseTypeValueEnterPUK and + keycardEvent.error.len == 0: + if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: + return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState) + if keycardFlowType == ResponseTypeValueSwapCard and + keycardEvent.error.len > 0 and + keycardEvent.error == RequestParamPUKRetries: + controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true)) + return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState) + if keycardFlowType == ResponseTypeValueSwapCard and + keycardEvent.error.len > 0 and + keycardEvent.error == RequestParamFreeSlots: + return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState) if keycardFlowType == ResponseTypeValueKeycardFlowResult: controller.setKeycardEvent(keycardEvent) if not defined(macosx): diff --git a/src/app/modules/startup/internal/keycard_enter_seed_phrase_words_state.nim b/src/app/modules/startup/internal/keycard_enter_seed_phrase_words_state.nim index 0caf03747a..845d262bde 100644 --- a/src/app/modules/startup/internal/keycard_enter_seed_phrase_words_state.nim +++ b/src/app/modules/startup/internal/keycard_enter_seed_phrase_words_state.nim @@ -24,4 +24,5 @@ method resolveKeycardNextState*(self: KeycardEnterSeedPhraseWordsState, keycardF if keycardFlowType == ResponseTypeValueKeycardFlowResult and keycardEvent.keyUid.len > 0: controller.setKeyUid(keycardEvent.keyUid) - return createState(StateType.UserProfileCreate, self.flowType, self) \ No newline at end of file + let backState = findBackStateWithTargetedStateType(self, StateType.WelcomeNewStatusUser) + return createState(StateType.UserProfileCreate, self.flowType, backState) \ No newline at end of file diff --git a/src/app/modules/startup/internal/keycard_repeat_pin_state.nim b/src/app/modules/startup/internal/keycard_repeat_pin_state.nim index c315ed1675..a29066ccac 100644 --- a/src/app/modules/startup/internal/keycard_repeat_pin_state.nim +++ b/src/app/modules/startup/internal/keycard_repeat_pin_state.nim @@ -40,16 +40,17 @@ method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: st if keycardFlowType == ResponseTypeValueKeycardFlowResult and keycardEvent.keyUid.len > 0: controller.setKeyUid(keycardEvent.keyUid) - return createState(StateType.KeycardPinSet, self.flowType, self.getBackState) + let backState = findBackStateWithTargetedStateType(self, StateType.UserProfileImportSeedPhrase) + return createState(StateType.KeycardPinSet, self.flowType, backState) if self.flowType == FlowType.FirstRunOldUserKeycardImport: - if keycardFlowType == ResponseTypeValueEnterPUK and - keycardEvent.error.len > 0 and - keycardEvent.error == RequestParamPUK: - controller.setRemainingAttempts(keycardEvent.pukRetries) - controller.setPukValid(false) - if keycardEvent.pukRetries > 0: - return createState(StateType.KeycardPinSet, self.flowType, self.getBackState) - return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState) + if keycardFlowType == ResponseTypeValueEnterPUK: + if keycardEvent.error.len > 0 and + keycardEvent.error == RequestParamPUK: + controller.setRemainingAttempts(keycardEvent.pukRetries) + controller.setPukValid(false) + if keycardEvent.pukRetries > 0: + return createState(StateType.KeycardPinSet, self.flowType, self.getBackState) + return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState) if keycardFlowType == ResponseTypeValueKeycardFlowResult: controller.setKeycardEvent(keycardEvent) controller.setPukValid(true) diff --git a/src/app/modules/startup/internal/keycard_wrong_pin_state.nim b/src/app/modules/startup/internal/keycard_wrong_pin_state.nim index 6d9d7b412a..f3bb582b8b 100644 --- a/src/app/modules/startup/internal/keycard_wrong_pin_state.nim +++ b/src/app/modules/startup/internal/keycard_wrong_pin_state.nim @@ -36,6 +36,15 @@ method resolveKeycardNextState*(self: KeycardWrongPinState, keycardFlowType: str if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState) return nil + if keycardFlowType == ResponseTypeValueSwapCard and + keycardEvent.error.len > 0 and + keycardEvent.error == RequestParamPUKRetries: + controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true)) + return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState) + if keycardFlowType == ResponseTypeValueSwapCard and + keycardEvent.error.len > 0 and + keycardEvent.error == RequestParamFreeSlots: + return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState) if keycardFlowType == ResponseTypeValueKeycardFlowResult: controller.setKeycardEvent(keycardEvent) if not defined(macosx): diff --git a/src/app/modules/startup/internal/state_factory_state_onboarding_implementation.nim b/src/app/modules/startup/internal/state_factory_state_onboarding_implementation.nim index 713845c4aa..a7414e6600 100644 --- a/src/app/modules/startup/internal/state_factory_state_onboarding_implementation.nim +++ b/src/app/modules/startup/internal/state_factory_state_onboarding_implementation.nim @@ -1,11 +1,18 @@ proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State = + var defaultBackState = state + if state.flowType == FlowType.FirstRunNewUserNewKeycardKeys and + state.stateType == StateType.KeycardEmpty: + ## `KeycardEmpty` state is known in the context of `FirstRunNewUserNewKeycardKeys` only if we jump to it from + ## `FirstRunOldUserKeycardImport` flow, in that case we need to set back state appropriatelly respecting different flow. + defaultBackState = state.getBackState + if keycardFlowType == ResponseTypeValueKeycardFlowResult and keycardEvent.error.len > 0 and keycardEvent.error == ErrorConnection: controller.resumeCurrentFlowLater() if state.stateType == StateType.KeycardPluginReader: return nil - return createState(StateType.KeycardPluginReader, state.flowType, state) + return createState(StateType.KeycardPluginReader, state.flowType, defaultBackState) if keycardFlowType == ResponseTypeValueInsertCard and keycardEvent.error.len > 0 and keycardEvent.error == ErrorConnection: @@ -13,12 +20,12 @@ proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: strin return nil if state.stateType == StateType.KeycardPluginReader: return createState(StateType.KeycardInsertKeycard, state.flowType, state.getBackState) - return createState(StateType.KeycardInsertKeycard, state.flowType, state) + return createState(StateType.KeycardInsertKeycard, state.flowType, defaultBackState) if keycardFlowType == ResponseTypeValueCardInserted: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = false)) if state.stateType == StateType.KeycardInsertKeycard: return createState(StateType.KeycardInsertedKeycard, state.flowType, state.getBackState) - return createState(StateType.KeycardInsertedKeycard, state.flowType, state) + return createState(StateType.KeycardInsertedKeycard, state.flowType, defaultBackState) proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State = let ensureState = ensureReaderAndCardPresenceOnboarding(state, keycardFlowType, keycardEvent, controller) @@ -26,89 +33,98 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key return ensureState if state.flowType == FlowType.FirstRunNewUserNewKeycardKeys: + var backState = state.getBackState + if state.stateType == StateType.WelcomeNewStatusUser: + backState = state + + if state.stateType == StateType.KeycardEmpty: + ## `KeycardEmpty` state is known in the context of `FirstRunNewUserNewKeycardKeys` only if we jump to it from + ## `FirstRunOldUserKeycardImport` flow, in that case we need to set back state appropriatelly respecting different flow. + backState = state.getBackState + if keycardFlowType == ResponseTypeValueEnterNewPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorRequireInit: - return createState(StateType.KeycardRecognizedKeycard, state.flowType, state.getBackState) + return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState) if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len == 0: - return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState) + return createState(StateType.KeycardNotEmpty, state.flowType, backState) if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: - return createState(StateType.KeycardLocked, state.flowType, state.getBackState) + return createState(StateType.KeycardLocked, state.flowType, backState) if keycardFlowType == ResponseTypeValueSwapCard and keycardEvent.error.len > 0: if keycardEvent.error == ErrorNotAKeycard: - return createState(StateType.KeycardNotKeycard, state.flowType, state.getBackState) + return createState(StateType.KeycardNotKeycard, state.flowType, backState) if keycardEvent.error == RequestParamFreeSlots: - return createState(StateType.KeycardLocked, state.flowType, state.getBackState) + return createState(StateType.KeycardLocked, state.flowType, backState) if keycardEvent.error == RequestParamPUKRetries: - return createState(StateType.KeycardLocked, state.flowType, state.getBackState) + return createState(StateType.KeycardLocked, state.flowType, backState) if keycardEvent.error == ErrorHasKeys: - return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState) + return createState(StateType.KeycardNotEmpty, state.flowType, backState) if keycardFlowType == ResponseTypeValueEnterMnemonic and keycardEvent.error.len > 0 and keycardEvent.error == ErrorLoadingKeys: controller.buildSeedPhrasesFromIndexes(keycardEvent.seedPhraseIndexes) - return createState(StateType.KeycardPinSet, state.flowType, state.getBackState) - if keycardFlowType == ResponseTypeValueKeycardFlowResult and - keycardEvent.keyUid.len > 0: - controller.setKeyUid(keycardEvent.keyUid) - return createState(StateType.UserProfileCreate, state.flowType, state) + return createState(StateType.KeycardPinSet, state.flowType, backState) if state.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard: + var backState = state.getBackState + if state.stateType == StateType.UserProfileImportSeedPhrase: + backState = state + if keycardFlowType == ResponseTypeValueEnterNewPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorRequireInit: if state.stateType == StateType.UserProfileEnterSeedPhrase: - return createState(StateType.KeycardCreatePin, state.flowType, state.getBackState) - return createState(StateType.KeycardRecognizedKeycard, state.flowType, state.getBackState) + return createState(StateType.KeycardCreatePin, state.flowType, backState) + return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState) if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len == 0: - return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState) + return createState(StateType.KeycardNotEmpty, state.flowType, backState) if keycardFlowType == ResponseTypeValueSwapCard and keycardEvent.error.len > 0: if keycardEvent.error == ErrorNotAKeycard: - return createState(StateType.KeycardNotKeycard, state.flowType, state.getBackState) + return createState(StateType.KeycardNotKeycard, state.flowType, backState) if keycardEvent.error == RequestParamFreeSlots: - return createState(StateType.KeycardLocked, state.flowType, state.getBackState) + return createState(StateType.KeycardLocked, state.flowType, backState) if keycardEvent.error == RequestParamPUKRetries: - return createState(StateType.KeycardLocked, state.flowType, state.getBackState) + return createState(StateType.KeycardLocked, state.flowType, backState) if keycardEvent.error == ErrorHasKeys: - return createState(StateType.KeycardNotEmpty, state.flowType, state.getBackState) - if keycardFlowType == ResponseTypeValueKeycardFlowResult and - keycardEvent.keyUid.len > 0: - controller.setKeyUid(keycardEvent.keyUid) - return createState(StateType.KeycardPinSet, state.flowType, state.getBackState) + return createState(StateType.KeycardNotEmpty, state.flowType, backState) if state.flowType == FlowType.FirstRunOldUserKeycardImport: + var backState = state.getBackState + if state.stateType == StateType.RecoverOldUser: + backState = state + controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = false)) controller.setKeyUid(keycardEvent.keyUid) if keycardFlowType == ResponseTypeValueEnterPIN and keycardEvent.error.len == 0: - return createState(StateType.KeycardRecognizedKeycard, state.flowType, state.getBackState) + return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState) if keycardFlowType == ResponseTypeValueEnterPUK and keycardEvent.error.len == 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: - return createState(StateType.KeycardMaxPinRetriesReached, state.flowType, state.getBackState) + return createState(StateType.KeycardMaxPinRetriesReached, state.flowType, backState) if keycardFlowType == ResponseTypeValueSwapCard and keycardEvent.error.len > 0 and keycardEvent.error == ErrorNoKeys: - return createState(StateType.KeycardEmpty, state.flowType, nil) + return createState(StateType.KeycardEmpty, state.flowType, backState) if keycardFlowType == ResponseTypeValueSwapCard and keycardEvent.error.len > 0 and keycardEvent.error == RequestParamPUKRetries: controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true)) - return createState(StateType.KeycardMaxPukRetriesReached, state.flowType, state.getBackState) + return createState(StateType.KeycardMaxPukRetriesReached, state.flowType, backState) if keycardFlowType == ResponseTypeValueSwapCard and keycardEvent.error.len > 0 and keycardEvent.error == RequestParamFreeSlots: - return createState(StateType.KeycardMaxPairingSlotsReached, state.flowType, state.getBackState) + return createState(StateType.KeycardMaxPairingSlotsReached, state.flowType, backState) if keycardFlowType == ResponseTypeValueEnterNewPIN and keycardEvent.error.len > 0 and keycardEvent.error == ErrorRequireInit: - return createState(StateType.KeycardCreatePin, state.flowType, nil) + return createState(StateType.KeycardCreatePin, state.flowType, backState) if state.flowType == FlowType.AppLogin: if keycardFlowType == ResponseTypeValueSwapCard and diff --git a/src/app/modules/startup/internal/user_profile_create_state.nim b/src/app/modules/startup/internal/user_profile_create_state.nim index 5ebff0546d..213ba20d39 100644 --- a/src/app/modules/startup/internal/user_profile_create_state.nim +++ b/src/app/modules/startup/internal/user_profile_create_state.nim @@ -20,4 +20,5 @@ method getNextPrimaryState*(self: UserProfileCreateState, controller: Controller return createState(StateType.UserProfileChatKey, self.flowType, self) method executeBackCommand*(self: UserProfileCreateState, controller: Controller) = - controller.setDisplayName("") \ No newline at end of file + controller.setDisplayName("") + controller.clearImage() \ No newline at end of file diff --git a/src/app/modules/startup/internal/user_profile_enter_seed_phrase_state.nim b/src/app/modules/startup/internal/user_profile_enter_seed_phrase_state.nim index 3cec9c6780..b2ed4a7366 100644 --- a/src/app/modules/startup/internal/user_profile_enter_seed_phrase_state.nim +++ b/src/app/modules/startup/internal/user_profile_enter_seed_phrase_state.nim @@ -23,7 +23,7 @@ method getNextPrimaryState*(self: UserProfileEnterSeedPhraseState, controller: C return createState(StateType.UserProfileCreate, self.flowType, self) if self.flowType == FlowType.FirstRunOldUserKeycardImport: if not self.enteredMnemonicMatchTargetedKeyUid: - return createState(StateType.KeycardWrongKeycard, self.flowType, nil) + return createState(StateType.KeycardWrongKeycard, self.flowType, self) if self.flowType == FlowType.FirstRunOldUserImportSeedPhrase: return createState(StateType.UserProfileCreatePassword, self.flowType, self) diff --git a/src/app/modules/startup/module.nim b/src/app/modules/startup/module.nim index a694a59d14..2d8dd288ee 100644 --- a/src/app/modules/startup/module.nim +++ b/src/app/modules/startup/module.nim @@ -458,13 +458,15 @@ method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurr if currStateObj.isNil: error "cannot resolve current state for onboarding/login flow continuation" return - if currStateObj.flowType() == FlowType.LostKeycardReplacement: - let newState = currStateObj.getBackState() - if newState.isNil: - error "cannot resolve new state for onboarding/login flow continuation after shared flow is terminated" - return - self.view.setCurrentStartupState(newState) - debug "new state for onboarding/login flow continuation after shared flow is terminated", setCurrFlow=newState.flowType(), newCurrState=newState.stateType() + if currStateObj.flowType() == FlowType.FirstRunNewUserNewKeycardKeys or + currStateObj.flowType() == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard or + currStateObj.flowType() == FlowType.LostKeycardReplacement: + let newState = currStateObj.getBackState() + if newState.isNil: + error "cannot resolve new state for onboarding/login flow continuation after shared flow is terminated" + return + self.view.setCurrentStartupState(newState) + debug "new state for onboarding/login flow continuation after shared flow is terminated", setCurrFlow=newState.flowType(), newCurrState=newState.stateType() method storeKeyPairForNewKeycardUser*[T](self: Module[T]) = self.delegate.storeKeyPairForNewKeycardUser() diff --git a/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml b/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml index 5952bf2f37..4f7807d131 100644 --- a/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml +++ b/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml @@ -403,7 +403,7 @@ Item { } PropertyChanges { target: txtDesc - text: qsTr("Seed phrases are used to back up and restore your keys. Only use this option if you already have a seed phrase.") + text: qsTr("Seed phrases are used to back up and restore your keys.\nOnly use this option if you already have a seed phrase.") height: Constants.onboarding.loginInfoHeight2 } PropertyChanges {