fix(@desktop/keycard): login flow

Onboarding flow updated according to the latest related
figma changes.
This commit is contained in:
Sale Djenic 2022-09-30 21:16:15 +02:00 committed by saledjenic
parent 2a019f330a
commit 0cb23e0f16
25 changed files with 679 additions and 293 deletions

View File

@ -36,6 +36,7 @@ type
profileService: profile_service.Service
keycardService: keycard_service.Service
connectionIds: seq[UUID]
keychainConnectionIds: seq[UUID]
tmpProfileImageDetails: ProfileImageDetails
tmpDisplayName: string
tmpPassword: string
@ -70,14 +71,32 @@ proc newController*(delegate: io_interface.AccessInterface,
result.keycardService = keycardService
result.tmpPinMatch = false
result.tmpSeedPhraseLength = 0
result.tmpKeychainErrorOccurred = true
result.tmpKeychainErrorOccurred = false
result.tmpRecoverUsingSeedPhraseWhileLogin = false
result.tmpSelectedLoginAccountIsKeycardAccount = false
# Forward declaration
proc cleanTmpData*(self: Controller)
proc disconnectKeychain*(self: Controller) =
for id in self.keychainConnectionIds:
self.events.disconnect(id)
self.keychainConnectionIds = @[]
proc connectKeychain*(self: Controller) =
var handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_SUCCESS) do(e:Args):
let args = KeyChainServiceArg(e)
self.delegate.emitObtainingPasswordSuccess(args.data)
self.keychainConnectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_ERROR) do(e:Args):
let args = KeyChainServiceArg(e)
self.tmpKeychainErrorOccurred = true
self.delegate.emitObtainingPasswordError(args.errDescription, args.errType)
self.keychainConnectionIds.add(handlerId)
proc disconnect*(self: Controller) =
self.disconnectKeychain()
for id in self.connectionIds:
self.events.disconnect(id)
@ -85,6 +104,8 @@ proc delete*(self: Controller) =
self.disconnect()
proc init*(self: Controller) =
self.connectKeychain()
var handlerId = self.events.onWithUUID(SignalType.NodeLogin.event) do(e:Args):
let signal = NodeSignal(e)
self.delegate.onNodeLogin(signal.event.error)
@ -101,17 +122,6 @@ proc init*(self: Controller) =
self.events.emit("nodeReady", Args())
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_SUCCESS) do(e:Args):
let args = KeyChainServiceArg(e)
self.delegate.emitObtainingPasswordSuccess(args.data)
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_KEYCHAIN_SERVICE_ERROR) do(e:Args):
let args = KeyChainServiceArg(e)
self.tmpKeychainErrorOccurred = true
self.delegate.emitObtainingPasswordError(args.errDescription, args.errType)
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
let args = KeycardArgs(e)
self.delegate.onKeycardResponse(args.flowType, args.flowEvent)
@ -234,7 +244,7 @@ proc cleanTmpData*(self: Controller) =
self.tmpSelectedLoginAccountKeyUid = ""
self.tmpSelectedLoginAccountIsKeycardAccount = false
self.tmpProfileImageDetails = ProfileImageDetails()
self.tmpKeychainErrorOccurred = true
self.tmpKeychainErrorOccurred = false
self.setDisplayName("")
self.setPassword("")
self.setDefaultWalletEmoji("")
@ -273,7 +283,7 @@ proc validMnemonic*(self: Controller, mnemonic: string): bool =
return true
return false
proc importMnemonic(self: Controller): bool =
proc importMnemonic*(self: Controller): bool =
let error = self.accountsService.importMnemonic(self.tmpSeedPhrase)
if(error.len == 0):
self.delegate.importAccountSuccess()

View File

@ -8,17 +8,22 @@ proc newLoginKeycardEmptyState*(flowType: FlowType, backState: State): LoginKeyc
proc delete*(self: LoginKeycardEmptyState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardEmptyState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
controller.runLoadAccountFlow(seedPhraseLength = 0, seedPhrase = "", puk = "", factoryReset = true)
method getNextSecondaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
let newState = createState(StateType.WelcomeNewStatusUser, self.flowType, self)
newState.executeSecondaryCommand(controller)
return newState
method getNextTertiaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardEmptyState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -0,0 +1,24 @@
type
LoginKeycardEnterPasswordState* = ref object of State
proc newLoginKeycardEnterPasswordState*(flowType: FlowType, backState: State): LoginKeycardEnterPasswordState =
result = LoginKeycardEnterPasswordState()
result.setup(flowType, StateType.LoginKeycardEnterPassword, backState)
proc delete*(self: LoginKeycardEnterPasswordState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardEnterPasswordState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
method getNextTertiaryState*(self: LoginKeycardEnterPasswordState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardEnterPasswordState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)

View File

@ -10,18 +10,19 @@ proc delete*(self: LoginKeycardEnterPinState) =
method executePrimaryCommand*(self: LoginKeycardEnterPinState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextSecondaryState*(self: LoginKeycardEnterPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
if controller.isSelectedLoginAccountKeycardAccount() and
controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextTertiaryState*(self: LoginKeycardEnterPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardEnterPinState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardEnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
@ -32,8 +33,7 @@ method resolveKeycardNextState*(self: LoginKeycardEnterPinState, keycardFlowType
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:
controller.setKeycardEvent(keycardEvent)
controller.loginAccountKeycard()
return nil
return createState(StateType.LoginKeycardPinVerified, self.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPIN:

View File

@ -8,24 +8,15 @@ proc newLoginKeycardInsertKeycardState*(flowType: FlowType, backState: State): L
proc delete*(self: LoginKeycardInsertKeycardState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardInsertKeycardState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
if controller.keychainErrorOccurred() or controller.getPin().len != PINLengthForStatusApp:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardInsertKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
@ -39,5 +30,5 @@ method resolveKeycardNextState*(self: LoginKeycardInsertKeycardState, keycardFlo
return nil
if keycardFlowType == ResponseTypeValueCardInserted:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = false))
return createState(StateType.LoginKeycardReadingKeycard, self.flowType, nil)
return createState(StateType.LoginKeycardInsertedKeycard, self.flowType, nil)
return nil

View File

@ -0,0 +1,13 @@
type
LoginKeycardInsertedKeycardState* = ref object of State
proc newLoginKeycardInsertedKeycardState*(flowType: FlowType, backState: State): LoginKeycardInsertedKeycardState =
result = LoginKeycardInsertedKeycardState()
result.setup(flowType, StateType.LoginKeycardInsertedKeycard, backState)
proc delete*(self: LoginKeycardInsertedKeycardState) =
self.State.delete
method getNextPrimaryState*(self: LoginKeycardInsertedKeycardState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
return createState(StateType.LoginKeycardReadingKeycard, self.flowType, nil)

View File

@ -0,0 +1,32 @@
type
LoginKeycardMaxPairingSlotsReachedState* = ref object of State
proc newLoginKeycardMaxPairingSlotsReachedState*(flowType: FlowType, backState: State): LoginKeycardMaxPairingSlotsReachedState =
result = LoginKeycardMaxPairingSlotsReachedState()
result.setup(flowType, StateType.LoginKeycardMaxPairingSlotsReached, backState)
proc delete*(self: LoginKeycardMaxPairingSlotsReachedState) =
self.State.delete
method executeBackCommand*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller) =
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
controller.runLoginFlow()
method getNextPrimaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(true)
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, nil)
method getNextTertiaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardMaxPairingSlotsReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -13,15 +13,18 @@ method executeBackCommand*(self: LoginKeycardMaxPinRetriesReachedState, controll
controller.runLoginFlow()
method getNextPrimaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
return createState(StateType.KeycardRecover, self.flowType, self)
method getNextSecondaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
return createState(StateType.KeycardRecover, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardMaxPinRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -8,11 +8,25 @@ proc newLoginKeycardMaxPukRetriesReachedState*(flowType: FlowType, backState: St
proc delete*(self: LoginKeycardMaxPukRetriesReachedState) =
self.State.delete
method executeBackCommand*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller) =
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
controller.runLoginFlow()
method getNextPrimaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(true)
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, nil)
method getNextTertiaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardMaxPukRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -0,0 +1,13 @@
type
LoginKeycardPinVerifiedState* = ref object of State
proc newLoginKeycardPinVerifiedState*(flowType: FlowType, backState: State): LoginKeycardPinVerifiedState =
result = LoginKeycardPinVerifiedState()
result.setup(flowType, StateType.LoginKeycardPinVerified, backState)
proc delete*(self: LoginKeycardPinVerifiedState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardPinVerifiedState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
controller.loginAccountKeycard()

View File

@ -10,25 +10,12 @@ proc newLoginKeycardReadingKeycardState*(flowType: FlowType, backState: State):
proc delete*(self: LoginKeycardReadingKeycardState) =
self.State.delete
method executePrimaryCommand*(self: LoginKeycardReadingKeycardState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =
if controller.keychainErrorOccurred() or controller.getPin().len != PINLengthForStatusApp:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
let (flowType, flowEvent) = controller.getLastReceivedKeycardData()
# this is used in case a keycard is not inserted in the moment when flow is run (we're animating an insertion)
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, flowType, flowEvent, controller)
method resolveKeycardNextState*(self: LoginKeycardReadingKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
# this is used in case a keycard is inserted and we jump to the first meaningful screen
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -0,0 +1,17 @@
type
LoginKeycardRecognizedKeycardState* = ref object of State
proc newLoginKeycardRecognizedKeycardState*(flowType: FlowType, backState: State): LoginKeycardRecognizedKeycardState =
result = LoginKeycardRecognizedKeycardState()
result.setup(flowType, StateType.LoginKeycardRecognizedKeycard, backState)
proc delete*(self: LoginKeycardRecognizedKeycardState) =
self.State.delete
method getNextPrimaryState*(self: LoginKeycardRecognizedKeycardState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
if value == LS_VALUE_STORE:
controller.tryToObtainDataFromKeychain()
return createState(StateType.Login, self.flowType, nil)
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)

View File

@ -10,22 +10,19 @@ proc delete*(self: LoginKeycardWrongKeycardState) =
method executePrimaryCommand*(self: LoginKeycardWrongKeycardState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
if controller.keychainErrorOccurred() or controller.getPin().len != PINLengthForStatusApp:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
if controller.isSelectedLoginAccountKeycardAccount() and
controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextTertiaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardWrongKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -12,22 +12,19 @@ proc delete*(self: LoginKeycardWrongPinState) =
method executePrimaryCommand*(self: LoginKeycardWrongPinState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
if controller.keychainErrorOccurred() or controller.getPin().len != PINLengthForStatusApp:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
if controller.isSelectedLoginAccountKeycardAccount() and
controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextTertiaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardWrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
@ -50,5 +47,4 @@ method resolveKeycardNextState*(self: LoginKeycardWrongPinState, keycardFlowType
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:
controller.setKeycardEvent(keycardEvent)
controller.loginAccountKeycard()
return nil
return createState(StateType.LoginKeycardPinVerified, self.flowType, nil)

View File

@ -12,13 +12,15 @@ method executePrimaryCommand*(self: LoginNotKeycardState, controller: Controller
if self.flowType == FlowType.AppLogin:
controller.runLoadAccountFlow(seedPhraseLength = 0, seedPhrase = "", puk = "", factoryReset = true)
method getNextSecondaryState*(self: LoginNotKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginNotKeycardState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginNotKeycardState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginNotKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -8,24 +8,15 @@ proc newLoginPluginState*(flowType: FlowType, backState: State): LoginPluginStat
proc delete*(self: LoginPluginState) =
self.State.delete
method executePrimaryCommand*(self: LoginPluginState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginPluginState, controller: Controller): State =
if controller.keychainErrorOccurred() or controller.getPin().len != PINLengthForStatusApp:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginPluginState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextTertiaryState*(self: LoginPluginState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginPluginState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginPluginState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -10,22 +10,29 @@ proc delete*(self: LoginState) =
method executePrimaryCommand*(self: LoginState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if controller.keychainErrorOccurred():
return
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
elif controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginState, controller: Controller): State =
if controller.keychainErrorOccurred() or controller.getPin().len != PINLengthForStatusApp:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
return createState(StateType.LoginKeycardEnterPassword, self.flowType, nil)
else:
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextTertiaryState*(self: LoginState, controller: Controller): State =
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self)
method getNextQuaternaryState*(self: LoginState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -53,12 +53,17 @@ type StateType* {.pure.} = enum
Login = "Login"
LoginPlugin = "LoginPlugin"
LoginKeycardInsertKeycard = "LoginKeycardInsertKeycard"
LoginKeycardInsertedKeycard = "LoginKeycardInsertedKeycard"
LoginKeycardReadingKeycard = "LoginKeycardReadingKeycard"
LoginKeycardRecognizedKeycard = "LoginKeycardRecognizedKeycard"
LoginKeycardEnterPin = "LoginKeycardEnterPin"
LoginKeycardEnterPassword = "LoginKeycardEnterPassword"
LoginKeycardPinVerified = "LoginKeycardPinVerified"
LoginKeycardWrongKeycard = "LoginKeycardWrongKeycard"
LoginKeycardWrongPin = "LoginKeycardWrongPin"
LoginKeycardMaxPinRetriesReached = "LoginKeycardMaxPinRetriesReached"
LoginKeycardMaxPukRetriesReached = "LoginKeycardMaxPukRetriesReached"
LoginKeycardMaxPairingSlotsReached = "LoginKeycardMaxPairingSlotsReached"
LoginKeycardEmpty = "LoginKeycardEmpty"
LoginNotKeycard = "LoginNotKeycard"

View File

@ -56,12 +56,17 @@ include welcome_state
include login_state
include login_plugin_state
include login_keycard_insert_keycard_state
include login_keycard_inserted_keycard_state
include login_keycard_reading_keycard_state
include login_keycard_recognized_keycard_state
include login_keycard_enter_pin_state
include login_keycard_enter_password_state
include login_keycard_pin_verified_state
include login_keycard_wrong_keycard
include login_keycard_wrong_pin_state
include login_keycard_max_pin_retries_reached_state
include login_keycard_max_puk_retries_reached_state
include login_keycard_max_pairing_slots_reached_state
include login_keycard_empty_state
include login_not_keycard_state
@ -140,10 +145,18 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newLoginPluginState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardInsertKeycard:
return newLoginKeycardInsertKeycardState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardInsertedKeycard:
return newLoginKeycardInsertedKeycardState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardReadingKeycard:
return newLoginKeycardReadingKeycardState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardRecognizedKeycard:
return newLoginKeycardRecognizedKeycardState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardEnterPin:
return newLoginKeycardEnterPinState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardEnterPassword:
return newLoginKeycardEnterPasswordState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardPinVerified:
return newLoginKeycardPinVerifiedState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardWrongKeycard:
return newLoginKeycardWrongKeycardState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardWrongPin:
@ -152,6 +165,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newLoginKeycardMaxPinRetriesReachedState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardMaxPukRetriesReached:
return newLoginKeycardMaxPukRetriesReachedState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardMaxPairingSlotsReached:
return newLoginKeycardMaxPairingSlotsReachedState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardEmpty:
return newLoginKeycardEmptyState(flowType, backState)
if stateToBeCreated == StateType.LoginNotKeycard:
@ -193,7 +208,7 @@ proc ensureReaderAndCardPresenceLogin*(state: State, keycardFlowType: string, ke
return createState(StateType.LoginKeycardInsertKeycard, state.flowType, state.getBackState)
if keycardFlowType == ResponseTypeValueCardInserted:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WronglyInsertedCard, add = false))
return createState(StateType.LoginKeycardReadingKeycard, state.flowType, state.getBackState)
return createState(StateType.LoginKeycardInsertedKeycard, state.flowType, state.getBackState)
proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
let ensureState = ensureReaderAndCardPresenceOnboarding(state, keycardFlowType, keycardEvent, controller)
@ -303,17 +318,12 @@ proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardF
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len == 0:
controller.setKeycardEvent(keycardEvent)
controller.loginAccountKeycard()
return nil
return createState(StateType.LoginKeycardPinVerified, state.flowType, nil)
if keycardFlowType == ResponseTypeValueEnterPIN:
if keycardEvent.error.len == 0:
if not controller.keyUidMatch(keycardEvent.keyUid):
return createState(StateType.LoginKeycardWrongKeycard, state.flowType, nil)
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
if value == LS_VALUE_STORE:
controller.tryToObtainDataFromKeychain()
return nil
return createState(StateType.LoginKeycardEnterPin, state.flowType, nil)
return createState(StateType.LoginKeycardRecognizedKeycard, state.flowType, nil)
if keycardEvent.error.len > 0:
if keycardEvent.error == RequestParamPIN:
controller.setKeycardData($keycardEvent.pinRetries)
@ -331,4 +341,6 @@ proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardF
if keycardEvent.error == ErrorNotAKeycard:
return createState(StateType.LoginNotKeycard, state.flowType, nil)
if keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.LoginKeycardMaxPukRetriesReached, state.flowType, nil)
return createState(StateType.LoginKeycardMaxPukRetriesReached, state.flowType, nil)
if keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.LoginKeycardMaxPairingSlotsReached, state.flowType, nil)

View File

@ -33,14 +33,18 @@ method executePrimaryCommand*(self: UserProfileEnterSeedPhraseState, controller:
if self.successfulImport:
controller.runLoadAccountFlow(controller.getSeedPhraseLength(), controller.getSeedPhrase(), puk = "", factoryReset = true)
else:
self.successfulImport = controller.validMnemonic(controller.getSeedPhrase())
if self.successfulImport:
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.storeSeedPhraseToKeycard(controller.getSeedPhraseLength(), controller.getSeedPhrase())
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
self.correctKeycard = controller.getKeyUidForSeedPhrase(controller.getSeedPhrase()) == controller.getKeyUid()
if self.correctKeycard:
controller.runLoadAccountFlow(controller.getSeedPhraseLength(), controller.getSeedPhrase(), puk = "", factoryReset = true)
if self.flowType == FlowType.FirstRunOldUserImportSeedPhrase or
self.flowType == FlowType.FirstRunNewUserImportSeedPhrase:
self.successfulImport = controller.importMnemonic()
else:
self.successfulImport = controller.validMnemonic(controller.getSeedPhrase())
if self.successfulImport:
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.storeSeedPhraseToKeycard(controller.getSeedPhraseLength(), controller.getSeedPhrase())
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
self.correctKeycard = controller.getKeyUidForSeedPhrase(controller.getSeedPhrase()) == controller.getKeyUid()
if self.correctKeycard:
controller.runLoadAccountFlow(controller.getSeedPhraseLength(), controller.getSeedPhrase(), puk = "", factoryReset = true)
method resolveKeycardNextState*(self: UserProfileEnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =

View File

@ -251,14 +251,21 @@ method importAccountSuccess*[T](self: Module[T]) =
self.view.importAccountSuccess()
method setSelectedLoginAccount*[T](self: Module[T], item: login_acc_item.Item) =
self.controller.disconnectKeychain()
self.controller.cancelCurrentFlow()
self.controller.setSelectedLoginAccount(item.getKeyUid(), item.getKeycardCreatedAccount())
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil))
if item.getKeycardCreatedAccount():
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil))
self.controller.runLoginFlow()
else:
self.controller.tryToObtainDataFromKeychain()
else:
let value = singletonInstance.localAccountSettings.getStoreToKeychainValue()
if value == LS_VALUE_STORE:
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil))
self.controller.tryToObtainDataFromKeychain()
else:
self.view.setCurrentStartupState(newLoginKeycardEnterPasswordState(FlowType.AppLogin, nil))
self.view.setSelectedLoginAccount(item)
self.controller.connectKeychain()
method emitAccountLoginError*[T](self: Module[T], error: string) =
self.view.emitAccountLoginError(error)

View File

@ -460,6 +460,7 @@ proc setupAccountKeycard*(self: Service, keycardData: KeycardEvent) =
subaccountDataJson,
settingsJson,
nodeConfigJson)
self.setLocalAccountSettingsFile()
except Exception as e:
error "error: ", procName="setupAccount", errName = e.name, errDesription = e.msg

View File

@ -66,12 +66,17 @@ OnboardingBasePage {
if (root.startupStore.currentStartupState.stateType === Constants.startupState.login ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginPlugin ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardInsertKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardInsertedKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardReadingKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardRecognizedKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEnterPin ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEnterPassword ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardPinVerified ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardWrongKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardWrongPin ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPinRetriesReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPukRetriesReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPairingSlotsReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEmpty ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginNotKeycard)
{

View File

@ -11,6 +11,8 @@ import StatusQ.Controls 0.1
import StatusQ.Controls.Validators 0.1
import StatusQ.Popups 0.1
import shared.popups.keycard.helpers 1.0
import SortFilterProxyModel 0.2
import shared.panels 1.0
@ -36,8 +38,23 @@ Item {
onStateChanged: {
d.loading = false
pinInputField.statesInitialization()
pinInputField.forceFocus()
if(state === Constants.startupState.loginKeycardPinVerified) {
pinInputField.setPin("123456") // we are free to set fake pin in this case
pinInputField.enabled = false
} else {
pinInputField.statesInitialization()
pinInputField.forceFocus()
}
}
Timer {
id: timer
interval: 1000
running: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardRecognizedKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardPinVerified
onTriggered: {
root.startupStore.doPrimaryAction()
}
}
QtObject {
@ -47,14 +64,6 @@ Item {
readonly property string stateLoginRegularUser: "regularUserLogin"
readonly property string stateLoginKeycardUser: "keycardUserLogin"
property int index: 0
property variant images : [
Style.svg("keycard/card0@2x"),
Style.svg("keycard/card1@2x"),
Style.svg("keycard/card2@2x"),
Style.svg("keycard/card3@2x")
]
property int remainingAttempts: parseInt(root.startupStore.startupModuleInst.keycardData, 10)
onRemainingAttemptsChanged: {
pinInputField.statesInitialization()
@ -91,31 +100,20 @@ Item {
}
}
Timer {
interval: 400
running: root.state === d.stateLoginKeycardUser ||
root.state === Constants.startupState.loginKeycardInsertKeycard ||
root.state === Constants.startupState.loginKeycardReadingKeycard
repeat: true
onTriggered: {
d.index++
image.source = d.images[d.index % d.images.length]
}
}
Connections{
target: root.startupStore.startupModuleInst
onObtainingPasswordError: {
if (root.startupStore.selectedLoginAccount.keycardCreatedAccount) {
root.startupStore.doPrimaryAction() // in this case, switch to enter pin state
}
if (errorType === Constants.keychain.errorType.authentication) {
// We are notifying user only about keychain errors.
return
}
image.source = Style.png("keycard/biometrics-fail")
info.icon = ""
info.color = Theme.palette.dangerColor1
info.text = qsTr("Fingerprint not recognized")
obtainingPasswordErrorNotification.confirmationText = errorDescription
obtainingPasswordErrorNotification.open()
}
@ -164,14 +162,21 @@ Item {
ColumnLayout {
anchors.centerIn: parent
height: Constants.keycard.general.loginHeight
spacing: Style.current.bigPadding
Image {
KeycardImage {
id: image
Layout.alignment: Qt.AlignHCenter
fillMode: Image.PreserveAspectFit
antialiasing: true
mipmap: true
Layout.preferredHeight: Constants.keycard.general.imageHeight
Layout.preferredWidth: Constants.keycard.general.imageWidth
onAnimationCompleted: {
if (root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardInsertedKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardReadingKeycard) {
root.startupStore.doPrimaryAction()
}
}
}
StatusBaseText {
@ -184,10 +189,12 @@ Item {
Item {
id: userInfo
height: userImage.height
width: 318
Layout.preferredHeight: userImage.height
Layout.preferredWidth: 318
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Style.current.xlPadding
enabled: root.startupStore.currentStartupState.stateType !== Constants.startupState.loginKeycardReadingKeycard &&
root.startupStore.currentStartupState.stateType !== Constants.startupState.loginKeycardRecognizedKeycard &&
root.startupStore.currentStartupState.stateType !== Constants.startupState.loginKeycardPinVerified
UserImage {
id: userImage
@ -304,7 +311,7 @@ Item {
asset.name: "add"
onClicked: {
accountsPopup.close()
root.startupStore.doSecondaryAction()
root.startupStore.doTertiaryAction()
}
}
@ -313,7 +320,7 @@ Item {
asset.name: "wallet"
onClicked: {
accountsPopup.close()
root.startupStore.doTertiaryAction()
root.startupStore.doQuaternaryAction()
}
}
}
@ -383,7 +390,10 @@ Item {
Layout.alignment: Qt.AlignHCenter
spacing: Style.current.padding
property alias text: pinText.text
StatusBaseText {
id: pinText
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: Constants.keycard.general.fontSize2
wrapMode: Text.WordWrap
@ -398,6 +408,11 @@ Item {
enabled: !d.loading
onPinInputChanged: {
if (root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardPinVerified)
return
if (root.state !== Constants.startupState.loginKeycardWrongPin) {
image.source = Style.png("keycard/enter-pin-%1".arg(pinInput.length))
}
if(pinInput.length == 0)
return
root.startupStore.setPin(pinInput)
@ -406,12 +421,34 @@ Item {
}
}
StatusBaseText {
Row {
id: info
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Constants.keycard.general.fontSize3
wrapMode: Text.WordWrap
Layout.alignment: Qt.AlignCenter
spacing: Style.current.halfPadding
property alias text: infoTxt.text
property alias font: infoTxt.font
property alias color: infoTxt.color
property alias icon: infoIcon.icon
StatusIcon {
id: infoIcon
visible: icon !== ""
width: Style.current.padding
height: Style.current.padding
color: Theme.palette.baseColor1
}
StatusLoadingIndicator {
id: loading
visible: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardReadingKeycard
}
StatusBaseText {
id: infoTxt
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Constants.keycard.general.fontSize3
wrapMode: Text.WordWrap
}
}
StatusBaseText {
@ -446,29 +483,42 @@ Item {
parent.font.underline = false
}
onClicked: {
root.startupStore.doPrimaryAction()
root.startupStore.doSecondaryAction()
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}
states: [
State {
name: d.stateLoginRegularUser
when: !root.startupStore.selectedLoginAccount.keycardCreatedAccount
when: !root.startupStore.selectedLoginAccount.keycardCreatedAccount &&
root.startupStore.currentStartupState.stateType === Constants.startupState.login
PropertyChanges {
target: image
source: Style.png("status-logo")
Layout.preferredHeight: 128
Layout.preferredWidth: 128
source: localAccountSettings.storeToKeychainValue === Constants.keychain.storedValue.store?
Style.png("keycard/biometrics-success") : Style.png("status-logo")
pattern: ""
Layout.preferredHeight: localAccountSettings.storeToKeychainValue === Constants.keychain.storedValue.store?
Constants.keycard.general.imageHeight :
Constants.keycard.general.loginStatusLogoHeight
Layout.preferredWidth: localAccountSettings.storeToKeychainValue === Constants.keychain.storedValue.store?
Constants.keycard.general.imageWidth :
Constants.keycard.general.loginStatusLogoWidth
}
PropertyChanges {
target: title
text: qsTr("Welcome back")
text: localAccountSettings.storeToKeychainValue === Constants.keychain.storedValue.store? "" : qsTr("Welcome back")
visible: localAccountSettings.storeToKeychainValue !== Constants.keychain.storedValue.store
}
PropertyChanges {
target: passwordSection
visible: true
visible: localAccountSettings.storeToKeychainValue !== Constants.keychain.storedValue.store
}
PropertyChanges {
target: pinSection
@ -476,8 +526,12 @@ Item {
}
PropertyChanges {
target: info
text: ""
visible: false
text: qsTr("Waiting for TouchID...")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: "touch-id"
}
PropertyChanges {
target: message
@ -491,8 +545,8 @@ Item {
}
PropertyChanges {
target: link
text: ""
visible: false
text: qsTr("Use password instead")
visible: true
}
},
State {
@ -501,9 +555,8 @@ Item {
root.startupStore.currentStartupState.stateType === Constants.startupState.login
PropertyChanges {
target: image
source: Style.svg("keycard/card3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
source: Style.png("keycard/biometrics-success")
pattern: ""
}
PropertyChanges {
target: title
@ -520,7 +573,12 @@ Item {
}
PropertyChanges {
target: info
visible: false
text: qsTr("Waiting for TouchID...")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: "touch-id"
}
PropertyChanges {
target: message
@ -534,8 +592,8 @@ Item {
}
PropertyChanges {
target: link
text: ""
visible: false
text: qsTr("Use PIN instead")
visible: true
}
},
State {
@ -544,9 +602,8 @@ Item {
root.startupStore.currentStartupState.stateType === Constants.startupState.loginPlugin
PropertyChanges {
target: image
source: Style.svg("keycard/card3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
source: Style.png("keycard/empty-reader")
pattern: ""
}
PropertyChanges {
target: title
@ -567,6 +624,8 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
@ -589,9 +648,13 @@ Item {
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardInsertKeycard
PropertyChanges {
target: image
source: Style.svg("keycard/card3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
pattern: "keycard/card_insert/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 0
endImgIndex: 16
duration: 1000
loops: 1
}
PropertyChanges {
target: title
@ -612,6 +675,8 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
@ -631,14 +696,69 @@ Item {
visible: false
}
},
State {
name: Constants.startupState.loginKeycardInsertedKeycard
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardInsertedKeycard
PropertyChanges {
target: image
pattern: "keycard/card_inserted/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 0
endImgIndex: 29
duration: 1000
loops: 1
}
PropertyChanges {
target: title
text: ""
visible: false
}
PropertyChanges {
target: passwordSection
visible: false
}
PropertyChanges {
target: pinSection
visible: false
}
PropertyChanges {
target: info
text: qsTr("Keycard inserted...")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
text: ""
visible: false
}
PropertyChanges {
target: button
text: ""
visible: false
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginKeycardReadingKeycard
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardReadingKeycard
PropertyChanges {
target: image
source: Style.svg("keycard/card3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
pattern: "keycard/warning/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 0
endImgIndex: 55
duration: 3000
loops: 1
}
PropertyChanges {
target: title
@ -659,6 +779,103 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
text: ""
visible: false
}
PropertyChanges {
target: button
text: ""
visible: false
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginKeycardRecognizedKeycard
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardRecognizedKeycard
PropertyChanges {
target: image
pattern: "keycard/success/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 0
endImgIndex: 29
duration: 1300
loops: 1
}
PropertyChanges {
target: title
text: ""
visible: false
}
PropertyChanges {
target: passwordSection
visible: false
}
PropertyChanges {
target: pinSection
visible: false
}
PropertyChanges {
target: info
text: qsTr("Keycard recognized")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
height: Constants.keycard.general.loginInfoHeight1
icon: "checkmark"
}
PropertyChanges {
target: message
text: ""
visible: false
}
PropertyChanges {
target: button
text: ""
visible: false
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginKeycardEnterPassword
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEnterPassword
PropertyChanges {
target: image
source: Style.png("status-logo")
pattern: ""
Layout.preferredHeight: Constants.keycard.general.loginStatusLogoHeight
Layout.preferredWidth: Constants.keycard.general.loginStatusLogoWidth
}
PropertyChanges {
target: title
text: qsTr("Welcome back")
visible: true
}
PropertyChanges {
target: passwordSection
visible: true
}
PropertyChanges {
target: pinSection
visible: false
}
PropertyChanges {
target: info
text: ""
visible: true
}
PropertyChanges {
target: message
@ -681,9 +898,8 @@ Item {
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEnterPin
PropertyChanges {
target: image
source: Style.svg("keycard/card3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
source: Style.png("keycard/card-empty")
pattern: ""
}
PropertyChanges {
target: title
@ -697,13 +913,59 @@ Item {
PropertyChanges {
target: pinSection
visible: true
text: qsTr("Enter Keycard PIN")
}
PropertyChanges {
target: info
text: ""
visible: false
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
PropertyChanges {
target: message
text: ""
visible: false
}
PropertyChanges {
target: button
text: ""
visible: false
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginKeycardPinVerified
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardPinVerified
PropertyChanges {
target: image
pattern: "keycard/strong_success/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 0
endImgIndex: 20
duration: 1300
loops: 1
}
PropertyChanges {
target: title
text: ""
visible: false
}
PropertyChanges {
target: passwordSection
visible: false
}
PropertyChanges {
target: pinSection
visible: true
text: qsTr("PIN Verified")
}
PropertyChanges {
target: info
visible: false
}
PropertyChanges {
target: message
@ -726,9 +988,13 @@ Item {
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardWrongKeycard
PropertyChanges {
target: image
source: Style.svg("keycard/card-wrong3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
pattern: "keycard/strong_error/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 18
endImgIndex: 29
duration: 1300
loops: -1
}
PropertyChanges {
target: title
@ -749,10 +1015,12 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
height: Constants.keycard.general.loginInfoHeight2
icon: ""
}
PropertyChanges {
target: message
text: qsTr("Insert another Keycard")
text: qsTr("Insert proper Keycard")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
@ -773,9 +1041,8 @@ Item {
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardWrongPin
PropertyChanges {
target: image
source: Style.svg("keycard/card-wrong3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
source: Style.png("keycard/plain-error")
pattern: ""
}
PropertyChanges {
target: title
@ -789,6 +1056,7 @@ Item {
PropertyChanges {
target: pinSection
visible: true
text: qsTr("Enter Keycard PIN")
}
PropertyChanges {
target: info
@ -796,6 +1064,8 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
@ -819,12 +1089,18 @@ Item {
},
State {
name: Constants.startupState.loginKeycardMaxPinRetriesReached
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPinRetriesReached
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPinRetriesReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPukRetriesReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPairingSlotsReached
PropertyChanges {
target: image
source: Style.svg("keycard/card-error3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
pattern: "keycard/strong_error/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 18
endImgIndex: 29
duration: 1300
loops: -1
}
PropertyChanges {
target: title
@ -845,6 +1121,8 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
@ -853,52 +1131,7 @@ Item {
}
PropertyChanges {
target: button
text: qsTr("Recover your Keycard")
visible: true
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginKeycardMaxPukRetriesReached
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPukRetriesReached
PropertyChanges {
target: image
source: Style.svg("keycard/card-error3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
}
PropertyChanges {
target: title
text: ""
visible: false
}
PropertyChanges {
target: passwordSection
visible: false
}
PropertyChanges {
target: pinSection
visible: false
}
PropertyChanges {
target: info
text: qsTr("Keycard locked")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
}
PropertyChanges {
target: message
text: ""
visible: false
}
PropertyChanges {
target: button
text: qsTr("Recover with seed phrase")
text: qsTr("Unlock Keycard")
visible: true
}
PropertyChanges {
@ -912,9 +1145,8 @@ Item {
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEmpty
PropertyChanges {
target: image
source: Style.svg("keycard/card-wrong3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
source: Style.png("keycard/card-empty")
pattern: ""
}
PropertyChanges {
target: title
@ -931,10 +1163,12 @@ Item {
}
PropertyChanges {
target: info
text: qsTr("The card inserted is empty")
text: qsTr("The card inserted is empty (has no profile linked).")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message
@ -957,9 +1191,13 @@ Item {
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginNotKeycard
PropertyChanges {
target: image
source: Style.svg("keycard/card-wrong3@2x")
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
pattern: "keycard/strong_error/img-%1"
source: ""
startImgIndexForTheFirstLoop: 0
startImgIndexForOtherLoops: 18
endImgIndex: 29
duration: 1300
loops: -1
}
PropertyChanges {
target: title
@ -980,6 +1218,8 @@ Item {
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
height: Constants.keycard.general.loginInfoHeight1
icon: ""
}
PropertyChanges {
target: message

View File

@ -63,12 +63,17 @@ QtObject {
readonly property string login: "Login"
readonly property string loginPlugin: "LoginPlugin"
readonly property string loginKeycardInsertKeycard: "LoginKeycardInsertKeycard"
readonly property string loginKeycardInsertedKeycard: "LoginKeycardInsertedKeycard"
readonly property string loginKeycardReadingKeycard: "LoginKeycardReadingKeycard"
readonly property string loginKeycardRecognizedKeycard: "LoginKeycardRecognizedKeycard"
readonly property string loginKeycardEnterPin: "LoginKeycardEnterPin"
readonly property string loginKeycardEnterPassword: "LoginKeycardEnterPassword"
readonly property string loginKeycardPinVerified: "LoginKeycardPinVerified"
readonly property string loginKeycardWrongKeycard: "LoginKeycardWrongKeycard"
readonly property string loginKeycardWrongPin: "LoginKeycardWrongPin"
readonly property string loginKeycardMaxPinRetriesReached: "LoginKeycardMaxPinRetriesReached"
readonly property string loginKeycardMaxPukRetriesReached: "LoginKeycardMaxPukRetriesReached"
readonly property string loginKeycardMaxPairingSlotsReached: "LoginKeycardMaxPairingSlotsReached"
readonly property string loginKeycardEmpty: "LoginKeycardEmpty"
readonly property string loginNotKeycard: "LoginNotKeycard"
}
@ -388,6 +393,7 @@ QtObject {
readonly property QtObject general: QtObject {
readonly property int onboardingHeight: 460
readonly property int loginHeight: 460
readonly property int imageWidth: 240
readonly property int imageHeight: 240
readonly property int seedPhraseWidth: 816
@ -414,6 +420,10 @@ QtObject {
readonly property int titleHeight: 44
readonly property int messageHeight: 48
readonly property int footerButtonsHeight: 44
readonly property int loginInfoHeight1: 24
readonly property int loginInfoHeight2: 44
readonly property int loginStatusLogoWidth: 128
readonly property int loginStatusLogoHeight: 128
}
readonly property QtObject keyPairType: QtObject {