fix(@desktop/keycard): updates to the onboarding/login flow

- login states updated so they can resolve enter pin state from each state
that flow may be in
- not a keycard state added
- login plugin state added
This commit is contained in:
Sale Djenic 2022-09-13 11:55:19 +02:00 committed by saledjenic
parent 3042a0cffa
commit 405171dad7
16 changed files with 210 additions and 26 deletions

View File

@ -10,10 +10,7 @@ proc delete*(self: LoginKeycardEmptyState) =
method executePrimaryCommand*(self: LoginKeycardEmptyState, controller: Controller) = method executePrimaryCommand*(self: LoginKeycardEmptyState, controller: Controller) =
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount(): controller.runLoadAccountFlow(factoryReset = true)
controller.login()
else:
controller.runLoadAccountFlow(factoryReset = true)
method getNextSecondaryState*(self: LoginKeycardEmptyState, controller: Controller): State = method getNextSecondaryState*(self: LoginKeycardEmptyState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()

View File

@ -12,6 +12,12 @@ method executePrimaryCommand*(self: LoginKeycardInsertKeycardState, controller:
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount(): if not controller.isSelectedLoginAccountKeycardAccount():
controller.login() 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():
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State = method getNextSecondaryState*(self: LoginKeycardInsertKeycardState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()

View File

@ -12,11 +12,6 @@ method executeBackCommand*(self: LoginKeycardMaxPinRetriesReachedState, controll
if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne(): if self.flowType == FlowType.AppLogin and controller.isKeycardCreatedAccountSelectedOne():
controller.runLoginFlow() controller.runLoginFlow()
method executePrimaryCommand*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount():
controller.login()
method getNextPrimaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State = method getNextPrimaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
return createState(StateType.KeycardRecover, self.flowType, self) return createState(StateType.KeycardRecover, self.flowType, self)
@ -26,4 +21,8 @@ method getNextSecondaryState*(self: LoginKeycardMaxPinRetriesReachedState, contr
method getNextTertiaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State = method getNextTertiaryState*(self: LoginKeycardMaxPinRetriesReachedState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self) return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardMaxPinRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -11,4 +11,8 @@ proc delete*(self: LoginKeycardMaxPukRetriesReachedState) =
method getNextPrimaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State = method getNextPrimaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(true) controller.setRecoverUsingSeedPhraseWhileLogin(true)
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, nil) return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, nil)
method resolveKeycardNextState*(self: LoginKeycardMaxPukRetriesReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -14,7 +14,7 @@ method executePrimaryCommand*(self: LoginKeycardReadingKeycardState, controller:
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount(): if not controller.isSelectedLoginAccountKeycardAccount():
controller.login() controller.login()
elif not controller.keychainErrorOccurred(): elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin()) controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State = method getNextPrimaryState*(self: LoginKeycardReadingKeycardState, controller: Controller): State =

View File

@ -12,6 +12,12 @@ method executePrimaryCommand*(self: LoginKeycardWrongKeycardState, controller: C
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount(): if not controller.isSelectedLoginAccountKeycardAccount():
controller.login() 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():
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State = method getNextSecondaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()
@ -19,4 +25,8 @@ method getNextSecondaryState*(self: LoginKeycardWrongKeycardState, controller: C
method getNextTertiaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State = method getNextTertiaryState*(self: LoginKeycardWrongKeycardState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()
return createState(StateType.WelcomeOldStatusUser, self.flowType, self) return createState(StateType.WelcomeOldStatusUser, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardWrongKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -14,9 +14,13 @@ method executePrimaryCommand*(self: LoginKeycardWrongPinState, controller: Contr
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount(): if not controller.isSelectedLoginAccountKeycardAccount():
controller.login() controller.login()
elif controller.getPin().len == PINLengthForStatusApp: elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin()) controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
if controller.keychainErrorOccurred():
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginKeycardWrongPinState, controller: Controller): State = method getNextSecondaryState*(self: LoginKeycardWrongPinState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()
return createState(StateType.WelcomeNewStatusUser, self.flowType, self) return createState(StateType.WelcomeNewStatusUser, self.flowType, self)

View File

@ -0,0 +1,25 @@
type
LoginNotKeycardState* = ref object of State
proc newLoginNotKeycardState*(flowType: FlowType, backState: State): LoginNotKeycardState =
result = LoginNotKeycardState()
result.setup(flowType, StateType.LoginNotKeycard, backState)
proc delete*(self: LoginNotKeycardState) =
self.State.delete
method executePrimaryCommand*(self: LoginNotKeycardState, controller: Controller) =
if self.flowType == FlowType.AppLogin:
controller.runLoadAccountFlow(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)
method resolveKeycardNextState*(self: LoginNotKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -0,0 +1,32 @@
type
LoginPluginState* = ref object of State
proc newLoginPluginState*(flowType: FlowType, backState: State): LoginPluginState =
result = LoginPluginState()
result.setup(flowType, StateType.LoginPlugin, backState)
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():
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)
method resolveKeycardNextState*(self: LoginPluginState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -12,6 +12,12 @@ method executePrimaryCommand*(self: LoginState, controller: Controller) =
if self.flowType == FlowType.AppLogin: if self.flowType == FlowType.AppLogin:
if not controller.isSelectedLoginAccountKeycardAccount(): if not controller.isSelectedLoginAccountKeycardAccount():
controller.login() controller.login()
elif not controller.keychainErrorOccurred() and controller.getPin().len == PINLengthForStatusApp:
controller.enterKeycardPin(controller.getPin())
method getNextPrimaryState*(self: LoginState, controller: Controller): State =
if controller.keychainErrorOccurred():
return createState(StateType.LoginKeycardEnterPin, self.flowType, nil)
method getNextSecondaryState*(self: LoginState, controller: Controller): State = method getNextSecondaryState*(self: LoginState, controller: Controller): State =
controller.cancelCurrentFlow() controller.cancelCurrentFlow()

View File

@ -47,6 +47,7 @@ type StateType* {.pure.} = enum
KeycardMaxPinRetriesReached = "KeycardMaxPinRetriesReached" KeycardMaxPinRetriesReached = "KeycardMaxPinRetriesReached"
KeycardMaxPukRetriesReached = "KeycardMaxPukRetriesReached" KeycardMaxPukRetriesReached = "KeycardMaxPukRetriesReached"
Login = "Login" Login = "Login"
LoginPlugin = "LoginPlugin"
LoginKeycardInsertKeycard = "LoginKeycardInsertKeycard" LoginKeycardInsertKeycard = "LoginKeycardInsertKeycard"
LoginKeycardReadingKeycard = "LoginKeycardReadingKeycard" LoginKeycardReadingKeycard = "LoginKeycardReadingKeycard"
LoginKeycardEnterPin = "LoginKeycardEnterPin" LoginKeycardEnterPin = "LoginKeycardEnterPin"
@ -55,6 +56,7 @@ type StateType* {.pure.} = enum
LoginKeycardMaxPinRetriesReached = "LoginKeycardMaxPinRetriesReached" LoginKeycardMaxPinRetriesReached = "LoginKeycardMaxPinRetriesReached"
LoginKeycardMaxPukRetriesReached = "LoginKeycardMaxPukRetriesReached" LoginKeycardMaxPukRetriesReached = "LoginKeycardMaxPukRetriesReached"
LoginKeycardEmpty = "LoginKeycardEmpty" LoginKeycardEmpty = "LoginKeycardEmpty"
LoginNotKeycard = "LoginNotKeycard"
## This is the base class for all state we may have in onboarding/login flow. ## This is the base class for all state we may have in onboarding/login flow.

View File

@ -47,6 +47,7 @@ include welcome_state_new_user
include welcome_state_old_user include welcome_state_old_user
include welcome_state include welcome_state
include login_state include login_state
include login_plugin_state
include login_keycard_insert_keycard_state include login_keycard_insert_keycard_state
include login_keycard_reading_keycard_state include login_keycard_reading_keycard_state
include login_keycard_enter_pin_state include login_keycard_enter_pin_state
@ -55,6 +56,7 @@ include login_keycard_wrong_pin_state
include login_keycard_max_pin_retries_reached_state include login_keycard_max_pin_retries_reached_state
include login_keycard_max_puk_retries_reached_state include login_keycard_max_puk_retries_reached_state
include login_keycard_empty_state include login_keycard_empty_state
include login_not_keycard_state
proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: State): State = proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: State): State =
if stateToBeCreated == StateType.AllowNotifications: if stateToBeCreated == StateType.AllowNotifications:
@ -119,6 +121,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newKeycardMaxPukRetriesReachedState(flowType, backState) return newKeycardMaxPukRetriesReachedState(flowType, backState)
if stateToBeCreated == StateType.Login: if stateToBeCreated == StateType.Login:
return newLoginState(flowType, backState) return newLoginState(flowType, backState)
if stateToBeCreated == StateType.LoginPlugin:
return newLoginPluginState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardInsertKeycard: if stateToBeCreated == StateType.LoginKeycardInsertKeycard:
return newLoginKeycardInsertKeycardState(flowType, backState) return newLoginKeycardInsertKeycardState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardReadingKeycard: if stateToBeCreated == StateType.LoginKeycardReadingKeycard:
@ -135,6 +139,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newLoginKeycardMaxPukRetriesReachedState(flowType, backState) return newLoginKeycardMaxPukRetriesReachedState(flowType, backState)
if stateToBeCreated == StateType.LoginKeycardEmpty: if stateToBeCreated == StateType.LoginKeycardEmpty:
return newLoginKeycardEmptyState(flowType, backState) return newLoginKeycardEmptyState(flowType, backState)
if stateToBeCreated == StateType.LoginNotKeycard:
return newLoginNotKeycardState(flowType, backState)
error "No implementation available for state ", state=stateToBeCreated error "No implementation available for state ", state=stateToBeCreated
@ -161,9 +167,9 @@ proc ensureReaderAndCardPresenceLogin*(state: State, keycardFlowType: string, ke
keycardEvent.error.len > 0 and keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection: keycardEvent.error == ErrorConnection:
controller.resumeCurrentFlowLater() controller.resumeCurrentFlowLater()
if state.stateType == StateType.Login: if state.stateType == StateType.LoginPlugin:
return nil return nil
return createState(StateType.Login, state.flowType, state) return createState(StateType.LoginPlugin, state.flowType, nil)
if keycardFlowType == ResponseTypeValueInsertCard and if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection: keycardEvent.error == ErrorConnection:
@ -279,10 +285,10 @@ proc ensureReaderAndCardPresenceAndResolveNextLoginState*(state: State, keycardF
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0: if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.LoginKeycardMaxPinRetriesReached, state.flowType, nil) return createState(StateType.LoginKeycardMaxPinRetriesReached, state.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and keycardEvent.error.len > 0:
keycardEvent.error == ErrorNoKeys: if keycardEvent.error == ErrorNoKeys:
return createState(StateType.LoginKeycardEmpty, state.flowType, nil) return createState(StateType.LoginKeycardEmpty, state.flowType, nil)
if keycardFlowType == ResponseTypeValueSwapCard and if keycardEvent.error == ErrorNotAKeycard:
keycardEvent.error.len > 0 and return createState(StateType.LoginNotKeycard, state.flowType, nil)
keycardEvent.error == RequestParamPUKRetries: if keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.LoginKeycardMaxPukRetriesReached, state.flowType, nil) return createState(StateType.LoginKeycardMaxPukRetriesReached, state.flowType, nil)

View File

@ -99,7 +99,6 @@ method load*[T](self: Module[T]) =
error "cannot run the app in login flow cause list of login accounts is empty" error "cannot run the app in login flow cause list of login accounts is empty"
quit() # quit the app quit() # quit the app
self.setSelectedLoginAccount(items[0]) self.setSelectedLoginAccount(items[0])
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil))
self.delegate.startupDidLoad() self.delegate.startupDidLoad()
method getKeycardSharedModule*[T](self: Module[T]): QVariant = method getKeycardSharedModule*[T](self: Module[T]): QVariant =
@ -228,8 +227,8 @@ method importAccountSuccess*[T](self: Module[T]) =
method setSelectedLoginAccount*[T](self: Module[T], item: login_acc_item.Item) = method setSelectedLoginAccount*[T](self: Module[T], item: login_acc_item.Item) =
self.controller.cancelCurrentFlow() self.controller.cancelCurrentFlow()
self.controller.setSelectedLoginAccount(item.getKeyUid(), item.getKeycardCreatedAccount()) self.controller.setSelectedLoginAccount(item.getKeyUid(), item.getKeycardCreatedAccount())
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil))
if item.getKeycardCreatedAccount(): if item.getKeycardCreatedAccount():
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil)) # nim garbage collector will handle all abandoned state objects
self.controller.runLoginFlow() self.controller.runLoginFlow()
else: else:
self.controller.tryToObtainDataFromKeychain() self.controller.tryToObtainDataFromKeychain()

View File

@ -64,6 +64,7 @@ OnboardingBasePage {
return seedPhraseInputViewComponent return seedPhraseInputViewComponent
} }
if (root.startupStore.currentStartupState.stateType === Constants.startupState.login || 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.loginKeycardInsertKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardReadingKeycard || root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardReadingKeycard ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEnterPin || root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEnterPin ||
@ -71,7 +72,8 @@ OnboardingBasePage {
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardWrongPin || root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardWrongPin ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPinRetriesReached || root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPinRetriesReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPukRetriesReached || root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardMaxPukRetriesReached ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEmpty) root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardEmpty ||
root.startupStore.currentStartupState.stateType === Constants.startupState.loginNotKeycard)
{ {
return loginViewComponent return loginViewComponent
} }

View File

@ -518,6 +518,49 @@ Item {
target: pinSection target: pinSection
visible: false visible: false
} }
PropertyChanges {
target: info
visible: false
}
PropertyChanges {
target: message
text: ""
visible: false
}
PropertyChanges {
target: button
text: ""
visible: false
}
PropertyChanges {
target: link
text: ""
visible: false
}
},
State {
name: Constants.startupState.loginPlugin
when: root.startupStore.selectedLoginAccount.keycardCreatedAccount &&
root.startupStore.currentStartupState.stateType === Constants.startupState.loginPlugin
PropertyChanges {
target: image
source: Style.svg("keycard/card3@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 { PropertyChanges {
target: info target: info
text: qsTr("Plug in Keycard reader...") text: qsTr("Plug in Keycard reader...")
@ -908,6 +951,53 @@ Item {
text: qsTr("Generate keys for a new Keycard") text: qsTr("Generate keys for a new Keycard")
visible: true visible: true
} }
},
State {
name: Constants.startupState.loginNotKeycard
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
}
PropertyChanges {
target: title
text: ""
visible: false
}
PropertyChanges {
target: passwordSection
visible: false
}
PropertyChanges {
target: pinSection
visible: false
}
PropertyChanges {
target: info
text: qsTr("This is not a Keycard")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.dangerColor1
}
PropertyChanges {
target: message
text: qsTr("The card inserted is not a recognised Keycard,\nplease remove and try and again")
visible: true
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.baseColor1
}
PropertyChanges {
target: button
text: ""
visible: false
}
PropertyChanges {
target: link
text: ""
visible: false
}
} }
] ]
} }

View File

@ -57,6 +57,7 @@ QtObject {
readonly property string keycardMaxPinRetriesReached: "KeycardMaxPinRetriesReached" readonly property string keycardMaxPinRetriesReached: "KeycardMaxPinRetriesReached"
readonly property string keycardMaxPukRetriesReached: "KeycardMaxPukRetriesReached" readonly property string keycardMaxPukRetriesReached: "KeycardMaxPukRetriesReached"
readonly property string login: "Login" readonly property string login: "Login"
readonly property string loginPlugin: "LoginPlugin"
readonly property string loginKeycardInsertKeycard: "LoginKeycardInsertKeycard" readonly property string loginKeycardInsertKeycard: "LoginKeycardInsertKeycard"
readonly property string loginKeycardReadingKeycard: "LoginKeycardReadingKeycard" readonly property string loginKeycardReadingKeycard: "LoginKeycardReadingKeycard"
readonly property string loginKeycardEnterPin: "LoginKeycardEnterPin" readonly property string loginKeycardEnterPin: "LoginKeycardEnterPin"
@ -65,6 +66,7 @@ QtObject {
readonly property string loginKeycardMaxPinRetriesReached: "LoginKeycardMaxPinRetriesReached" readonly property string loginKeycardMaxPinRetriesReached: "LoginKeycardMaxPinRetriesReached"
readonly property string loginKeycardMaxPukRetriesReached: "LoginKeycardMaxPukRetriesReached" readonly property string loginKeycardMaxPukRetriesReached: "LoginKeycardMaxPukRetriesReached"
readonly property string loginKeycardEmpty: "LoginKeycardEmpty" readonly property string loginKeycardEmpty: "LoginKeycardEmpty"
readonly property string loginNotKeycard: "LoginNotKeycard"
} }
readonly property QtObject predefinedKeycardData: QtObject { readonly property QtObject predefinedKeycardData: QtObject {