feat(@desktop/keycard): rename keycard flow

Fixes: #7033
This commit is contained in:
Sale Djenic 2022-10-12 19:08:59 +02:00 committed by saledjenic
parent c1f4874e18
commit b1f8a476e8
41 changed files with 702 additions and 119 deletions

View File

@ -55,6 +55,10 @@ proc init*(self: Controller) =
let args = KeycardActivityArgs(e)
self.delegate.onKeycardUnlocked(args.keycardUid)
self.events.on(SIGNAL_KEYCARD_NAME_CHANGED) do(e: Args):
let args = KeycardActivityArgs(e)
self.delegate.onKeycardNameChanged(args.keycardUid, args.keycardNewName)
self.events.on(SIGNAL_KEYCARD_UID_UPDATED) do(e: Args):
let args = KeycardActivityArgs(e)
self.delegate.onKeycardUidUpdated(args.keycardUid, args.keycardNewUid)

View File

@ -46,7 +46,7 @@ method runDisplayKeycardContentPopup*(self: AccessInterface) {.base.} =
method runFactoryResetPopup*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method runRenameKeycardPopup*(self: AccessInterface) {.base.} =
method runRenameKeycardPopup*(self: AccessInterface, keycardUid: string, keyUid: string) {.base.} =
raise newException(ValueError, "No implementation available")
method runChangePinPopup*(self: AccessInterface) {.base.} =
@ -70,6 +70,9 @@ method onKeycardLocked*(self: AccessInterface, keycardUid: string) {.base.} =
method onKeycardUnlocked*(self: AccessInterface, keycardUid: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onKeycardNameChanged*(self: AccessInterface, keycardUid: string, keycardNewName: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onKeycardUidUpdated*(self: AccessInterface, keycardUid: string, keycardNewUid: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -123,7 +123,7 @@ method runUnlockKeycardPopupForKeycardWithUid*(self: Module, keycardUid: string)
self.createSharedKeycardModule()
if self.keycardSharedModule.isNil:
return
self.keycardSharedModule.setUidOfAKeycardWhichNeedToBeUnlocked(keycardUid)
self.keycardSharedModule.setUidOfAKeycardWhichNeedToBeProcessed(keycardUid)
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.UnlockKeycard)
method runDisplayKeycardContentPopup*(self: Module) =
@ -138,8 +138,12 @@ method runFactoryResetPopup*(self: Module) =
return
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.FactoryReset)
method runRenameKeycardPopup*(self: Module) =
info "TODO: Rename Keycard..."
method runRenameKeycardPopup*(self: Module, keycardUid: string, keyUid: string) =
self.createSharedKeycardModule()
if self.keycardSharedModule.isNil:
return
self.keycardSharedModule.setUidOfAKeycardWhichNeedToBeProcessed(keycardUid)
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.RenameKeycard, keyUid)
method runChangePinPopup*(self: Module) =
info "TODO: Change PIN for a Keycard..."
@ -187,10 +191,10 @@ proc buildKeycardList(self: Module) =
item.setImage(singletonInstance.userProfile.getIcon())
if ka.walletType == WalletTypeSeed:
item.setPairType(KeyPairType.SeedImport)
item.setIcon("wallet")
item.setIcon("keycard")
if ka.walletType == WalletTypeKey:
item.setPairType(KeyPairType.PrivateKeyImport)
item.setIcon("wallet")
item.setIcon("keycard")
item.addAccount(ka.name, ka.path, ka.address, ka.emoji, ka.color, icon = "", balance = 0.0)
items.add(item)
self.view.setKeycardItems(items)
@ -207,6 +211,10 @@ method onKeycardUnlocked*(self: Module, keycardUid: string) =
self.view.keycardModel().setLocked(keycardUid, false)
self.view.emitKeycardDetailsChangedSignal(keycardUid)
method onKeycardNameChanged*(self: Module, keycardUid: string, keycardNewName: string) =
self.view.keycardModel().setName(keycardUid, keycardNewName)
self.view.emitKeycardDetailsChangedSignal(keycardUid)
method onKeycardUidUpdated*(self: Module, keycardUid: string, keycardNewUid: string) =
self.view.keycardModel().setKeycardUid(keycardUid, keycardNewUid)
self.view.emitKeycardUidChangedSignal(keycardUid, keycardNewUid)

View File

@ -64,8 +64,8 @@ QtObject:
proc runFactoryResetPopup*(self: View) {.slot.} =
self.delegate.runFactoryResetPopup()
proc runRenameKeycardPopup*(self: View) {.slot.} =
self.delegate.runRenameKeycardPopup()
proc runRenameKeycardPopup*(self: View, keycardUid: string, keyUid: string) {.slot.} =
self.delegate.runRenameKeycardPopup(keycardUid, keyUid)
proc runChangePinPopup*(self: View) {.slot.} =
self.delegate.runChangePinPopup()

View File

@ -31,12 +31,13 @@ type
connectionKeycardResponse: UUID
tmpKeycardContainsMetadata: bool
tmpCardMetadata: CardMetadata
tmpKeycardUidForUnlocking: string
tmpKeycardUidForProcessing: string
tmpPin: string
tmpPinMatch: bool
tmpPuk: string
tmpValidPuk: bool
tmpPassword: string
tmpKeycardName: string
tmpSelectedKeyPairIsProfile: bool
tmpSelectedKeyPairDto: KeyPairDto
tmpSelectedKeyPairWalletPaths: seq[string]
@ -142,11 +143,11 @@ proc containsMetadata*(self: Controller): bool =
proc setContainsMetadata*(self: Controller, value: bool) =
self.tmpKeycardContainsMetadata = value
proc setUidOfAKeycardWhichNeedToBeUnlocked*(self: Controller, value: string) =
self.tmpKeycardUidForUnlocking = value
proc setUidOfAKeycardWhichNeedToBeProcessed*(self: Controller, value: string) =
self.tmpKeycardUidForProcessing = value
proc getUidOfAKeycardWhichNeedToBeUnlocked*(self: Controller): string =
return self.tmpKeycardUidForUnlocking
proc getUidOfAKeycardWhichNeedToBeProcessed*(self: Controller): string =
return self.tmpKeycardUidForProcessing
proc setPin*(self: Controller, value: string) =
self.tmpPin = value
@ -190,6 +191,12 @@ proc setPassword*(self: Controller, value: string) =
proc getPassword*(self: Controller): string =
return self.tmpPassword
proc setKeycarName*(self: Controller, value: string) =
self.tmpKeycardName = value
proc getKeycarName*(self: Controller): string =
return self.tmpKeycardName
proc getKeyUidWhichIsBeingAuthenticating*(self: Controller): string =
self.tmpKeyUidWhichIsBeingAuthenticating
@ -273,6 +280,9 @@ proc setMetadataFromKeycard*(self: Controller, cardMetadata: CardMetadata, updat
if updateKeyPair:
self.delegate.setKeyPairStoredOnKeycard(cardMetadata)
proc setNamePropForKeyPairStoredOnKeycard*(self: Controller, name: string) =
self.delegate.setNamePropForKeyPairStoredOnKeycard(name)
proc runSharedModuleFlow*(self: Controller, flowToRun: FlowType) =
self.delegate.runFlow(flowToRun)
@ -370,6 +380,14 @@ proc setCurrentKeycardStateToUnlocked*(self: Controller, keycardUid: string) =
if not self.walletAccountService.setKeycardUnlocked(keycardUid):
info "updating keycard unlocked state failed", keycardUid=keycardUid
proc setKeycardName*(self: Controller, keycardUid: string, keycardName: string): bool =
if not serviceApplicable(self.walletAccountService):
return false
if not self.walletAccountService.setKeycardName(keycardUid, keycardName):
info "updating keycard name failed", keycardUid=keycardUid
return false
return true
proc updateKeycardUid*(self: Controller, keycardUid: string) =
if not serviceApplicable(self.walletAccountService):
return

View File

@ -0,0 +1,20 @@
type
EnterKeycardNameState* = ref object of State
success: bool
proc newEnterKeycardNameState*(flowType: FlowType, backState: State): EnterKeycardNameState =
result = EnterKeycardNameState()
result.setup(flowType, StateType.EnterKeycardName, backState)
result.success = false
proc delete*(self: EnterKeycardNameState) =
self.State.delete
method getNextPrimaryState*(self: EnterKeycardNameState, controller: Controller): State =
if self.flowType == FlowType.RenameKeycard:
return createState(StateType.RenamingKeycard, self.flowType, nil)
method executeTertiaryCommand*(self: EnterKeycardNameState, controller: Controller) =
if self.flowType == FlowType.RenameKeycard:
controller.setPassword("")
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -15,13 +15,12 @@ method getNextPrimaryState*(self: EnterPinState, controller: Controller): State
if self.flowType == FlowType.Authentication:
if controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
if self.flowType == FlowType.DisplayKeycardContent:
controller.runSharedModuleFlow(FlowType.FactoryReset)
method executeSecondaryCommand*(self: EnterPinState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
if controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
if self.flowType == FlowType.Authentication:
@ -32,7 +31,8 @@ method executeTertiaryCommand*(self: EnterPinState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method resolveKeycardNextState*(self: EnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
@ -117,6 +117,27 @@ method resolveKeycardNextState*(self: EnterPinState, keycardFlowType: string, ke
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setMetadataFromKeycard(keycardEvent.cardMetadata, updateKeyPair = true)
return createState(StateType.PinVerified, self.flowType, nil)
if self.flowType == FlowType.RenameKeycard:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorPIN:
controller.setKeycardData($keycardEvent.pinRetries)
if keycardEvent.pinRetries > 0:
return createState(StateType.WrongPin, self.flowType, nil)
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true))
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true))
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true))
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setMetadataFromKeycard(keycardEvent.cardMetadata, updateKeyPair = true)
return createState(StateType.PinVerified, self.flowType, nil)

View File

@ -10,9 +10,16 @@ proc delete*(self: KeycardEmptyMetadataState) =
method executeTertiaryCommand*(self: KeycardEmptyMetadataState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard:
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method executePrimaryCommand*(self: KeycardEmptyMetadataState, controller: Controller) =
if self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method getNextPrimaryState*(self: KeycardEmptyMetadataState, controller: Controller): State =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard:

View File

@ -12,12 +12,14 @@ method executePrimaryCommand*(self: KeycardEmptyState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method executeTertiaryCommand*(self: KeycardEmptyState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -25,5 +25,6 @@ method executeTertiaryCommand*(self: KeycardInsertedState, controller: Controlle
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -14,9 +14,12 @@ method getNextPrimaryState*(self: KeycardMetadataDisplayState, controller: Contr
return createState(StateType.FactoryResetConfirmationDisplayMetadata, self.flowType, self)
if self.flowType == FlowType.DisplayKeycardContent:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
if self.flowType == FlowType.RenameKeycard:
return createState(StateType.EnterKeycardName, self.flowType, nil)
method executeTertiaryCommand*(self: KeycardMetadataDisplayState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -0,0 +1,17 @@
type
KeycardRenameFailureState* = ref object of State
proc newKeycardRenameFailureState*(flowType: FlowType, backState: State): KeycardRenameFailureState =
result = KeycardRenameFailureState()
result.setup(flowType, StateType.KeycardRenameFailure, backState)
proc delete*(self: KeycardRenameFailureState) =
self.State.delete
method executePrimaryCommand*(self: KeycardRenameFailureState, controller: Controller) =
if self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method executeTertiaryCommand*(self: KeycardRenameFailureState, controller: Controller) =
if self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)

View File

@ -0,0 +1,17 @@
type
KeycardRenameSuccessState* = ref object of State
proc newKeycardRenameSuccessState*(flowType: FlowType, backState: State): KeycardRenameSuccessState =
result = KeycardRenameSuccessState()
result.setup(flowType, StateType.KeycardRenameSuccess, backState)
proc delete*(self: KeycardRenameSuccessState) =
self.State.delete
method executePrimaryCommand*(self: KeycardRenameSuccessState, controller: Controller) =
if self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method executeTertiaryCommand*(self: KeycardRenameSuccessState, controller: Controller) =
if self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)

View File

@ -13,7 +13,8 @@ method getNextPrimaryState*(self: MaxPairingSlotsReachedState, controller: Contr
self.flowType == FlowType.SetupNewKeycard:
return createState(StateType.FactoryResetConfirmation, self.flowType, self)
if self.flowType == FlowType.Authentication or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.runSharedModuleFlow(FlowType.UnlockKeycard)
return nil
@ -22,5 +23,6 @@ method executeTertiaryCommand*(self: MaxPairingSlotsReachedState, controller: Co
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -10,8 +10,9 @@ proc delete*(self: MaxPinRetriesReachedState) =
method getNextPrimaryState*(self: MaxPinRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.DisplayKeycardContent:
controller.runSharedModuleFlow(FlowType.UnlockKeycard)
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.runSharedModuleFlow(FlowType.UnlockKeycard)
if self.flowType == FlowType.SetupNewKeycard:
let currValue = extractPredefinedKeycardDataToNumber(controller.getKeycardData())
if (currValue and PredefinedKeycardData.UseUnlockLabelForLockedState.int) > 0:
@ -25,7 +26,8 @@ method getNextPrimaryState*(self: MaxPinRetriesReachedState, controller: Control
method executeTertiaryCommand*(self: MaxPinRetriesReachedState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
if self.flowType == FlowType.SetupNewKeycard:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.UseUnlockLabelForLockedState, add = false))

View File

@ -13,7 +13,8 @@ method getNextPrimaryState*(self: MaxPukRetriesReachedState, controller: Control
self.flowType == FlowType.SetupNewKeycard:
return createState(StateType.FactoryResetConfirmation, self.flowType, self)
if self.flowType == FlowType.Authentication or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.runSharedModuleFlow(FlowType.UnlockKeycard)
if self.flowType == FlowType.UnlockKeycard:
return createState(StateType.EnterSeedPhrase, self.flowType, self)
@ -23,5 +24,6 @@ method executeTertiaryCommand*(self: MaxPukRetriesReachedState, controller: Cont
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -13,5 +13,6 @@ method executeTertiaryCommand*(self: NotKeycardState, controller: Controller) =
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -11,12 +11,14 @@ proc delete*(self: PinVerifiedState) =
method getNextPrimaryState*(self: PinVerifiedState, controller: Controller): State =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
return createState(StateType.KeycardMetadataDisplay, self.flowType, nil)
return nil
method executeTertiaryCommand*(self: PinVerifiedState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -18,7 +18,8 @@ method executeTertiaryCommand*(self: PluginReaderState, controller: Controller)
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method resolveKeycardNextState*(self: PluginReaderState, keycardFlowType: string, keycardEvent: KeycardEvent,

View File

@ -14,12 +14,7 @@ method executeBackCommand*(self: ReadingKeycardState, controller: Controller) =
controller.cancelCurrentFlow()
method executeTertiaryCommand*(self: ReadingKeycardState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
error "reading state must not be canceled"
method getNextSecondaryState*(self: ReadingKeycardState, controller: Controller): State =
let (flowType, flowEvent) = controller.getLastReceivedKeycardData()
@ -28,11 +23,19 @@ method getNextSecondaryState*(self: ReadingKeycardState, controller: Controller)
method resolveKeycardNextState*(self: ReadingKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
if self.flowType == FlowType.UnlockKeycard:
let ensureKeycardPresenceState = ensureReaderAndCardPresence(self, keycardFlowType, keycardEvent, controller)
if ensureKeycardPresenceState.isNil: # means the keycard is inserted
let kcUid = controller.getUidOfAKeycardWhichNeedToBeUnlocked()
if kcUid.len > 0 and kcUid != keycardEvent.instanceUID:
return createState(StateType.WrongKeycard, self.flowType, nil)
if self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.RenameKeycard:
# this part is only for the flows which are card specific (the card we're running a flow for is known in advance)
let ensureKeycardPresenceState = ensureReaderAndCardPresence(self, keycardFlowType, keycardEvent, controller)
if ensureKeycardPresenceState.isNil: # means the keycard is inserted
let nextState = ensureReaderAndCardPresenceAndResolveNextState(self, keycardFlowType, keycardEvent, controller)
if not nextState.isNil and
(nextState.stateType == StateType.KeycardEmpty or
nextState.stateType == StateType.NotKeycard or
nextState.stateType == StateType.KeycardEmptyMetadata):
return nextState
let kcUid = controller.getUidOfAKeycardWhichNeedToBeProcessed()
if kcUid.len > 0 and kcUid != keycardEvent.instanceUID:
return createState(StateType.WrongKeycard, self.flowType, nil)
# this is used in case a keycard is inserted and we jump to the first meaningful screen
return ensureReaderAndCardPresenceAndResolveNextState(self, keycardFlowType, keycardEvent, controller)

View File

@ -25,10 +25,8 @@ method getNextSecondaryState*(self: RecognizedKeycardState, controller: Controll
return createState(StateType.UnlockKeycardOptions, self.flowType, nil)
if self.flowType == FlowType.DisplayKeycardContent:
return createState(StateType.EnterPin, self.flowType, nil)
if self.flowType == FlowType.RenameKeycard:
return createState(StateType.EnterPin, self.flowType, nil)
method executeTertiaryCommand*(self: RecognizedKeycardState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.DisplayKeycardContent:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
error "recognized state must not be canceled"

View File

@ -0,0 +1,37 @@
type
RenamingKeycardState* = ref object of State
success: bool
proc newRenamingKeycardState*(flowType: FlowType, backState: State): RenamingKeycardState =
result = RenamingKeycardState()
result.setup(flowType, StateType.RenamingKeycard, backState)
result.success = false
proc delete*(self: RenamingKeycardState) =
self.State.delete
method executePrimaryCommand*(self: RenamingKeycardState, controller: Controller) =
if self.flowType == FlowType.RenameKeycard:
let md = controller.getMetadataFromKeycard()
let paths = md.walletAccounts.map(a => a.path)
self.success = controller.setKeycardName(controller.getUidOfAKeycardWhichNeedToBeProcessed(),
controller.getKeycarName())
if self.success:
controller.setNamePropForKeyPairStoredOnKeycard(controller.getKeycarName())
controller.runStoreMetadataFlow(controller.getKeycarName(), controller.getPin(), paths)
method getNextPrimaryState*(self: RenamingKeycardState, controller: Controller): State =
if self.flowType == FlowType.RenameKeycard:
if not self.success:
return createState(StateType.KeycardRenameFailure, self.flowType, nil)
method resolveKeycardNextState*(self: RenamingKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceAndResolveNextState(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.RenameKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:
return createState(StateType.KeycardRenameSuccess, self.flowType, nil)
return createState(StateType.KeycardRenameFailure, self.flowType, nil)

View File

@ -52,6 +52,10 @@ type StateType* {.pure.} = enum
EnterBiometricsPassword = "EnterBiometricsPassword"
WrongBiometricsPassword = "WrongBiometricsPassword"
BiometricsReadyToSign = "BiometricsReadyToSign"
EnterKeycardName = "EnterKeycardName"
RenamingKeycard = "RenamingKeycard"
KeycardRenameSuccess = "KeycardRenameSuccess"
KeycardRenameFailure = "KeycardRenameFailure"
## This is the base class for all state we may have in onboarding/login flow.

View File

@ -34,6 +34,7 @@ include biometrics_pin_invalid_state
include biometrics_ready_to_sign_state
include create_pin_state
include enter_biometrics_password_state
include enter_keycard_name_state
include enter_password_state
include enter_pin_state
include enter_puk_state
@ -49,6 +50,8 @@ include keycard_empty_state
include keycard_inserted_state
include keycard_metadata_display_state
include keycard_not_empty_state
include keycard_rename_failure_state
include keycard_rename_success_state
include keycard_already_unlocked_state
include max_pin_retries_reached_state
include max_puk_retries_reached_state
@ -60,6 +63,7 @@ include pin_verified_state
include plugin_reader_state
include reading_keycard_state
include recognized_keycard_state
include renaming_keycard_state
include repeat_pin_state
include seed_phrase_display_state
include seed_phrase_enter_words_state
@ -112,6 +116,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newCreatePinState(flowType, backState)
if stateToBeCreated == StateType.EnterBiometricsPassword:
return newEnterBiometricsPasswordState(flowType, backState)
if stateToBeCreated == StateType.EnterKeycardName:
return newEnterKeycardNameState(flowType, backState)
if stateToBeCreated == StateType.EnterPassword:
return newEnterPasswordState(flowType, backState)
if stateToBeCreated == StateType.EnterPin:
@ -142,6 +148,10 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newKeycardMetadataDisplayState(flowType, backState)
if stateToBeCreated == StateType.KeycardNotEmpty:
return newKeycardNotEmptyState(flowType, backState)
if stateToBeCreated == StateType.KeycardRenameFailure:
return newKeycardRenameFailureState(flowType, backState)
if stateToBeCreated == StateType.KeycardRenameSuccess:
return newKeycardRenameSuccessState(flowType, backState)
if stateToBeCreated == StateType.KeycardAlreadyUnlocked:
return newKeycardAlreadyUnlockedState(flowType, backState)
if stateToBeCreated == StateType.UnlockKeycardOptions:
@ -168,6 +178,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newReadingKeycardState(flowType, backState)
if stateToBeCreated == StateType.RecognizedKeycard:
return newRecognizedKeycardState(flowType, backState)
if stateToBeCreated == StateType.RenamingKeycard:
return newRenamingKeycardState(flowType, backState)
if stateToBeCreated == StateType.RepeatPin:
return newRepeatPinState(flowType, backState)
if stateToBeCreated == StateType.SeedPhraseDisplay:
@ -198,7 +210,8 @@ proc ensureReaderAndCardPresence*(state: State, keycardFlowType: string, keycard
if state.flowType == FlowType.FactoryReset or
state.flowType == FlowType.Authentication or
state.flowType == FlowType.UnlockKeycard or
state.flowType == FlowType.DisplayKeycardContent:
state.flowType == FlowType.DisplayKeycardContent or
state.flowType == FlowType.RenameKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
@ -401,3 +414,33 @@ proc ensureReaderAndCardPresenceAndResolveNextState*(state: State, keycardFlowTy
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNoKeys:
return createState(StateType.KeycardEmpty, state.flowType, nil)
if keycardEvent.error == ErrorNoData:
return createState(StateType.KeycardEmptyMetadata, state.flowType, nil)
if state.flowType == FlowType.RenameKeycard:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.RecognizedKeycard, state.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.UseGeneralMessageForLockedState, add = true))
return createState(StateType.MaxPinRetriesReached, state.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNotAKeycard:
return createState(StateType.NotKeycard, state.flowType, nil)
if keycardEvent.error == ErrorNoKeys:
return createState(StateType.KeycardEmpty, state.flowType, nil)
if keycardEvent.error == ErrorFreePairingSlots:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.UseGeneralMessageForLockedState, add = true))
return createState(StateType.MaxPairingSlotsReached, state.flowType, nil)
if keycardEvent.error == ErrorPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.UseGeneralMessageForLockedState, add = true))
return createState(StateType.MaxPukRetriesReached, state.flowType, nil)
if keycardFlowType == ResponseTypeValueKeycardFlowResult or
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNoKeys:
return createState(StateType.KeycardEmpty, state.flowType, nil)
if keycardEvent.error == ErrorNoData:
return createState(StateType.KeycardEmptyMetadata, state.flowType, nil)

View File

@ -9,10 +9,12 @@ proc delete*(self: WrongKeycardState) =
self.State.delete
method executePrimaryCommand*(self: WrongKeycardState, controller: Controller) =
if self.flowType == FlowType.UnlockKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
if self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method executeTertiaryCommand*(self: WrongKeycardState, controller: Controller) =
if self.flowType == FlowType.Authentication or
self.flowType == FlowType.UnlockKeycard:
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)

View File

@ -15,13 +15,15 @@ method getNextPrimaryState*(self: WrongPinState, controller: Controller): State
if self.flowType == FlowType.Authentication:
if controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
if self.flowType == FlowType.DisplayKeycardContent:
controller.runSharedModuleFlow(FlowType.FactoryReset)
if self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.runSharedModuleFlow(FlowType.FactoryReset)
method executeSecondaryCommand*(self: WrongPinState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
if controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
if self.flowType == FlowType.Authentication:
@ -32,7 +34,8 @@ method executeTertiaryCommand*(self: WrongPinState, controller: Controller) =
if self.flowType == FlowType.FactoryReset or
self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.Authentication or
self.flowType == FlowType.DisplayKeycardContent:
self.flowType == FlowType.DisplayKeycardContent or
self.flowType == FlowType.RenameKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
@ -100,6 +103,23 @@ method resolveKeycardNextState*(self: WrongPinState, keycardFlowType: string, ke
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setMetadataFromKeycard(keycardEvent.cardMetadata, updateKeyPair = true)
return createState(StateType.PinVerified, self.flowType, nil)
if self.flowType == FlowType.RenameKeycard:
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorPIN:
controller.setKeycardData($keycardEvent.pinRetries)
if keycardEvent.pinRetries > 0:
return self
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true))
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.HideKeyPair, add = true))
return createState(StateType.MaxPinRetriesReached, self.flowType, nil)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setMetadataFromKeycard(keycardEvent.cardMetadata, updateKeyPair = true)
return createState(StateType.PinVerified, self.flowType, nil)

View File

@ -57,6 +57,7 @@ type FlowType* {.pure.} = enum
Authentication = "Authentication"
UnlockKeycard = "UnlockKeycard"
DisplayKeycardContent = "DisplayKeycardContent"
RenameKeycard = "RenameKeycard"
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -91,7 +92,7 @@ method onKeycardResponse*(self: AccessInterface, keycardFlowType: string, keycar
method runFlow*(self: AccessInterface, flowToRun: FlowType, keyUid = "", bip44Path = "", txHash = "") {.base.} =
raise newException(ValueError, "No implementation available")
method setUidOfAKeycardWhichNeedToBeUnlocked*(self: AccessInterface, value: string) {.base.} =
method setUidOfAKeycardWhichNeedToBeProcessed*(self: AccessInterface, value: string) {.base.} =
raise newException(ValueError, "No implementation available")
method setPin*(self: AccessInterface, value: string) {.base.} =
@ -103,6 +104,9 @@ method setPuk*(self: AccessInterface, value: string) {.base.} =
method setPassword*(self: AccessInterface, value: string) {.base.} =
raise newException(ValueError, "No implementation available")
method setKeycarName*(self: AccessInterface, value: string) {.base.} =
raise newException(ValueError, "No implementation available")
method checkRepeatedKeycardPinWhileTyping*(self: AccessInterface, pin: string): bool {.base.} =
raise newException(ValueError, "No implementation available")
@ -124,6 +128,9 @@ method setSelectedKeyPair*(self: AccessInterface, item: KeyPairItem) {.base.} =
method setKeyPairStoredOnKeycard*(self: AccessInterface, cardMetadata: CardMetadata) {.base.} =
raise newException(ValueError, "No implementation available")
method setNamePropForKeyPairStoredOnKeycard*(self: AccessInterface, name: string) {.base.} =
raise newException(ValueError, "No implementation available")
method migratingProfileKeyPair*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -15,6 +15,7 @@ QtObject:
proc keyPairSelectedItemChanged*(self: KeyPairSelectedItem) {.signal.}
proc keyPairSelectedItemLockedChanged*(self: KeyPairSelectedItem) {.signal.}
proc keyPairSelectedItemIconChanged*(self: KeyPairSelectedItem) {.signal.}
proc keyPairSelectedItemNameChanged*(self: KeyPairSelectedItem) {.signal.}
proc setItem*(self: KeyPairSelectedItem, item: KeyPairItem) =
self.item = item
@ -56,6 +57,11 @@ QtObject:
QtProperty[string] name:
read = getName
notify = keyPairSelectedItemChanged
proc updateName*(self: KeyPairSelectedItem, name: string) =
if self.item.isNil:
return
self.item.setName(name)
self.keyPairSelectedItemNameChanged()
proc getImage*(self: KeyPairSelectedItem): string {.slot.} =
if(self.item.isNil):

View File

@ -120,6 +120,13 @@ QtObject:
let index = self.createIndex(i, 0, nil)
self.dataChanged(index, index, @[ModelRole.Locked.int])
proc setName*(self: KeycardModel, keycardUid: string, name: string) =
for i in 0 ..< self.items.len:
if(self.items[i].keycardUid == keycardUid):
self.items[i].setName(name)
let index = self.createIndex(i, 0, nil)
self.dataChanged(index, index, @[ModelRole.Name.int])
proc setKeycardUid*(self: KeycardModel, keycardUid: string, keycardNewUid: string) =
for i in 0 ..< self.items.len:
if(self.items[i].keycardUid == keycardUid):

View File

@ -66,8 +66,8 @@ method getKeycardData*[T](self: Module[T]): string =
method setKeycardData*[T](self: Module[T], value: string) =
self.view.setKeycardData(value)
method setUidOfAKeycardWhichNeedToBeUnlocked*[T](self: Module[T], value: string) =
self.controller.setUidOfAKeycardWhichNeedToBeUnlocked(value)
method setUidOfAKeycardWhichNeedToBeProcessed*[T](self: Module[T], value: string) =
self.controller.setUidOfAKeycardWhichNeedToBeProcessed(value)
method setPin*[T](self: Module[T], value: string) =
self.controller.setPin(value)
@ -78,6 +78,9 @@ method setPuk*[T](self: Module[T], value: string) =
method setPassword*[T](self: Module[T], value: string) =
self.controller.setPassword(value)
method setKeycarName*[T](self: Module[T], value: string) =
self.controller.setKeycarName(value)
method checkRepeatedKeycardPinWhileTyping*[T](self: Module[T], pin: string): bool =
self.controller.setPinMatch(false)
let storedPin = self.controller.getPin()
@ -295,13 +298,31 @@ proc prepareKeyPairItemForAuthentication[T](self: Module[T], keyUid: string) =
item = it
break
if item.name.len == 0:
error "sm_cannot find keypair among known keypairs for the given keyUid", keyUid=keyUid
error "sm_cannot find keypair among known keypairs for the given keyUid for authentication", keyUid=keyUid
item.setPubKey("")
item.setImage("")
item.setIcon("keycard")
item.setPairType(KeyPairType.Unknown)
self.view.setKeyPairForAuthentication(item)
proc prepareKeyPairForProcessing[T](self: Module[T], keyUid: string) =
var item = initKeyPairItem()
self.view.createKeyPairForProcessing()
let items = self.buildKeyPairsList(excludeAlreadyMigratedPairs = false)
for it in items:
if it.keyUid == keyUid:
item = it
break
if item.name.len == 0:
error "sm_cannot find keypair among known keypairs for the given keyUid for processing", keyUid=keyUid
let keyPairs = self.controller.getMigratedKeyPairByKeyUid(keyUid)
if keyPairs.len == 0:
error "sm_cannot find keypair among migrated keypairs for the given keyUid for processing", keyUid=keyUid
else:
item.setLocked(keyPairs[0].keycardLocked)
item.setIcon("keycard")
self.view.setKeyPairForProcessing(item)
method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Path = "", txHash = "") =
## In case of `Authentication` if we're signing a transaction we need to provide a key uid of a keypair that an account
## we want to sign a transaction for belongs to. If we're just doing an authentication for a logged in user, then
@ -348,6 +369,12 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Path
self.tmpLocalState = newReadingKeycardState(flowToRun, nil)
self.controller.runGetMetadataFlow(resolveAddress = true)
return
if flowToRun == FlowType.RenameKeycard:
self.prepareKeyPairForProcessing(keyUid)
self.view.createKeyPairStoredOnKeycard()
self.tmpLocalState = newReadingKeycardState(flowToRun, nil)
self.controller.runGetMetadataFlow(resolveAddress = true) # we're firstly displaying the keycard content
return
method setSelectedKeyPair*[T](self: Module[T], item: KeyPairItem) =
var paths: seq[string]
@ -398,6 +425,9 @@ method setKeyPairStoredOnKeycard*[T](self: Module[T], cardMetadata: CardMetadata
item.addAccount(name = "", wa.path, wa.address, emoji = "", color = self.generateRandomColor(), icon = "wallet", balance)
self.view.setKeyPairStoredOnKeycardIsKnown(knownKeyPair)
self.view.setKeyPairStoredOnKeycard(item)
method setNamePropForKeyPairStoredOnKeycard*[T](self: Module[T], name: string) =
self.view.setNamePropForKeyPairStoredOnKeycard(name)
method onUserAuthenticated*[T](self: Module[T], password: string) =
let currStateObj = self.view.currentStateObj()

View File

@ -18,6 +18,8 @@ QtObject:
keyPairStoredOnKeycardVariant: QVariant
keyPairForAuthentication: KeyPairSelectedItem
keyPairForAuthenticationVariant: QVariant
keyPairForProcessing: KeyPairSelectedItem
keyPairForProcessingVariant: QVariant
keycardData: string # used to temporary store the data coming from keycard, depends on current state different data may be stored
proc delete*(self: View) =
@ -39,6 +41,10 @@ QtObject:
self.keyPairForAuthentication.delete
if not self.keyPairForAuthenticationVariant.isNil:
self.keyPairForAuthenticationVariant.delete
if not self.keyPairForProcessing.isNil:
self.keyPairForProcessing.delete
if not self.keyPairForProcessingVariant.isNil:
self.keyPairForProcessingVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
@ -144,6 +150,10 @@ QtObject:
read = getKeyPairStoredOnKeycard
proc setKeyPairStoredOnKeycard*(self: View, item: KeyPairItem) =
self.keyPairStoredOnKeycard.setItem(item)
proc setNamePropForKeyPairStoredOnKeycard*(self: View, name: string) =
if self.keyPairStoredOnKeycard.isNil:
return
self.keyPairStoredOnKeycard.updateName(name)
proc createKeyPairForAuthentication*(self: View) =
if self.keyPairForAuthentication.isNil:
@ -164,6 +174,21 @@ QtObject:
return
self.keyPairForAuthentication.updateLockedState(locked)
proc createKeyPairForProcessing*(self: View) =
if self.keyPairForProcessing.isNil:
self.keyPairForProcessing = newKeyPairSelectedItem()
if self.keyPairForProcessingVariant.isNil:
self.keyPairForProcessingVariant = newQVariant(self.keyPairForProcessing)
proc getKeyPairForProcessing*(self: View): QVariant {.slot.} =
if self.keyPairForProcessingVariant.isNil:
return newQVariant()
return self.keyPairForProcessingVariant
QtProperty[QVariant] keyPairForProcessing:
read = getKeyPairForProcessing
proc setKeyPairForProcessing*(self: View, item: KeyPairItem) =
self.keyPairForProcessing.setItem(item)
proc setPin*(self: View, value: string) {.slot.} =
self.delegate.setPin(value)
@ -173,6 +198,9 @@ QtObject:
proc setPassword*(self: View, value: string) {.slot.} =
self.delegate.setPassword(value)
proc setKeycarName*(self: View, value: string) {.slot.} =
self.delegate.setKeycarName(value)
proc checkRepeatedKeycardPinWhileTyping*(self: View, pin: string): bool {.slot.} =
return self.delegate.checkRepeatedKeycardPinWhileTyping(pin)

View File

@ -28,6 +28,7 @@ const DefaultBIP44Path = "m/0"
const PINLengthForStatusApp* = 6
const PUKLengthForStatusApp* = 12
const CardNameLength* = 20
const SupportedMnemonicLength12* = 12
const SupportedMnemonicLength18* = 18
@ -211,9 +212,12 @@ QtObject:
self.startFlow(payload)
proc startStoreMetadataFlow*(self: Service, cardName: string, pin: string, walletPaths: seq[string]) =
var name = cardName
if cardName.len > CardNameLength:
name = cardName[0 .. CardNameLength - 1]
let payload = %* {
RequestParamPIN: pin,
RequestParamCardName: cardName,
RequestParamCardName: name,
RequestParamWalletPaths: walletPaths
}
self.currentFlow = KCSFlowType.StoreMetadata

View File

@ -36,6 +36,7 @@ const SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT* = "walletAccount/tokensRebuilt"
const SIGNAL_KEYCARD_LOCKED* = "keycardLocked"
const SIGNAL_KEYCARD_UNLOCKED* = "keycardUnlocked"
const SIGNAL_KEYCARD_UID_UPDATED* = "keycardUidUpdated"
const SIGNAL_KEYCARD_NAME_CHANGED* = "keycardNameChanged"
var
balanceCache {.threadvar.}: Table[string, float64]
@ -88,6 +89,7 @@ type TokensPerAccountArgs* = ref object of Args
type KeycardActivityArgs* = ref object of Args
keycardUid*: string
keycardNewUid*: string
keycardNewName*: string
const CheckBalanceSlotExecuteIntervalInSeconds = 15 * 60 # 15 mins
const CheckBalanceTimerIntervalInMilliseconds = 5000 # 5 sec
@ -522,10 +524,11 @@ QtObject:
proc setKeycardName*(self: Service, keycardUid: string, name: string): bool =
try:
let response = backend.setKeycardName(keycardUid, name)
return self.responseHasNoErrors("setKeycardName", response)
result = self.responseHasNoErrors("setKeycardName", response)
if result:
self.events.emit(SIGNAL_KEYCARD_NAME_CHANGED, KeycardActivityArgs(keycardUid: keycardUid, keycardNewName: name))
except Exception as e:
error "error: ", procName="setKeycardName", errName = e.name, errDesription = e.msg
return false
proc setKeycardLocked*(self: Service, keycardUid: string): bool =
try:
@ -535,7 +538,6 @@ QtObject:
self.events.emit(SIGNAL_KEYCARD_LOCKED, KeycardActivityArgs(keycardUid: keycardUid))
except Exception as e:
error "error: ", procName="setKeycardLocked", errName = e.name, errDesription = e.msg
return false
proc setKeycardUnlocked*(self: Service, keycardUid: string): bool =
try:
@ -545,7 +547,6 @@ QtObject:
self.events.emit(SIGNAL_KEYCARD_UNLOCKED, KeycardActivityArgs(keycardUid: keycardUid))
except Exception as e:
error "error: ", procName="setKeycardUnlocked", errName = e.name, errDesription = e.msg
return false
proc updateKeycardUid*(self: Service, oldKeycardUid: string, newKeycardUid: string): bool =
try:
@ -555,7 +556,6 @@ QtObject:
self.events.emit(SIGNAL_KEYCARD_UID_UPDATED, KeycardActivityArgs(keycardUid: oldKeycardUid, keycardNewUid: newKeycardUid))
except Exception as e:
error "error: ", procName="updateKeycardUid", errName = e.name, errDesription = e.msg
return false
proc deleteKeycard*(self: Service, keycardUid: string): bool =
try:

View File

@ -34,8 +34,8 @@ QtObject {
root.keycardModule.runFactoryResetPopup()
}
function runRenameKeycardPopup() {
root.keycardModule.runRenameKeycardPopup()
function runRenameKeycardPopup(keycardUid, keyUid) {
root.keycardModule.runRenameKeycardPopup(keycardUid, keyUid)
}
function runChangePinPopup() {

View File

@ -23,9 +23,11 @@ ColumnLayout {
QtObject {
id: d
property bool collapsed: true
property string keyUid: ""
function resetKeycardDetails() {
let kcItem = root.keycardStore.getKeycardDetailsAsJson(root.keycardUid)
d.keyUid = kcItem.keyUid
keycardDetails.keycardName = kcItem.name
keycardDetails.keycardLocked = kcItem.locked
keycardDetails.keyPairType = kcItem.pairType
@ -83,7 +85,7 @@ ColumnLayout {
}
]
onClicked: {
root.keycardStore.runRenameKeycardPopup()
root.keycardStore.runRenameKeycardPopup(root.keycardUid, d.keyUid)
}
}

View File

@ -58,6 +58,9 @@ StatusModal {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.displayKeycardContent) {
return qsTr("Check whats on a Keycard")
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard) {
return qsTr("Rename Keycard")
}
return ""
}
@ -67,6 +70,7 @@ StatusModal {
property bool seedPhraseRevealed: false
readonly property bool disablePopupClose: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.recognizedKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess &&
root.sharedKeycardModule.migratingProfileKeyPair())
@ -94,6 +98,9 @@ StatusModal {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.factoryResetSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardEmptyMetadata ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardEmpty ||
@ -158,6 +165,9 @@ StatusModal {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongPassword) {
return passwordComponent
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.enterKeycardName) {
return enterNameComponent
}
return undefined
}
@ -294,6 +304,21 @@ StatusModal {
}
}
}
Component {
id: enterNameComponent
EnterName {
sharedKeycardModule: root.sharedKeycardModule
Component.onCompleted: {
d.primaryButtonEnabled = false
}
onValidation: {
d.primaryButtonEnabled = result
}
}
}
}
leftButtons: [
@ -402,13 +427,30 @@ StatusModal {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPairingSlotsReached)
return qsTr("Cancel")
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.pluginReader ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.insertKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardInserted ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.recognizedKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.enterPin ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongPin ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.notKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.pinVerified ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPinRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPukRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPairingSlotsReached)
return qsTr("Cancel")
}
return ""
}
visible: text !== ""
enabled: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair) {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard) {
if (d.disablePopupClose) {
return false
}
@ -458,7 +500,8 @@ StatusModal {
visible: text !== ""
enabled: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair) {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard) {
if (d.disablePopupClose) {
return false
}
@ -629,6 +672,7 @@ StatusModal {
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.displayKeycardContent) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardEmpty ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardEmptyMetadata ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay) {
return qsTr("Done")
}
@ -644,12 +688,36 @@ StatusModal {
return qsTr("Unlock Keycard")
}
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardEmptyMetadata ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard)
return qsTr("Done")
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongPin) {
return qsTr("I dont know the PIN")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.pinVerified ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay) {
return qsTr("Next")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPinRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPukRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPairingSlotsReached) {
return qsTr("Unlock Keycard")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.enterKeycardName) {
return qsTr("Rename this Keycard")
}
}
return ""
}
visible: text !== ""
enabled: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair) {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard) {
if (d.disablePopupClose) {
return false
}
@ -704,6 +772,10 @@ StatusModal {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.repeatPin)
return false
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.enterKeycardName)
return d.primaryButtonEnabled
}
return true
}
icon.name: {

View File

@ -27,10 +27,21 @@ StatusListItem {
signal keyPairSelected()
color: Style.current.grey
color: root.keyPairCardLocked? Theme.palette.dangerColor3 : Style.current.grey
title: root.keyPairName
titleAsideText: root.keyPairType === Constants.keycard.keyPairType.profile?
Utils.getElidedCompressedPk(d.myPublicKey) : ""
statusListItemTitleAside.textFormat: Text.RichText
statusListItemTitleAside.visible: !!statusListItemTitleAside.text
statusListItemTitleAside.text: {
let t = ""
if (root.keyPairType === Constants.keycard.keyPairType.profile) {
t = Utils.getElidedCompressedPk(d.myPublicKey)
}
if (root.keyPairCardLocked) {
let label = qsTr("Keycard Locked")
t += `<font color="${Theme.palette.dangerColor1}" size="5">${label}</font>`
}
return t
}
asset {
width: root.keyPairIcon? 24 : 40

View File

@ -26,7 +26,7 @@ StatusListItem {
color: root.keycardLocked? Theme.palette.dangerColor3 : Style.current.grey
title: root.keycardName
statusListItemTitleAside.textFormat: Text.RichText
statusListItemTitleAside.visible: true
statusListItemTitleAside.visible: !!statusListItemTitleAside.text
statusListItemTitleAside.text: {
let t = ""
if (root.keyPairType === Constants.keycard.keyPairType.profile) {
@ -45,11 +45,12 @@ StatusListItem {
name: root.keyPairImage? root.keyPairImage : root.keyPairIcon
isImage: !!root.keyPairImage
color: root.keyPairType === Constants.keycard.keyPairType.profile?
Utils.colorForPubkey(d.myPublicKey) : Theme.palette.primaryColor1
Utils.colorForPubkey(d.myPublicKey) :
root.keycardLocked? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
letterSize: Math.max(4, asset.width / 2.4)
charactersLen: 2
isLetterIdenticon: !root.keyPairIcon && !asset.name.toString()
bgColor: root.keycardLocked? Theme.palette.dangerColor2 : Theme.palette.primaryColor3
bgColor: root.keycardLocked? Theme.palette.dangerColor3 : Theme.palette.primaryColor3
}
ringSettings {

View File

@ -0,0 +1,110 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import utils 1.0
import "../helpers"
Item {
id: root
property var sharedKeycardModule
signal validation(bool result)
QtObject {
id: d
property bool entryValid: false
function updateValidity() {
d.entryValid = keycardName.text.trim().length > 0 && keycardName.text !== root.sharedKeycardModule.keyPairStoredOnKeycard.name
root.validation(d.entryValid)
}
}
Component.onCompleted: {
keycardName.input.edit.forceActiveFocus()
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Style.current.xlPadding
anchors.bottomMargin: Style.current.halfPadding
anchors.leftMargin: Style.current.xlPadding
anchors.rightMargin: Style.current.xlPadding
spacing: Style.current.padding
StatusBaseText {
id: title
Layout.alignment: Qt.AlignCenter
font.weight: Font.Bold
}
StatusInput {
id: keycardName
Layout.preferredWidth: Constants.keycard.general.keycardNameInputWidth
Layout.alignment: Qt.AlignCenter
charLimit: Constants.keycard.general.keycardNameLength
placeholderText: qsTr("Keycard name")
text: root.sharedKeycardModule.keyPairStoredOnKeycard.name
input.acceptReturn: true
onTextChanged: {
d.updateValidity()
if (d.entryValid) {
root.sharedKeycardModule.setKeycarName(text)
}
}
onKeyPressed: {
if (d.entryValid &&
(input.edit.keyEvent === Qt.Key_Return ||
input.edit.keyEvent === Qt.Key_Enter)) {
event.accepted = true
root.sharedKeycardModule.currentState.doPrimaryAction()
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
StatusBaseText {
Layout.alignment: Qt.AlignLeft
text: qsTr("Preview")
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
KeyPairItem {
Layout.preferredWidth: parent.width
keyPairType: root.sharedKeycardModule.keyPairStoredOnKeycard.pairType
keyPairPubKey: root.sharedKeycardModule.keyPairStoredOnKeycard.pubKey
keyPairName: keycardName.text
keyPairIcon: root.sharedKeycardModule.keyPairStoredOnKeycard.icon
keyPairImage: root.sharedKeycardModule.keyPairStoredOnKeycard.image
keyPairDerivedFrom: root.sharedKeycardModule.keyPairStoredOnKeycard.derivedFrom
keyPairAccounts: root.sharedKeycardModule.keyPairStoredOnKeycard.accounts
}
}
states: [
State {
name: Constants.keycardSharedState.enterKeycardName
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.enterKeycardName
PropertyChanges {
target: title
text: qsTr("Rename this Keycard")
font.pixelSize: Constants.keycard.general.fontSize1
color: Theme.palette.directColor1
}
}
]
}

View File

@ -16,7 +16,8 @@ Item {
property var sharedKeycardModule
Component.onCompleted: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard) {
root.sharedKeycardModule.currentState.doPrimaryAction()
}
}
@ -88,6 +89,20 @@ Item {
}
}
Component {
id: keyPairForProcessingComponent
KeyPairItem {
keyPairType: root.sharedKeycardModule.keyPairForProcessing.pairType
keyPairPubKey: root.sharedKeycardModule.keyPairForProcessing.pubKey
keyPairName: root.sharedKeycardModule.keyPairForProcessing.name
keyPairIcon: root.sharedKeycardModule.keyPairForProcessing.icon
keyPairImage: root.sharedKeycardModule.keyPairForProcessing.image
keyPairDerivedFrom: root.sharedKeycardModule.keyPairForProcessing.derivedFrom
keyPairAccounts: root.sharedKeycardModule.keyPairForProcessing.accounts
keyPairCardLocked: root.sharedKeycardModule.keyPairForProcessing.locked
}
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Style.current.xlPadding
@ -127,7 +142,8 @@ Item {
StatusLoadingIndicator {
id: loading
visible: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard
}
StatusBaseText {
id: title
@ -187,12 +203,28 @@ Item {
return true
}
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard && !d.hideKeyPair) {
if(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.insertKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardInserted ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.recognizedKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPinRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPukRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPairingSlotsReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure)
return true
}
return false
}
sourceComponent: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.setupNewKeycard) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure) {
if (root.sharedKeycardModule.keyPairStoredOnKeycardIsKnown) {
return knownKeyPairComponent
}
@ -239,6 +271,22 @@ Item {
return unknownKeyPairCompontnt
}
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard) {
if(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure) {
return knownKeyPairComponent
}
if(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.insertKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardInserted ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.recognizedKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPinRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPukRetriesReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.maxPairingSlotsReached ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongKeycard)
return keyPairForProcessingComponent
}
return undefined
}
@ -327,11 +375,24 @@ Item {
}
},
State {
name: Constants.keycardSharedState.readingKeycard
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard
name: "processing"
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard
PropertyChanges {
target: title
text: qsTr("Reading Keycard...")
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard) {
return qsTr("Reading Keycard...")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair) {
return qsTr("Migrating key pair to Keycard")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.renamingKeycard) {
return qsTr("Renaming keycard...")
}
return ""
}
font.pixelSize: Constants.keycard.general.fontSize2
font.weight: Font.Bold
color: Theme.palette.baseColor1
@ -426,7 +487,8 @@ Item {
PropertyChanges {
target: message
text: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.authentication) {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.authentication ||
root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.renameKeycard) {
return qsTr("Keycard inserted does not match the Keycard below")
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.unlockKeycard) {
@ -659,36 +721,20 @@ Item {
}
},
State {
name: Constants.keycardSharedState.migratingKeyPair
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair
name: "processing-success"
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess
PropertyChanges {
target: title
text: qsTr("Migrating key pair to Keycard")
font.pixelSize: Constants.keycard.general.fontSize2
font.weight: Font.Bold
color: Theme.palette.baseColor1
}
PropertyChanges {
target: image
pattern: "keycard/warning/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 0
endImgIndex: 55
duration: 3000
loops: -1
}
PropertyChanges {
target: message
text: ""
}
},
State {
name: Constants.keycardSharedState.keyPairMigrateSuccess
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess
PropertyChanges {
target: title
text: qsTr("Key pair successfully migrated")
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess) {
return qsTr("Key pair successfully migrated")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameSuccess) {
return qsTr("Keycard successfully renamed")
}
return ""
}
font.pixelSize: Constants.keycard.general.fontSize1
font.weight: Font.Bold
color: Theme.palette.directColor1
@ -705,17 +751,31 @@ Item {
}
PropertyChanges {
target: message
text: qsTr("To complete migration close Status and log in with your new Keycard")
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess) {
return qsTr("To complete migration close Status and log in with your new Keycard")
}
return ""
}
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.directColor1
}
},
State {
name: Constants.keycardSharedState.keyPairMigrateFailure
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure
name: "processing-failure"
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure
PropertyChanges {
target: title
text: qsTr("Key pair failed to migrated")
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure) {
return qsTr("Key pair failed to migrated")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardRenameFailure) {
return qsTr("Keycard renaming failed")
}
return ""
}
font.pixelSize: Constants.keycard.general.fontSize1
font.weight: Font.Bold
color: Theme.palette.directColor1

View File

@ -96,6 +96,7 @@ QtObject {
readonly property string authentication: "Authentication"
readonly property string unlockKeycard: "UnlockKeycard"
readonly property string displayKeycardContent: "DisplayKeycardContent"
readonly property string renameKeycard: "RenameKeycard"
}
readonly property QtObject keycardSharedState: QtObject {
@ -145,6 +146,10 @@ QtObject {
readonly property string biometricsReadyToSign: "BiometricsReadyToSign"
readonly property string enterBiometricsPassword: "EnterBiometricsPassword"
readonly property string wrongBiometricsPassword: "WrongBiometricsPassword"
readonly property string enterKeycardName: "EnterKeycardName"
readonly property string renamingKeycard: "RenamingKeycard"
readonly property string keycardRenameSuccess: "KeycardRenameSuccess"
readonly property string keycardRenameFailure: "KeycardRenameFailure"
}
readonly property QtObject keychain: QtObject {
@ -390,6 +395,8 @@ QtObject {
readonly property int enterSeedPhraseWordsHeight: 60
readonly property int keycardPinLength: 6
readonly property int keycardPukLength: 12
readonly property int keycardNameLength: 20
readonly property int keycardNameInputWidth: 448
readonly property int keycardPukAdditionalSpacingOnEvery4Items: 4
readonly property int keycardPukAdditionalSpacing: 32
readonly property int fontSize1: 22