From ced5a9bb4b63f3f63896d1353d17bfc676aee7ce Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Mon, 8 Apr 2024 09:40:49 +0200 Subject: [PATCH] feat(keycard): noticeable delay in starting flows This is not an issue actually, instead a request was if the Keycard is present to display an appropriate state based on the Keycard content, which requires the following steps when a user clicks any flow to run: - run appropriate keycard flow - wait for a response from the keycard - resolving state that needs to be displayed based on the response - display appropriate state This commit changes that to the following: - display keycard reading state immediately after the user clicks any flow to run and then the rest as it was - run appropriate keycard flow - wait for a response from the keycard - resolving state that needs to be displayed based on the response - display appropriate state With this change on OS' where communication between the app and keycard is slow it wouldn't look like a delay in running flow, but instead, a user will be aware immediately that something is ongoing. Closes #13242 --- .../shared_modules/keycard_popup/module.nim | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/app/modules/shared_modules/keycard_popup/module.nim b/src/app/modules/shared_modules/keycard_popup/module.nim index d86e74b96b..1dca7fb198 100644 --- a/src/app/modules/shared_modules/keycard_popup/module.nim +++ b/src/app/modules/shared_modules/keycard_popup/module.nim @@ -433,14 +433,14 @@ method onKeycardResponse*[T](self: Module[T], keycardFlowType: string, keycardEv ## Check local state first, in case postponed flow is run if not self.tmpLocalState.isNil: let nextState = self.tmpLocalState.resolveKeycardNextState(keycardFlowType, keycardEvent, self.controller) - defer: self.tmpLocalState.delete - defer: self.tmpLocalState = nil + defer: + self.tmpLocalState.delete + self.tmpLocalState = nil if nextState.isNil: return self.preStateActivities(nextState.flowType(), nextState.stateType()) self.reEvaluateKeyPairForProcessing(self.tmpLocalState.flowType(), self.tmpLocalState.stateType()) self.view.setCurrentState(nextState) - self.controller.readyToDisplayPopup() debug "sm_on_keycard_response - from_local - set state", setCurrFlow=nextState.flowType(), setCurrState=nextState.stateType() return ## Check regular flows @@ -497,6 +497,12 @@ method prepareKeyPairForProcessing*[T](self: Module[T], keyUid: string, keycardU item.setIcon("keycard") self.view.setKeyPairForProcessing(item) +proc displayReadingState[T](self: Module[T], flowType: FlowType, backState: State) = + self.tmpLocalState = newReadingKeycardState(flowType, backState) + self.view.setCurrentState(self.tmpLocalState) + self.controller.readyToDisplayPopup() + debug "sm_cannot - display reading state", setCurrFlow=self.tmpLocalState.flowType(), setCurrState=self.tmpLocalState.stateType() + method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths: seq[string] = @[], txHash = "", forceFlow = false, returnToFlow = FlowType.General) = ## In case of `Authentication` or `Sign` flow, if keyUid is provided, that keypair will be authenticated, ## otherwise the logged in profile will be authenticated. @@ -519,7 +525,7 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, if flowToRun == FlowType.FactoryReset: if keyUid.len > 0: self.prepareKeyPairForProcessing(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runGetMetadataFlow(resolveAddress = true) return if flowToRun == FlowType.SetupNewKeycard: @@ -536,7 +542,7 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false) return self.setSelectedKeyPair(filteredItems[0]) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runLoadAccountFlow() return if flowToRun == FlowType.Authentication: @@ -544,7 +550,7 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, if keyUid.len == 0 or keyUid == singletonInstance.userProfile.getKeyUid(): if singletonInstance.userProfile.getIsKeycardUser(): self.prepareKeyPairItemForAuthentication(singletonInstance.userProfile.getKeyUid()) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runAuthenticationFlow(singletonInstance.userProfile.getKeyUid(), bip44Paths) if singletonInstance.userProfile.getUsingBiometricLogin(): self.controller.connectKeychainSignals() @@ -552,7 +558,7 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, return self.view.setCurrentState(newEnterPasswordState(flowToRun, nil)) if singletonInstance.userProfile.getUsingBiometricLogin(): - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.connectKeychainSignals() self.controller.tryToObtainDataFromKeychain() else: @@ -561,7 +567,7 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, return else: self.prepareKeyPairItemForAuthentication(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runAuthenticationFlow(keyUid, bip44Paths) return if flowToRun == FlowType.Sign: @@ -587,7 +593,7 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, return self.runningFlow = flowToRun self.prepareKeyPairItemForAuthentication(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runSignFlow(keyUid, bip44Paths[0], txHash) if finalKeyUid == singletonInstance.userProfile.getKeyUid() and singletonInstance.userProfile.getUsingBiometricLogin(): @@ -598,48 +604,48 @@ proc proceedWithRunFlow[T](self: Module[T], flowToRun: FlowType, keyUid: string, ## since we can run unlock keycard flow from an already running flow, in order to avoid changing displayed keypair ## (locked keypair) we have to set keycard uid of a keycard used in the flow we're jumping from to `UnlockKeycard` flow. self.prepareKeyPairForProcessing(keyUid, self.controller.getKeycardUid()) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runGetMetadataFlow(resolveAddress = true) return if flowToRun == FlowType.DisplayKeycardContent: - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runGetMetadataFlow(resolveAddress = true) return if flowToRun == FlowType.RenameKeycard: self.prepareKeyPairForProcessing(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runGetMetadataFlow(resolveAddress = true) # we're firstly displaying the keycard content return if flowToRun == FlowType.ChangeKeycardPin: self.prepareKeyPairForProcessing(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runChangePinFlow() return if flowToRun == FlowType.ChangeKeycardPuk: self.prepareKeyPairForProcessing(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runChangePukFlow() return if flowToRun == FlowType.ChangePairingCode: self.prepareKeyPairForProcessing(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runChangePairingFlow() return if flowToRun == FlowType.CreateCopyOfAKeycard: self.prepareKeyPairForProcessing(keyUid) - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runGetMetadataFlow(resolveAddress = true) return if flowToRun == FlowType.SetupNewKeycardNewSeedPhrase: - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runLoadAccountFlow() return if flowToRun == FlowType.SetupNewKeycardOldSeedPhrase: - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runLoadAccountFlow() return if flowToRun == FlowType.ImportFromKeycard: - self.tmpLocalState = newReadingKeycardState(flowToRun, nil) + self.displayReadingState(flowToRun, nil) self.controller.runGetMetadataFlow(resolveAddress = true, exportMasterAddr = true) return if flowToRun == FlowType.MigrateFromKeycardToApp: