feat(@desktop/keycards): managing mocked keycards when running keycard flows
This commit is contained in:
parent
b97e1fc8da
commit
d107a9f90b
7
Makefile
7
Makefile
|
@ -392,11 +392,16 @@ STATUSKEYCARDGO := vendor/status-keycard-go/build/libkeycard/libkeycard.$(LIBSTA
|
||||||
STATUSKEYCARDGO_LIBDIR := $(shell pwd)/$(shell dirname "$(STATUSKEYCARDGO)")
|
STATUSKEYCARDGO_LIBDIR := $(shell pwd)/$(shell dirname "$(STATUSKEYCARDGO)")
|
||||||
export STATUSKEYCARDGO_LIBDIR
|
export STATUSKEYCARDGO_LIBDIR
|
||||||
|
|
||||||
|
STATUSKEYCARDGO_RULE := build-lib
|
||||||
|
ifeq ($(TEST_ENVIRONMENT),true)
|
||||||
|
STATUSKEYCARDGO_RULE := build-mocked-lib
|
||||||
|
endif
|
||||||
|
|
||||||
status-keycard-go: $(STATUSKEYCARDGO)
|
status-keycard-go: $(STATUSKEYCARDGO)
|
||||||
$(STATUSKEYCARDGO): | deps
|
$(STATUSKEYCARDGO): | deps
|
||||||
echo -e $(BUILD_MSG) "status-keycard-go"
|
echo -e $(BUILD_MSG) "status-keycard-go"
|
||||||
+ cd vendor/status-keycard-go && \
|
+ cd vendor/status-keycard-go && \
|
||||||
$(MAKE) build-lib $(STATUSKEYCARDGO_MAKE_PARAMS) $(HANDLE_OUTPUT)
|
$(MAKE) $(STATUSKEYCARDGO_RULE) $(STATUSKEYCARDGO_MAKE_PARAMS) $(HANDLE_OUTPUT)
|
||||||
|
|
||||||
QRCODEGEN := vendor/QR-Code-generator/c/libqrcodegen.a
|
QRCODEGEN := vendor/QR-Code-generator/c/libqrcodegen.a
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import NimQml, os
|
import NimQml, strutils, os
|
||||||
|
|
||||||
import ../../constants
|
import ../../constants
|
||||||
|
|
||||||
|
@ -142,7 +142,8 @@ QtObject:
|
||||||
|
|
||||||
|
|
||||||
proc getTestEnvironment*(self: LocalAppSettings): bool {.slot.} =
|
proc getTestEnvironment*(self: LocalAppSettings): bool {.slot.} =
|
||||||
return existsEnv(TEST_ENVIRONMENT_VAR)
|
let value = getEnv(TEST_ENVIRONMENT_VAR)
|
||||||
|
return value.toUpperAscii() == "TRUE" or value == "1"
|
||||||
|
|
||||||
QtProperty[bool] testEnvironment:
|
QtProperty[bool] testEnvironment:
|
||||||
read = getTestEnvironment
|
read = getTestEnvironment
|
||||||
|
|
|
@ -353,6 +353,23 @@ method windowDeactivated*(self: AccessInterface) {.base.} =
|
||||||
method communityMembersRevealedAccountsLoaded*(self: AccessInterface, communityId: string, membersRevealedAccounts: MembersRevealedAccounts) {.base.} =
|
method communityMembersRevealedAccountsLoaded*(self: AccessInterface, communityId: string, membersRevealedAccounts: MembersRevealedAccounts) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
method registerMockedKeycard*(self: AccessInterface, cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method pluginMockedReaderAction*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method unplugMockedReaderAction*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method insertMockedKeycardAction*(self: AccessInterface, cardIndex: int) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method removeMockedKeycardAction*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
# This way (using concepts) is used only for the modules managed by AppController
|
# This way (using concepts) is used only for the modules managed by AppController
|
||||||
type
|
type
|
||||||
DelegateInterface* = concept c
|
DelegateInterface* = concept c
|
||||||
|
|
|
@ -1424,3 +1424,19 @@ method communityMembersRevealedAccountsLoaded*[T](self: Module[T], communityId:
|
||||||
|
|
||||||
self.view.model.setMembersAirdropAddress(communityId, communityMembersAirdropAddress)
|
self.view.model.setMembersAirdropAddress(communityId, communityMembersAirdropAddress)
|
||||||
|
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
method registerMockedKeycard*[T](self: Module[T], cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) =
|
||||||
|
self.keycardService.registerMockedKeycard(cardIndex, readerState, keycardState, mockedKeycard, mockedKeycardHelper)
|
||||||
|
|
||||||
|
method pluginMockedReaderAction*[T](self: Module[T]) =
|
||||||
|
self.keycardService.pluginMockedReaderAction()
|
||||||
|
|
||||||
|
method unplugMockedReaderAction*[T](self: Module[T]) =
|
||||||
|
self.keycardService.unplugMockedReaderAction()
|
||||||
|
|
||||||
|
method insertMockedKeycardAction*[T](self: Module[T], cardIndex: int) =
|
||||||
|
self.keycardService.insertMockedKeycardAction(cardIndex)
|
||||||
|
|
||||||
|
method removeMockedKeycardAction*[T](self: Module[T]) =
|
||||||
|
self.keycardService.removeMockedKeycardAction()
|
|
@ -296,3 +296,20 @@ QtObject:
|
||||||
proc showIncludeWatchOnlyAccountUpdated*(self: View, includeWatchOnly: bool) {.signal.}
|
proc showIncludeWatchOnlyAccountUpdated*(self: View, includeWatchOnly: bool) {.signal.}
|
||||||
proc showToastKeypairRemoved*(self: View, keypairName: string) {.signal.}
|
proc showToastKeypairRemoved*(self: View, keypairName: string) {.signal.}
|
||||||
proc showToastKeypairsImported*(self: View, keypairName: string, keypairsCount: int, error: string) {.signal.}
|
proc showToastKeypairsImported*(self: View, keypairName: string, keypairsCount: int, error: string) {.signal.}
|
||||||
|
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
proc registerMockedKeycard*(self: View, cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) {.slot.} =
|
||||||
|
self.delegate.registerMockedKeycard(cardIndex, readerState, keycardState, mockedKeycard, mockedKeycardHelper)
|
||||||
|
|
||||||
|
proc pluginMockedReaderAction*(self: View) {.slot.} =
|
||||||
|
self.delegate.pluginMockedReaderAction()
|
||||||
|
|
||||||
|
proc unplugMockedReaderAction*(self: View) {.slot.} =
|
||||||
|
self.delegate.unplugMockedReaderAction()
|
||||||
|
|
||||||
|
proc insertMockedKeycardAction*(self: View, cardIndex: int) {.slot.} =
|
||||||
|
self.delegate.insertMockedKeycardAction(cardIndex)
|
||||||
|
|
||||||
|
proc removeMockedKeycardAction*(self: View) {.slot.} =
|
||||||
|
self.delegate.removeMockedKeycardAction()
|
||||||
|
|
|
@ -195,6 +195,23 @@ method onReencryptionProcessStarted*(self: AccessInterface) {.base.} =
|
||||||
method onReencryptionProcessFinished*(self: AccessInterface) {.base.} =
|
method onReencryptionProcessFinished*(self: AccessInterface) {.base.} =
|
||||||
raise newException(ValueError, "No implementation available")
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
method registerMockedKeycard*(self: AccessInterface, cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method pluginMockedReaderAction*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method unplugMockedReaderAction*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method insertMockedKeycardAction*(self: AccessInterface, cardIndex: int) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
|
method removeMockedKeycardAction*(self: AccessInterface) {.base.} =
|
||||||
|
raise newException(ValueError, "No implementation available")
|
||||||
|
|
||||||
# This way (using concepts) is used only for the modules managed by AppController
|
# This way (using concepts) is used only for the modules managed by AppController
|
||||||
type
|
type
|
||||||
DelegateInterface* = concept c
|
DelegateInterface* = concept c
|
||||||
|
|
|
@ -553,3 +553,20 @@ method onReencryptionProcessFinished*[T](self: Module[T]) =
|
||||||
self.moveToStartupState()
|
self.moveToStartupState()
|
||||||
return
|
return
|
||||||
self.moveToLoadingAppState()
|
self.moveToLoadingAppState()
|
||||||
|
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
method registerMockedKeycard*[T](self: Module[T], cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) =
|
||||||
|
self.keycardService.registerMockedKeycard(cardIndex, readerState, keycardState, mockedKeycard, mockedKeycardHelper)
|
||||||
|
|
||||||
|
method pluginMockedReaderAction*[T](self: Module[T]) =
|
||||||
|
self.keycardService.pluginMockedReaderAction()
|
||||||
|
|
||||||
|
method unplugMockedReaderAction*[T](self: Module[T]) =
|
||||||
|
self.keycardService.unplugMockedReaderAction()
|
||||||
|
|
||||||
|
method insertMockedKeycardAction*[T](self: Module[T], cardIndex: int) =
|
||||||
|
self.keycardService.insertMockedKeycardAction(cardIndex)
|
||||||
|
|
||||||
|
method removeMockedKeycardAction*[T](self: Module[T]) =
|
||||||
|
self.keycardService.removeMockedKeycardAction()
|
|
@ -373,3 +373,20 @@ QtObject:
|
||||||
|
|
||||||
proc validateLocalPairingConnectionString*(self: View, connectionString: string): string {.slot.} =
|
proc validateLocalPairingConnectionString*(self: View, connectionString: string): string {.slot.} =
|
||||||
return self.delegate.validateLocalPairingConnectionString(connectionString)
|
return self.delegate.validateLocalPairingConnectionString(connectionString)
|
||||||
|
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
proc registerMockedKeycard*(self: View, cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) {.slot.} =
|
||||||
|
self.delegate.registerMockedKeycard(cardIndex, readerState, keycardState, mockedKeycard, mockedKeycardHelper)
|
||||||
|
|
||||||
|
proc pluginMockedReaderAction*(self: View) {.slot.} =
|
||||||
|
self.delegate.pluginMockedReaderAction()
|
||||||
|
|
||||||
|
proc unplugMockedReaderAction*(self: View) {.slot.} =
|
||||||
|
self.delegate.unplugMockedReaderAction()
|
||||||
|
|
||||||
|
proc insertMockedKeycardAction*(self: View, cardIndex: int) {.slot.} =
|
||||||
|
self.delegate.insertMockedKeycardAction(cardIndex)
|
||||||
|
|
||||||
|
proc removeMockedKeycardAction*(self: View) {.slot.} =
|
||||||
|
self.delegate.removeMockedKeycardAction()
|
|
@ -1,7 +1,8 @@
|
||||||
import NimQml, json, os, chronicles, random, strutils
|
import NimQml, json, os, chronicles, random, strutils
|
||||||
import keycard_go
|
import keycard_go
|
||||||
import ../../../app/core/eventemitter
|
import app/global/global_singleton
|
||||||
import ../../../app/core/tasks/[qt, threadpool]
|
import app/core/eventemitter
|
||||||
|
import app/core/tasks/[qt, threadpool]
|
||||||
import ../../../constants as status_const
|
import ../../../constants as status_const
|
||||||
|
|
||||||
import constants
|
import constants
|
||||||
|
@ -148,6 +149,50 @@ QtObject:
|
||||||
if self.doLogging:
|
if self.doLogging:
|
||||||
debug "keycardCancelFlow", kcServiceCurrFlow=($self.currentFlow), response=response
|
debug "keycardCancelFlow", kcServiceCurrFlow=($self.currentFlow), response=response
|
||||||
|
|
||||||
|
##########################################################
|
||||||
|
## Used in test env only, for testing keycard flows
|
||||||
|
proc registerMockedKeycard*(self: Service, cardIndex: int, readerState: int, keycardState: int,
|
||||||
|
mockedKeycard: string, mockedKeycardHelper: string) =
|
||||||
|
if not singletonInstance.localAppSettings.getTestEnvironment():
|
||||||
|
error "registerMockedKeycard can be used only in test env"
|
||||||
|
return
|
||||||
|
let response = keycard_go.mockedLibRegisterKeycard(cardIndex, readerState, keycardState, mockedKeycard, mockedKeycardHelper)
|
||||||
|
if self.doLogging:
|
||||||
|
debug "mockedLibRegisterKeycard", kcServiceCurrFlow=($self.currentFlow), cardIndex=cardIndex, readerState=readerState, keycardState=keycardState, mockedKeycard=mockedKeycard, mockedKeycardHelper=mockedKeycardHelper, response=response
|
||||||
|
|
||||||
|
proc pluginMockedReaderAction*(self: Service) =
|
||||||
|
if not singletonInstance.localAppSettings.getTestEnvironment():
|
||||||
|
error "pluginMockedReaderAction can be used only in test env"
|
||||||
|
return
|
||||||
|
let response = keycard_go.mockedLibReaderPluggedIn()
|
||||||
|
if self.doLogging:
|
||||||
|
debug "mockedLibReaderPluggedIn", kcServiceCurrFlow=($self.currentFlow), response=response
|
||||||
|
|
||||||
|
proc unplugMockedReaderAction*(self: Service) =
|
||||||
|
if not singletonInstance.localAppSettings.getTestEnvironment():
|
||||||
|
error "unplugMockedReaderAction can be used only in test env"
|
||||||
|
return
|
||||||
|
let response = keycard_go.mockedLibReaderUnplugged()
|
||||||
|
if self.doLogging:
|
||||||
|
debug "mockedLibReaderUnplugged", kcServiceCurrFlow=($self.currentFlow), response=response
|
||||||
|
|
||||||
|
proc insertMockedKeycardAction*(self: Service, cardIndex: int) =
|
||||||
|
if not singletonInstance.localAppSettings.getTestEnvironment():
|
||||||
|
error "insertMockedKeycardAction can be used only in test env"
|
||||||
|
return
|
||||||
|
let response = keycard_go.mockedLibKeycardInserted(cardIndex)
|
||||||
|
if self.doLogging:
|
||||||
|
debug "mockedLibKeycardInserted", kcServiceCurrFlow=($self.currentFlow), cardIndex=cardIndex, response=response
|
||||||
|
|
||||||
|
proc removeMockedKeycardAction*(self: Service) =
|
||||||
|
if not singletonInstance.localAppSettings.getTestEnvironment():
|
||||||
|
error "removeMockedKeycardAction can be used only in test env"
|
||||||
|
return
|
||||||
|
let response = keycard_go.mockedLibKeycardRemoved()
|
||||||
|
if self.doLogging:
|
||||||
|
debug "mockedLibKeycardRemoved", kcServiceCurrFlow=($self.currentFlow), response=response
|
||||||
|
##########################################################
|
||||||
|
|
||||||
proc generateRandomPUK*(self: Service): string =
|
proc generateRandomPUK*(self: Service): string =
|
||||||
randomize()
|
randomize()
|
||||||
for i in 0 ..< PUKLengthForStatusApp:
|
for i in 0 ..< PUKLengthForStatusApp:
|
||||||
|
|
|
@ -8,6 +8,7 @@ import StatusQ.Core.Theme 0.1
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
import shared.popups.keycard 1.0
|
import shared.popups.keycard 1.0
|
||||||
|
import shared.panels 1.0
|
||||||
|
|
||||||
import "controls"
|
import "controls"
|
||||||
import "views"
|
import "views"
|
||||||
|
@ -30,6 +31,16 @@ OnboardingBasePage {
|
||||||
loader.sourceComponent = undefined
|
loader.sourceComponent = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockedKeycardLibFlowController {
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.topMargin: Style.current.bigPadding
|
||||||
|
anchors.leftMargin: 4 * Style.current.bigPadding
|
||||||
|
visible: localAppSettings.testEnvironment
|
||||||
|
|
||||||
|
relatedModule: root.startupStore.startupModuleInst
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: loader
|
id: loader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
|
@ -1622,4 +1622,20 @@ Item {
|
||||||
onClosed: userAgreementLoader.active = false
|
onClosed: userAgreementLoader.active = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: mockedKeycardLibInitialController
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
active: localAppSettings.testEnvironment
|
||||||
|
|
||||||
|
sourceComponent: MockedKeycardLibInitialController {
|
||||||
|
width: 450
|
||||||
|
height: 500
|
||||||
|
|
||||||
|
onClose: {
|
||||||
|
mockedKeycardLibInitialController.active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Popups 0.1
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string title
|
||||||
|
property int selectedState: MockedKeycardReaderStateSelector.State.NoReader
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
NoReader,
|
||||||
|
NoKeycard,
|
||||||
|
KeycardInserted
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
|
||||||
|
readonly property string readerStateReaderUnplugged: qsTr("Reader Unplugged")
|
||||||
|
readonly property string readerStateKeycardNotInserted: qsTr("Keycard Not Inserted")
|
||||||
|
readonly property string readerStateKeycardInserted: qsTr("Keycard Inserted")
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: root.title
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
id: selectReaderStateButton
|
||||||
|
|
||||||
|
text: {
|
||||||
|
switch (root.selectedState) {
|
||||||
|
case MockedKeycardReaderStateSelector.State.NoReader:
|
||||||
|
return d.readerStateReaderUnplugged
|
||||||
|
case MockedKeycardReaderStateSelector.State.NoKeycard:
|
||||||
|
return d.readerStateKeycardNotInserted
|
||||||
|
case MockedKeycardReaderStateSelector.State.KeycardInserted:
|
||||||
|
return d.readerStateKeycardInserted
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
icon.name: "chevron-down"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (initialReaderState.opened) {
|
||||||
|
initialReaderState.close()
|
||||||
|
} else {
|
||||||
|
initialReaderState.popup(selectReaderStateButton.x, selectReaderStateButton.y + selectReaderStateButton.height + 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusMenu {
|
||||||
|
id: initialReaderState
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.readerStateReaderUnplugged
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardReaderStateSelector.State.NoReader
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.readerStateKeycardNotInserted
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardReaderStateSelector.State.NoKeycard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.readerStateKeycardInserted
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardReaderStateSelector.State.KeycardInserted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Controls 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Popups 0.1
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string title
|
||||||
|
property int selectedState: MockedKeycardStateSelector.State.EmptyKeycard
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
NotStatusKeycard,
|
||||||
|
EmptyKeycard,
|
||||||
|
MaxPairingSlotsReached,
|
||||||
|
MaxPINRetriesReached,
|
||||||
|
MaxPUKRetriesReached,
|
||||||
|
KeycardWithMnemonicOnly,
|
||||||
|
KeycardWithMnemonicAndMedatada,
|
||||||
|
CustomKeycard // should be always the last option
|
||||||
|
}
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
|
||||||
|
readonly property string kcStateNotStatusKeycard: qsTr("Not Status Keycard")
|
||||||
|
readonly property string kcStateEmptyKeycard: qsTr("Empty Keycard")
|
||||||
|
readonly property string kcStateMaxPairingSlotsReached: qsTr("Max Pairing Slots Reached")
|
||||||
|
readonly property string kcStateMaxPINRetriesReached: qsTr("Max PIN Retries Reached")
|
||||||
|
readonly property string kcStateMaxPUKRetriesReached: qsTr("Max PUK Retries Reached")
|
||||||
|
readonly property string kcStateKeycardWithMnemonicOnly: qsTr("Keycard With Mnemonic Only")
|
||||||
|
readonly property string kcStateKeycardWithMnemonicAndMedatada: qsTr("Keycard With Mnemonic & Metadata")
|
||||||
|
readonly property string kcStateCustomKeycard: qsTr("Custom Keycard")
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: root.title
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
id: selectKeycardsStateButton
|
||||||
|
|
||||||
|
text: {
|
||||||
|
switch (root.selectedState) {
|
||||||
|
case MockedKeycardStateSelector.State.NotStatusKeycard:
|
||||||
|
return d.kcStateNotStatusKeycard
|
||||||
|
case MockedKeycardStateSelector.State.EmptyKeycard:
|
||||||
|
return d.kcStateEmptyKeycard
|
||||||
|
case MockedKeycardStateSelector.State.MaxPairingSlotsReached:
|
||||||
|
return d.kcStateMaxPairingSlotsReached
|
||||||
|
case MockedKeycardStateSelector.State.MaxPINRetriesReached:
|
||||||
|
return d.kcStateMaxPINRetriesReached
|
||||||
|
case MockedKeycardStateSelector.State.MaxPUKRetriesReached:
|
||||||
|
return d.kcStateMaxPUKRetriesReached
|
||||||
|
case MockedKeycardStateSelector.State.KeycardWithMnemonicOnly:
|
||||||
|
return d.kcStateKeycardWithMnemonicOnly
|
||||||
|
case MockedKeycardStateSelector.State.KeycardWithMnemonicAndMedatada:
|
||||||
|
return d.kcStateKeycardWithMnemonicAndMedatada
|
||||||
|
case MockedKeycardStateSelector.State.CustomKeycard:
|
||||||
|
return d.kcStateCustomKeycard
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
icon.name: "chevron-down"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (initialKeycardState.opened) {
|
||||||
|
initialKeycardState.close()
|
||||||
|
} else {
|
||||||
|
initialKeycardState.popup(selectKeycardsStateButton.x, selectKeycardsStateButton.y + selectKeycardsStateButton.height + 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusMenu {
|
||||||
|
id: initialKeycardState
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateNotStatusKeycard
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.NotStatusKeycard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateEmptyKeycard
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.EmptyKeycard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateMaxPairingSlotsReached
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.MaxPairingSlotsReached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateMaxPINRetriesReached
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.MaxPINRetriesReached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateMaxPUKRetriesReached
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.MaxPUKRetriesReached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateKeycardWithMnemonicOnly
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.KeycardWithMnemonicOnly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateKeycardWithMnemonicAndMedatada
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.KeycardWithMnemonicAndMedatada
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusAction {
|
||||||
|
text: d.kcStateCustomKeycard
|
||||||
|
onTriggered: {
|
||||||
|
root.selectedState = MockedKeycardStateSelector.State.CustomKeycard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,3 +41,5 @@ TransactionAddressTile 1.0 TransactionAddressTile.qml
|
||||||
TransactionDataTile 1.0 TransactionDataTile.qml
|
TransactionDataTile 1.0 TransactionDataTile.qml
|
||||||
TransactionDelegate 1.0 TransactionDelegate.qml
|
TransactionDelegate 1.0 TransactionDelegate.qml
|
||||||
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
||||||
|
MockedKeycardReaderStateSelector 1.0 MockedKeycardReaderStateSelector.qml
|
||||||
|
MockedKeycardStateSelector 1.0 MockedKeycardStateSelector.qml
|
|
@ -0,0 +1,65 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var relatedModule
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Plugin R")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!!root.relatedModule) {
|
||||||
|
root.relatedModule.pluginMockedReaderAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Unplug R")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!!root.relatedModule) {
|
||||||
|
root.relatedModule.unplugMockedReaderAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Ins Kc 1")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!!root.relatedModule) {
|
||||||
|
root.relatedModule.insertMockedKeycardAction(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Ins Kc 2")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!!root.relatedModule) {
|
||||||
|
root.relatedModule.insertMockedKeycardAction(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Remove Kc")
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (!!root.relatedModule) {
|
||||||
|
root.relatedModule.removeMockedKeycardAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,213 @@
|
||||||
|
import QtQuick 2.14
|
||||||
|
import QtQuick.Layouts 1.14
|
||||||
|
|
||||||
|
import StatusQ.Core 0.1
|
||||||
|
import StatusQ.Controls 0.1
|
||||||
|
import StatusQ.Core.Theme 0.1
|
||||||
|
|
||||||
|
import shared.controls 1.0
|
||||||
|
|
||||||
|
import utils 1.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
color: Style.current.modalBackground
|
||||||
|
radius: Style.current.radius
|
||||||
|
border.color: Style.current.grey3
|
||||||
|
border.width: 2
|
||||||
|
|
||||||
|
signal close()
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
id: d
|
||||||
|
|
||||||
|
property int btnWidth: 30
|
||||||
|
property int btnHeight: 30
|
||||||
|
property int margin: 8
|
||||||
|
|
||||||
|
property bool minimized: false
|
||||||
|
property int maxWidth
|
||||||
|
property int maxHeight
|
||||||
|
onMinimizedChanged: {
|
||||||
|
if (minimized) {
|
||||||
|
d.maxWidth = root.width
|
||||||
|
d.maxHeight = root.height
|
||||||
|
root.width = header.implicitWidth + 2 * d.margin
|
||||||
|
root.height = header.implicitHeight + 2 * d.margin
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root.width = d.maxWidth
|
||||||
|
root.height = d.maxHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: header
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: d.margin
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: d.margin
|
||||||
|
spacing: d.margin
|
||||||
|
|
||||||
|
StatusFlatRoundButton {
|
||||||
|
type: StatusFlatRoundButton.Type.Secondary
|
||||||
|
icon.name: d.minimized? "chevron-up" : "chevron-down"
|
||||||
|
icon.color: Theme.palette.directColor1
|
||||||
|
implicitWidth: d.btnWidth
|
||||||
|
implicitHeight: d.btnHeight
|
||||||
|
onClicked: {
|
||||||
|
d.minimized = !d.minimized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusFlatRoundButton {
|
||||||
|
type: StatusFlatRoundButton.Type.Secondary
|
||||||
|
icon.name: "close"
|
||||||
|
icon.color: Theme.palette.directColor1
|
||||||
|
implicitWidth: d.btnWidth
|
||||||
|
implicitHeight: d.btnHeight
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MockedKeycardReaderStateSelector {
|
||||||
|
id: readerState
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.topMargin: Style.current.bigPadding
|
||||||
|
anchors.leftMargin: Style.current.bigPadding
|
||||||
|
visible: !d.minimized
|
||||||
|
title: qsTr("Initial reader state")
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusTabBar {
|
||||||
|
id: tabBar
|
||||||
|
anchors.top: readerState.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: Style.current.bigPadding
|
||||||
|
visible: !d.minimized
|
||||||
|
|
||||||
|
StatusTabButton {
|
||||||
|
width: implicitWidth
|
||||||
|
leftPadding: 0
|
||||||
|
text: qsTr("Keycard-1")
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusTabButton {
|
||||||
|
width: implicitWidth
|
||||||
|
text: qsTr("Keycard-2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StackLayout {
|
||||||
|
anchors.top: tabBar.bottom
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.margins: Style.current.halfPadding
|
||||||
|
visible: !d.minimized
|
||||||
|
currentIndex: tabBar.currentIndex
|
||||||
|
|
||||||
|
KeycardSettingsTab {
|
||||||
|
cardIndex: 1
|
||||||
|
|
||||||
|
onRegisterKeycard: {
|
||||||
|
mainModule.registerMockedKeycard(cardIndex, readerState.selectedState, kcState, kc, kcHelper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeycardSettingsTab {
|
||||||
|
cardIndex: 2
|
||||||
|
|
||||||
|
onRegisterKeycard: {
|
||||||
|
mainModule.registerMockedKeycard(cardIndex, MockedKeycardReaderStateSelector.NoKeycard, kcState, kc, kcHelper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component KeycardSettingsTab: StatusScrollView {
|
||||||
|
id: keycardSettingsTabRoot
|
||||||
|
|
||||||
|
property int cardIndex
|
||||||
|
|
||||||
|
signal registerKeycard(int kcState, string kc, string kcHelper)
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
MockedKeycardStateSelector {
|
||||||
|
id: keycardState
|
||||||
|
title: qsTr("Keycard %1 - initial keycard state").arg(keycardSettingsTabRoot.cardIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: customSection
|
||||||
|
visible: keycardState.selectedState === MockedKeycardStateSelector.CustomKeycard
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
StatusInput {
|
||||||
|
id: mockedKeycard
|
||||||
|
label: qsTr("Mocked Keycard")
|
||||||
|
implicitWidth: 400
|
||||||
|
minimumHeight: 200
|
||||||
|
maximumHeight: 200
|
||||||
|
input.multiline: true
|
||||||
|
input.verticalAlignment: TextEdit.AlignTop
|
||||||
|
placeholderText: qsTr("Enter json form of status-go MockedKeycard")
|
||||||
|
errorMessageCmp.text: qsTr("Invalid json format")
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusInput {
|
||||||
|
id: mockedKeycardHelper
|
||||||
|
label: qsTr("Specific keycard details")
|
||||||
|
implicitWidth: 400
|
||||||
|
minimumHeight: 200
|
||||||
|
maximumHeight: 200
|
||||||
|
input.multiline: true
|
||||||
|
input.verticalAlignment: TextEdit.AlignTop
|
||||||
|
placeholderText: qsTr("Enter json form of status-go MockedKeycard")
|
||||||
|
errorMessageCmp.text: qsTr("Invalid json format")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
text: qsTr("Register Keycard")
|
||||||
|
onClicked: {
|
||||||
|
if (customSection.visible) {
|
||||||
|
mockedKeycard.input.valid = true
|
||||||
|
mockedKeycardHelper.input.valid = true
|
||||||
|
|
||||||
|
if (mockedKeycard.text != "") {
|
||||||
|
try {
|
||||||
|
JSON.parse(mockedKeycard.text)
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
mockedKeycard.input.valid = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mockedKeycardHelper.text != "") {
|
||||||
|
try {
|
||||||
|
JSON.parse(mockedKeycardHelper.text)
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
mockedKeycardHelper.input.valid = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mockedKeycard.input.valid || !mockedKeycardHelper.input.valid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keycardSettingsTabRoot.registerKeycard(keycardState.selectedState,
|
||||||
|
mockedKeycard.text,
|
||||||
|
mockedKeycardHelper.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,3 +25,5 @@ StatusAssetSelector 1.0 StatusAssetSelector.qml
|
||||||
StyledText 1.0 StyledText.qml
|
StyledText 1.0 StyledText.qml
|
||||||
TextWithLabel 1.0 TextWithLabel.qml
|
TextWithLabel 1.0 TextWithLabel.qml
|
||||||
DropAndEditImagePanel 1.0 DropAndEditImagePanel.qml
|
DropAndEditImagePanel 1.0 DropAndEditImagePanel.qml
|
||||||
|
MockedKeycardLibFlowController 1.0 MockedKeycardLibFlowController.qml
|
||||||
|
MockedKeycardLibInitialController 1.0 MockedKeycardLibInitialController.qml
|
||||||
|
|
|
@ -83,21 +83,23 @@ StatusModal {
|
||||||
id: content
|
id: content
|
||||||
width: scrollView.availableWidth
|
width: scrollView.availableWidth
|
||||||
implicitHeight: {
|
implicitHeight: {
|
||||||
|
let additionalHeight = localAppSettings.testEnvironment? 60 : 0
|
||||||
|
|
||||||
// for all flows
|
// for all flows
|
||||||
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
|
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
|
||||||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.factoryResetConfirmationDisplayMetadata) {
|
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.factoryResetConfirmationDisplayMetadata) {
|
||||||
if (!root.sharedKeycardModule.keyPairStoredOnKeycardIsKnown) {
|
if (!root.sharedKeycardModule.keyPairStoredOnKeycardIsKnown) {
|
||||||
return Constants.keycard.general.popupBiggerHeight
|
return Constants.keycard.general.popupBiggerHeight + additionalHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard &&
|
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard &&
|
||||||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.manageKeycardAccounts &&
|
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.manageKeycardAccounts &&
|
||||||
root.sharedKeycardModule.keyPairHelper.accounts.count > 1) {
|
root.sharedKeycardModule.keyPairHelper.accounts.count > 1) {
|
||||||
return Constants.keycard.general.popupBiggerHeight
|
return Constants.keycard.general.popupBiggerHeight + additionalHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
return Constants.keycard.general.popupHeight
|
return Constants.keycard.general.popupHeight + additionalHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedKeycardModule: root.sharedKeycardModule
|
sharedKeycardModule: root.sharedKeycardModule
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
|
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
import shared.panels 1.0
|
||||||
|
|
||||||
import "./states"
|
import "./states"
|
||||||
|
|
||||||
|
@ -18,9 +19,26 @@ Item {
|
||||||
property bool primaryButtonEnabled: false
|
property bool primaryButtonEnabled: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockedKeycardLibFlowController {
|
||||||
|
id: mockedLibFlowController
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: Style.current.padding
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
visible: localAppSettings.testEnvironment
|
||||||
|
|
||||||
|
relatedModule: mainModule
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: loader
|
id: loader
|
||||||
anchors.fill: parent
|
|
||||||
|
anchors.top: mockedLibFlowController.visible? mockedLibFlowController.bottom : parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
switch (root.sharedKeycardModule.currentState.stateType) {
|
switch (root.sharedKeycardModule.currentState.stateType) {
|
||||||
case Constants.keycardSharedState.biometrics:
|
case Constants.keycardSharedState.biometrics:
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6a4bed51d53f3ef8d1eaff038e08449c288c8334
|
Subproject commit a1724bad72e83ca83df2632d83a631cd8d8ff0f6
|
|
@ -1 +1 @@
|
||||||
Subproject commit c6b7095a85f04fe798e4847406967beb0d3566d3
|
Subproject commit 1a86f57a96932ff248f767487ce41575ee1c4b7c
|
Loading…
Reference in New Issue