feat(@desktop/keycard): initial UI for the keycard settings

This is just a wireframe implementation, without any special functionalities.

Fixes: #7023
This commit is contained in:
Sale Djenic 2022-08-16 11:19:15 +02:00 committed by saledjenic
parent 1c77192d5b
commit 398f62806f
16 changed files with 360 additions and 7 deletions

View File

@ -227,7 +227,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.gifService,
result.ensService,
result.networkService,
result.generalService
result.generalService,
result.keycardService
)
# Do connections

View File

@ -52,6 +52,7 @@ import ../../../app_service/service/gif/service as gif_service
import ../../../app_service/service/ens/service as ens_service
import ../../../app_service/service/network/service as network_service
import ../../../app_service/service/general/service as general_service
import ../../../app_service/service/keycard/service as keycard_service
from ../../../app_service/common/types import StatusType
import ../../../app_service/common/social_links
@ -120,7 +121,8 @@ proc newModule*[T](
gifService: gif_service.Service,
ensService: ens_service.Service,
networkService: network_service.Service,
generalService: general_service.Service
generalService: general_service.Service,
keycardService: keycard_service.Service
): Module[T] =
result = Module[T]()
result.delegate = delegate
@ -158,7 +160,7 @@ proc newModule*[T](
result, events, accountsService, settingsService, stickersService,
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
devicesService, mailserversService, chatService, ensService, walletAccountService, generalService, communityService,
networkService,
networkService, keycardService
)
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService, networkService)
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,

View File

@ -85,3 +85,6 @@ method getCommunitiesModule*(self: AccessInterface): QVariant {.base.} =
method communitiesModuleDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method getKeycardModule*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -0,0 +1,26 @@
import chronicles
import io_interface
import ../../../../core/eventemitter
logScope:
topics = "profile-section-keycard-module-controller"
type
Controller* = ref object of RootObj
delegate: io_interface.AccessInterface
events: EventEmitter
proc newController*(delegate: io_interface.AccessInterface,
events: EventEmitter):
Controller =
result = Controller()
result.delegate = delegate
result.events = events
proc delete*(self: Controller) =
discard
proc init*(self: Controller) =
discard

View File

@ -0,0 +1,23 @@
import NimQml
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
## Abstract class for any input/interaction with this module.
method delete*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method load*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method isLoaded*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface
# Delegate for the view must be declared here due to use of QtObject and multi
# inheritance, which is not well supported in Nim.
method viewDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -0,0 +1,58 @@
import NimQml, chronicles
import ./io_interface, ./view, ./controller
import ../io_interface as delegate_interface
import ../../../../core/eventemitter
import ../../../../../app_service/service/keycard/service as keycard_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
export io_interface
logScope:
topics = "profile-section-profile-module"
type
Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface
controller: Controller
view: View
viewVariant: QVariant
moduleLoaded: bool
events: EventEmitter
keycardService: keycard_service.Service
walletAccountService: wallet_account_service.Service
proc newModule*(delegate: delegate_interface.AccessInterface,
events: EventEmitter,
keycardService: keycard_service.Service,
walletAccountService: wallet_account_service.Service): Module =
result = Module()
result.delegate = delegate
result.events = events
result.keycardService = keycardService
result.walletAccountService = walletAccountService
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events)
result.moduleLoaded = false
method delete*(self: Module) =
self.view.delete
self.viewVariant.delete
self.controller.delete
method load*(self: Module) =
self.controller.init()
self.view.load()
method isLoaded*(self: Module): bool =
return self.moduleLoaded
method viewDidLoad*(self: Module) =
self.moduleLoaded = true
self.delegate.profileModuleDidLoad()
method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant

View File

@ -0,0 +1,20 @@
import NimQml
import ./io_interface
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
proc delete*(self: View) =
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
new(result, delete)
result.QObject.setup
result.delegate = delegate
proc load*(self: View) =
self.delegate.viewDidLoad()

View File

@ -20,7 +20,7 @@ import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/general/service as general_service
import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/keycard/service as keycard_service
import ./profile/module as profile_module
import ./contacts/module as contacts_module
@ -33,6 +33,7 @@ import ./sync/module as sync_module
import ./notifications/module as notifications_module
import ./ens_usernames/module as ens_usernames_module
import ./communities/module as communities_module
import ./keycard/module as keycard_module
export io_interface
@ -55,6 +56,7 @@ type
notificationsModule: notifications_module.AccessInterface
ensUsernamesModule: ens_usernames_module.AccessInterface
communitiesModule: communities_module.AccessInterface
keycardModule: keycard_module.AccessInterface
proc newModule*(delegate: delegate_interface.AccessInterface,
events: EventEmitter,
@ -75,6 +77,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
generalService: general_service.Service,
communityService: community_service.Service,
networkService: network_service.Service,
keycardService: keycard_service.Service
): Module =
result = Module()
result.delegate = delegate
@ -96,6 +99,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
result, events, settingsService, ensService, walletAccountService, networkService
)
result.communitiesModule = communities_module.newModule(result, communityService)
result.keycardModule = keycard_module.newModule(result, events, keycardService, walletAccountService)
singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant)
@ -109,6 +113,7 @@ method delete*(self: Module) =
self.devicesModule.delete
self.syncModule.delete
self.communitiesModule.delete
self.keycardModule.delete
self.view.delete
self.viewVariant.delete
@ -127,6 +132,7 @@ method load*(self: Module) =
self.notificationsModule.load()
self.ensUsernamesModule.load()
self.communitiesModule.load()
self.keycardModule.load()
method isLoaded*(self: Module): bool =
return self.moduleLoaded
@ -165,6 +171,9 @@ proc checkIfModuleDidLoad(self: Module) =
if(not self.communitiesModule.isLoaded()):
return
if(not self.keycardModule.isLoaded()):
return
self.moduleLoaded = true
self.delegate.profileSectionDidLoad()
@ -232,4 +241,7 @@ method getCommunitiesModule*(self: Module): QVariant =
self.communitiesModule.getModuleAsVariant()
method communitiesModuleDidLoad*(self: Module) =
self.checkIfModuleDidLoad()
self.checkIfModuleDidLoad()
method getKeycardModule*(self: Module): QVariant =
self.keycardModule.getModuleAsVariant()

View File

@ -70,3 +70,8 @@ QtObject:
return self.delegate.getCommunitiesModule()
QtProperty[QVariant] communitiesModule:
read = getCommunitiesModule
proc getKeycardModule(self: View): QVariant {.slot.} =
return self.delegate.getKeycardModule()
QtProperty[QVariant] keycardModule:
read = getKeycardModule

View File

@ -222,6 +222,15 @@ StatusAppTwoPanelLayout {
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.communitiesSettings)
contentWidth: d.contentWidth
}
KeycardView {
implicitWidth: parent.width
implicitHeight: parent.height
keycardStore: profileView.store.keycardStore
sectionTitle: profileView.store.getNameForSubsection(Constants.settingsSubsection.keycard)
contentWidth: d.contentWidth
}
}
} // Item
ModuleWarning {

View File

@ -0,0 +1,9 @@
import QtQuick 2.13
import utils 1.0
QtObject {
id: root
property var keycardModule
}

View File

@ -55,6 +55,10 @@ QtObject {
property WalletStore walletStore: WalletStore {
}
property KeycardStore keycardStore: KeycardStore {
keycardModule: profileSectionModuleInst.keycardModule
}
property var stickersModuleInst: stickersModule
property var stickersStore: StickersStore {
stickersModule: stickersModuleInst
@ -75,6 +79,9 @@ QtObject {
append({subsection: Constants.settingsSubsection.profile,
text: qsTr("Profile"),
icon: "profile"})
append({subsection: Constants.settingsSubsection.keycard,
text: qsTr("Keycard"),
icon: "keycard"})
append({subsection: Constants.settingsSubsection.ensUsernames,
text: qsTr("ENS usernames"),
icon: "username"})

View File

@ -0,0 +1,167 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Popups 0.1
import utils 1.0
import shared.panels 1.0
import shared.controls 1.0
import shared.status 1.0
import "../stores"
import "../controls"
import "../panels"
SettingsContentBase {
id: root
property KeycardStore keycardStore
titleRowComponentLoader.sourceComponent: StatusButton {
text: qsTr("Get Keycard")
onClicked: {
console.warn("TODO: Go to purchase page...")
}
}
ColumnLayout {
id: contentColumn
spacing: Constants.settingsSection.itemSpacing
Image {
Layout.alignment: Qt.AlignCenter
Layout.preferredHeight: sourceSize.height
Layout.preferredWidth: sourceSize.width
fillMode: Image.PreserveAspectFit
antialiasing: true
source: Style.png("keycard/security-keycard@2x")
mipmap: true
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: Style.current.halfPadding
}
StyledText {
Layout.alignment: Qt.AlignCenter
font.pixelSize: Constants.settingsSection.importantInfoFontSize
color: Style.current.directColor1
text: qsTr("Secure your funds. Keep your profile safe.")
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: Style.current.halfPadding
}
StatusListItem {
Layout.preferredWidth: root.contentWidth
title: qsTr("Setup a new Keycard with an existing account")
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: {
console.warn("TODO: Run Set up Keycard flow...")
}
}
StatusSectionHeadline {
Layout.preferredWidth: root.contentWidth
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Create, import or restore a Keycard account")
}
StatusListItem {
Layout.preferredWidth: root.contentWidth
title: qsTr("Generate a seed phrase")
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: {
console.warn("TODO: Generate a seed phrase...")
}
}
StatusListItem {
Layout.preferredWidth: root.contentWidth
title: qsTr("Import or restore via a seed phrase")
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: {
console.warn("TODO: Import or restore via a seed phrase...")
}
}
StatusListItem {
Layout.preferredWidth: root.contentWidth
title: qsTr("Import from Keycard to Status Desktop")
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: {
console.warn("TODO: Import from Keycard to Status Desktop...")
}
}
StatusSectionHeadline {
Layout.preferredWidth: root.contentWidth
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
text: qsTr("Other")
}
StatusListItem {
Layout.preferredWidth: root.contentWidth
title: qsTr("Check whats on a Keycard")
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: {
console.warn("TODO: Check whats on a Keycard...")
}
}
StatusListItem {
Layout.preferredWidth: root.contentWidth
title: qsTr("Factory reset a Keycard")
components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
}
]
sensor.onClicked: {
console.warn("TODO: Factory reset a Keycard...")
}
}
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -132,8 +132,9 @@ QtObject {
property int advanced: 10
property int about: 11
property int communitiesSettings: 12
property int signout: 13
property int backUpSeed: 14
property int keycard: 13
property int signout: 14
property int backUpSeed: 15
}
readonly property QtObject currentUserStatus: QtObject{
@ -273,6 +274,7 @@ QtObject {
readonly property int radius: 8
readonly property int mainHeaderFontSize: 28
readonly property int subHeaderFontSize: 15
readonly property int importantInfoFontSize: 18
readonly property int infoFontSize: 15
readonly property int infoLineHeight: 22
readonly property int infoSpacing: 5