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)")
|
||||
export STATUSKEYCARDGO_LIBDIR
|
||||
|
||||
STATUSKEYCARDGO_RULE := build-lib
|
||||
ifeq ($(TEST_ENVIRONMENT),true)
|
||||
STATUSKEYCARDGO_RULE := build-mocked-lib
|
||||
endif
|
||||
|
||||
status-keycard-go: $(STATUSKEYCARDGO)
|
||||
$(STATUSKEYCARDGO): | deps
|
||||
echo -e $(BUILD_MSG) "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
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, os
|
||||
import NimQml, strutils, os
|
||||
|
||||
import ../../constants
|
||||
|
||||
|
@ -142,7 +142,8 @@ QtObject:
|
|||
|
||||
|
||||
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:
|
||||
read = getTestEnvironment
|
||||
|
|
|
@ -353,6 +353,23 @@ method windowDeactivated*(self: AccessInterface) {.base.} =
|
|||
method communityMembersRevealedAccountsLoaded*(self: AccessInterface, communityId: string, membersRevealedAccounts: MembersRevealedAccounts) {.base.} =
|
||||
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
|
||||
type
|
||||
DelegateInterface* = concept c
|
||||
|
|
|
@ -1424,3 +1424,19 @@ method communityMembersRevealedAccountsLoaded*[T](self: Module[T], communityId:
|
|||
|
||||
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 showToastKeypairRemoved*(self: View, keypairName: 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.} =
|
||||
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
|
||||
type
|
||||
DelegateInterface* = concept c
|
||||
|
|
|
@ -553,3 +553,20 @@ method onReencryptionProcessFinished*[T](self: Module[T]) =
|
|||
self.moveToStartupState()
|
||||
return
|
||||
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.} =
|
||||
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 keycard_go
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
import app/global/global_singleton
|
||||
import app/core/eventemitter
|
||||
import app/core/tasks/[qt, threadpool]
|
||||
import ../../../constants as status_const
|
||||
|
||||
import constants
|
||||
|
@ -148,6 +149,50 @@ QtObject:
|
|||
if self.doLogging:
|
||||
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 =
|
||||
randomize()
|
||||
for i in 0 ..< PUKLengthForStatusApp:
|
||||
|
|
|
@ -8,6 +8,7 @@ import StatusQ.Core.Theme 0.1
|
|||
|
||||
import utils 1.0
|
||||
import shared.popups.keycard 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import "controls"
|
||||
import "views"
|
||||
|
@ -30,6 +31,16 @@ OnboardingBasePage {
|
|||
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 {
|
||||
id: loader
|
||||
anchors.fill: parent
|
||||
|
|
|
@ -1622,4 +1622,20 @@ Item {
|
|||
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
|
||||
TransactionDelegate 1.0 TransactionDelegate.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
|
||||
TextWithLabel 1.0 TextWithLabel.qml
|
||||
DropAndEditImagePanel 1.0 DropAndEditImagePanel.qml
|
||||
MockedKeycardLibFlowController 1.0 MockedKeycardLibFlowController.qml
|
||||
MockedKeycardLibInitialController 1.0 MockedKeycardLibInitialController.qml
|
||||
|
|
|
@ -83,21 +83,23 @@ StatusModal {
|
|||
id: content
|
||||
width: scrollView.availableWidth
|
||||
implicitHeight: {
|
||||
let additionalHeight = localAppSettings.testEnvironment? 60 : 0
|
||||
|
||||
// for all flows
|
||||
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay ||
|
||||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.factoryResetConfirmationDisplayMetadata) {
|
||||
if (!root.sharedKeycardModule.keyPairStoredOnKeycardIsKnown) {
|
||||
return Constants.keycard.general.popupBiggerHeight
|
||||
return Constants.keycard.general.popupBiggerHeight + additionalHeight
|
||||
}
|
||||
}
|
||||
|
||||
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.importFromKeycard &&
|
||||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.manageKeycardAccounts &&
|
||||
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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.14
|
||||
|
||||
import utils 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import "./states"
|
||||
|
||||
|
@ -18,9 +19,26 @@ Item {
|
|||
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 {
|
||||
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: {
|
||||
switch (root.sharedKeycardModule.currentState.stateType) {
|
||||
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