From 30f11c06d420a9e6be0348de5c84c62c7e3ce02a Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Thu, 14 Oct 2021 10:04:15 +0200 Subject: [PATCH] onboarding process updated, import account feature handled --- src/app/boot/app_controller.nim | 9 +- src/app/modules/startup/controller.nim | 20 +- .../modules/startup/controller_interface.nim | 5 - src/app/modules/startup/io_interface.nim | 29 ++- .../modules/startup/login/account_item.nim | 63 ++++++ src/app/modules/startup/login/controller.nim | 19 +- .../startup/login/controller_interface.nim | 12 +- .../modules/startup/login/io_interface.nim | 30 +-- src/app/modules/startup/login/item.nim | 21 -- src/app/modules/startup/login/model.nim | 61 +++++- src/app/modules/startup/login/module.nim | 56 +++-- .../module_base_interface.nim | 5 + .../module_controller_delegate_interface.nim | 0 .../module_view_delegate_interface.nim | 2 + src/app/modules/startup/login/view.nim | 41 +++- src/app/modules/startup/module.nim | 49 ++--- .../modules/startup/onboarding/controller.nim | 58 ++++-- .../onboarding/controller_interface.nim | 16 +- .../startup/onboarding/io_interface.nim | 37 +--- src/app/modules/startup/onboarding/model.nim | 2 +- src/app/modules/startup/onboarding/module.nim | 60 ++++-- .../module_base_interface.nim | 5 + .../module_controller_delegate_interface.nim | 11 + .../module_view_delegate_interface.nim | 21 ++ src/app/modules/startup/onboarding/view.nim | 55 ++++- .../module_access_interface.nim | 8 + .../module_base_interface.nim | 5 + .../module_controller_delegate_interface.nim | 0 .../module_login_delegate_interface.nim | 2 + .../module_onboarding_delegate_interface.nim | 5 + .../module_view_delegate_interface.nim | 2 + src/app/modules/startup/view.nim | 30 +-- .../service/accounts/dto/accounts.nim | 7 +- .../accounts/dto/generated_accounts.nim | 6 +- src/app_service/service/accounts/service.nim | 196 +++++++++++++----- .../service/accounts/service_interface.nim | 20 +- src/nim_status_client.nim | 2 +- .../controls/AccountViewDelegate.qml | 6 +- .../Onboarding/panels/AccountListPanel.qml | 26 +-- .../Onboarding/popups/GenKeyModal.qml | 32 +-- .../popups/MnemonicRecoverySuccessModal.qml | 5 +- .../Onboarding/shared/CreatePasswordModal.qml | 24 +-- .../Onboarding/stores/OnboardingStore.qml | 7 +- .../Onboarding/views/GenKeyView.qml | 14 +- .../AppLayouts/Onboarding/views/LoginView.qml | 11 +- ui/app/AppLayouts/Wallet/WalletLayout.qml | 9 +- ui/app/AppLayouts/Wallet/stores/RootStore.qml | 7 +- ui/app/AppLayouts/WalletV2/WalletV2Layout.qml | 9 +- .../shared/controls/SeedPhraseTextArea.qml | 2 +- ui/imports/utils/Constants.qml | 4 + ui/main.qml | 14 +- 51 files changed, 757 insertions(+), 383 deletions(-) create mode 100644 src/app/modules/startup/login/account_item.nim delete mode 100644 src/app/modules/startup/login/item.nim create mode 100644 src/app/modules/startup/login/private_interfaces/module_base_interface.nim create mode 100644 src/app/modules/startup/login/private_interfaces/module_controller_delegate_interface.nim create mode 100644 src/app/modules/startup/login/private_interfaces/module_view_delegate_interface.nim create mode 100644 src/app/modules/startup/onboarding/private_interfaces/module_base_interface.nim create mode 100644 src/app/modules/startup/onboarding/private_interfaces/module_controller_delegate_interface.nim create mode 100644 src/app/modules/startup/onboarding/private_interfaces/module_view_delegate_interface.nim create mode 100644 src/app/modules/startup/private_interfaces/module_access_interface.nim create mode 100644 src/app/modules/startup/private_interfaces/module_base_interface.nim create mode 100644 src/app/modules/startup/private_interfaces/module_controller_delegate_interface.nim create mode 100644 src/app/modules/startup/private_interfaces/module_login_delegate_interface.nim create mode 100644 src/app/modules/startup/private_interfaces/module_onboarding_delegate_interface.nim create mode 100644 src/app/modules/startup/private_interfaces/module_view_delegate_interface.nim diff --git a/src/app/boot/app_controller.nim b/src/app/boot/app_controller.nim index 812a43838f..516d351876 100644 --- a/src/app/boot/app_controller.nim +++ b/src/app/boot/app_controller.nim @@ -42,6 +42,7 @@ proc load*(self: AppController) # Startup Module Delegate Interface proc startupDidLoad*(self: AppController) +proc accountCreated*(self: AppController) # Main Module Delegate Interface proc mainDidLoad*(self: AppController) @@ -95,12 +96,14 @@ proc delete*(self: AppController) = proc startupDidLoad*(self: AppController) = echo "StartupDidLoad" + singletonInstance.engine.load(newQUrl("qrc:///main.qml")) # self.login.init() # self.onboarding.init() proc mainDidLoad*(self: AppController) = # This to will be adapted to appropriate modules later: self.appService.onLoggedIn() + self.startupModule.moveToAppState() # Reset login and onboarding to remove any mnemonic that would have been saved in the accounts list # self.login.reset() @@ -121,4 +124,8 @@ proc load*(self: AppController) = self.chatService.init() self.communityService.init() - self.mainModule.load() \ No newline at end of file + self.mainModule.load() + +proc accountCreated*(self: AppController) = + echo "AppController account created" + self.load() \ No newline at end of file diff --git a/src/app/modules/startup/controller.nim b/src/app/modules/startup/controller.nim index 9a36c8b52b..6040abbbc5 100644 --- a/src/app/modules/startup/controller.nim +++ b/src/app/modules/startup/controller.nim @@ -1,29 +1,29 @@ import Tables import controller_interface +import io_interface import ../../../app_service/service/accounts/service_interface as accounts_service export controller_interface type - Controller*[T: controller_interface.DelegateInterface] = - ref object of controller_interface.AccessInterface - delegate: T + Controller* = ref object of controller_interface.AccessInterface + delegate: io_interface.AccessInterface accountsService: accounts_service.ServiceInterface -proc newController*[T](delegate: T, +proc newController*(delegate: io_interface.AccessInterface, accountsService: accounts_service.ServiceInterface): - Controller[T] = - result = Controller[T]() + Controller = + result = Controller() result.delegate = delegate result.accountsService = accountsService -method delete*[T](self: Controller[T]) = +method delete*(self: Controller) = discard -method init*[T](self: Controller[T]) = +method init*(self: Controller) = discard -method shouldStartWithOnboardingScreen*[T](self: Controller[T]): bool = - return self.accountsService.openedAccounts().len > 0 \ No newline at end of file +method shouldStartWithOnboardingScreen*(self: Controller): bool = + return self.accountsService.openedAccounts().len == 0 \ No newline at end of file diff --git a/src/app/modules/startup/controller_interface.nim b/src/app/modules/startup/controller_interface.nim index 22bb1c2a2e..c530b17ef7 100644 --- a/src/app/modules/startup/controller_interface.nim +++ b/src/app/modules/startup/controller_interface.nim @@ -10,9 +10,4 @@ method init*(self: AccessInterface) {.base.} = method shouldStartWithOnboardingScreen*(self: AccessInterface): bool {.base.} = raise newException(ValueError, "No implementation available") - -type - ## Abstract class (concept) which must be implemented by object/s used in this - ## module. - DelegateInterface* = concept c \ No newline at end of file diff --git a/src/app/modules/startup/io_interface.nim b/src/app/modules/startup/io_interface.nim index f4b5cc8b93..33f2c65652 100644 --- a/src/app/modules/startup/io_interface.nim +++ b/src/app/modules/startup/io_interface.nim @@ -1,22 +1,19 @@ -type - AccessInterface* {.pure inheritable.} = ref object of RootObj - ## Abstract class for any input/interaction with this module. +# Defines how parent module accesses this module +include ./private_interfaces/module_base_interface +include ./private_interfaces/module_access_interface -method delete*(self: AccessInterface) {.base.} = - raise newException(ValueError, "No implementation available") +# Defines how this module view communicates with this module +include ./private_interfaces/module_view_delegate_interface -method load*(self: AccessInterface) {.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") +# Defines how this controller communicates with this module +include ./private_interfaces/module_controller_delegate_interface +# Defines how submodules of this module communicate with this module +include ./private_interfaces/module_onboarding_delegate_interface +include ./private_interfaces/module_login_delegate_interface +# This way (using concepts) is used only for the modules managed by AppController type - ## Abstract class (concept) which must be implemented by object/s used in this - ## module. DelegateInterface* = concept c - c.startupDidLoad() \ No newline at end of file + c.startupDidLoad() + c.accountCreated() \ No newline at end of file diff --git a/src/app/modules/startup/login/account_item.nim b/src/app/modules/startup/login/account_item.nim new file mode 100644 index 0000000000..d07415f69e --- /dev/null +++ b/src/app/modules/startup/login/account_item.nim @@ -0,0 +1,63 @@ +import NimQml + +QtObject: + type AccountItem* = ref object of QObject + name: string + identicon: string + keyUid: string + thumbnailImage: string + largeImage: string + + proc setup(self: AccountItem) = + self.QObject.setup + + proc delete*(self: AccountItem) = + self.QObject.delete + + proc setAccountItemData*(self: AccountItem, name, identicon, keyUid, + thumbnailImage, largeImage: string) = + self.name = name + self.identicon = identicon + self.keyUid = keyUid + self.thumbnailImage = thumbnailImage + self.largeImage = largeImage + + proc newAccountItem*(): AccountItem = + new(result, delete) + result.setup + + proc newAccountItem*(name, identicon, keyUid, thumbnailImage, + largeImage: string): AccountItem = + new(result, delete) + result.setup + result.setAccountItemData(name, identicon, keyUid, thumbnailImage, largeImage) + + proc getName(self: AccountItem): string {.slot.} = + result = self.name + + QtProperty[string] name: + read = getName + + proc getIdenticon(self: AccountItem): string {.slot.} = + result = self.identicon + + QtProperty[string] identicon: + read = getIdenticon + + proc getKeyUid(self: AccountItem): string {.slot.} = + result = self.keyUid + + QtProperty[string] keyUid: + read = getKeyUid + + proc getThumbnailImage(self: AccountItem): string {.slot.} = + result = self.thumbnailImage + + QtProperty[string] thumbnailImage: + read = getThumbnailImage + + proc getLargeImage(self: AccountItem): string {.slot.} = + result = self.largeImage + + QtProperty[string] largeImage: + read = getLargeImage \ No newline at end of file diff --git a/src/app/modules/startup/login/controller.nim b/src/app/modules/startup/login/controller.nim index e873c19dcc..b6ea21a7dc 100644 --- a/src/app/modules/startup/login/controller.nim +++ b/src/app/modules/startup/login/controller.nim @@ -1,6 +1,7 @@ import Tables import controller_interface +import io_interface import status/[signals] import ../../../../app_service/[main] @@ -9,25 +10,27 @@ import ../../../../app_service/service/accounts/service_interface as accounts_se export controller_interface type - Controller*[T: controller_interface.DelegateInterface] = - ref object of controller_interface.AccessInterface - delegate: T + Controller* = ref object of controller_interface.AccessInterface + delegate: io_interface.AccessInterface appService: AppService accountsService: accounts_service.ServiceInterface -proc newController*[T](delegate: T, +proc newController*(delegate: io_interface.AccessInterface, appService: AppService, accountsService: accounts_service.ServiceInterface): - Controller[T] = - result = Controller[T]() + Controller = + result = Controller() result.delegate = delegate result.appService = appService result.accountsService = accountsService -method delete*[T](self: Controller[T]) = +method delete*(self: Controller) = discard -method init*[T](self: Controller[T]) = +method getOpenedAccounts*(self: Controller): seq[AccountDto] = + return self.accountsService.openedAccounts() + +method init*(self: Controller) = self.appService.status.events.on(SignalType.NodeStopped.event) do(e:Args): echo "-NEW-LOGIN-- NodeStopped: ", repr(e) #self.status.events.emit("nodeStopped", Args()) diff --git a/src/app/modules/startup/login/controller_interface.nim b/src/app/modules/startup/login/controller_interface.nim index 76d1b2fa50..8eb6d68db7 100644 --- a/src/app/modules/startup/login/controller_interface.nim +++ b/src/app/modules/startup/login/controller_interface.nim @@ -1,4 +1,4 @@ -#import ../../../../app_service/service/community/service_interface as community_service +import ../../../../app_service/service/accounts/service_interface type AccessInterface* {.pure inheritable.} = ref object of RootObj @@ -9,10 +9,6 @@ method delete*(self: AccessInterface) {.base.} = method init*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") - - -type - ## Abstract class (concept) which must be implemented by object/s used in this - ## module. - DelegateInterface* = concept c - \ No newline at end of file + +method getOpenedAccounts*(self: AccessInterface): seq[AccountDto] {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/login/io_interface.nim b/src/app/modules/startup/login/io_interface.nim index feca1b6502..680532c879 100644 --- a/src/app/modules/startup/login/io_interface.nim +++ b/src/app/modules/startup/login/io_interface.nim @@ -1,24 +1,12 @@ -type - AccessInterface* {.pure inheritable.} = ref object of RootObj - ## Abstract class for any input/interaction with this module. +# Defines how parent module accesses this module +include ./private_interfaces/module_base_interface +include ./private_interfaces/module_access_interface -method delete*(self: AccessInterface) {.base.} = - raise newException(ValueError, "No implementation available") +# Defines how this module view communicates with this module +include ./private_interfaces/module_view_delegate_interface -method load*(self: AccessInterface) {.base.} = - raise newException(ValueError, "No implementation available") +# Defines how this controller communicates with this module +include ./private_interfaces/module_controller_delegate_interface -method isLoaded*(self: AccessInterface): bool {.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") - -type - ## Abstract class (concept) which must be implemented by object/s used in this - ## module. - DelegateInterface* = concept c - c.loginDidLoad() +# Defines how submodules of this module communicate with this module +# will be added if needed \ No newline at end of file diff --git a/src/app/modules/startup/login/item.nim b/src/app/modules/startup/login/item.nim deleted file mode 100644 index 2544cee951..0000000000 --- a/src/app/modules/startup/login/item.nim +++ /dev/null @@ -1,21 +0,0 @@ -import NimQml - -QtObject: - type - Item* = ref object of QObject - - proc setup(self: Item) = - self.QObject.setup - - proc delete*(self: Item) = - self.QObject.delete - - proc newItem*(): Item = - new(result, delete) - result.setup() - - proc id*(self: Item): string {.slot.} = - self.id - - QtProperty[string] id: - read = id \ No newline at end of file diff --git a/src/app/modules/startup/login/model.nim b/src/app/modules/startup/login/model.nim index 5bbede6cf7..35da5c4bef 100644 --- a/src/app/modules/startup/login/model.nim +++ b/src/app/modules/startup/login/model.nim @@ -1,17 +1,60 @@ -import NimQml -import item +import NimQml, Tables, strutils, strformat + +import account_item + +type + ModelRole {.pure.} = enum + Account = UserRole + 1 QtObject: - type + type Model* = ref object of QAbstractListModel - sections: seq[Item] + items: seq[AccountItem] - proc setup(self: Model) = - self.QAbstractListModel.setup - - proc delete*(self: Model) = + proc delete(self: Model) = + self.items = @[] self.QAbstractListModel.delete + proc setup(self: Model) = + self.QAbstractListModel.setup + proc newModel*(): Model = new(result, delete) - result.setup \ No newline at end of file + result.setup + + proc countChanged*(self: Model) {.signal.} + + proc count*(self: Model): int {.slot.} = + self.items.len + + QtProperty[int] count: + read = count + notify = countChanged + + method rowCount(self: Model, index: QModelIndex = nil): int = + return self.items.len + + method roleNames(self: Model): Table[int, string] = + { + ModelRole.Account.int:"account" + }.toTable + + method data(self: Model, index: QModelIndex, role: int): QVariant = + if (not index.isValid): + return + + if (index.row < 0 or index.row >= self.items.len): + return + + let item = self.items[index.row] + let enumRole = role.ModelRole + + case enumRole: + of ModelRole.Account: + result = newQVariant(item) + + proc setItems*(self: Model, items: seq[AccountItem]) = + self.beginResetModel() + self.items = items + self.endResetModel() + self.countChanged() \ No newline at end of file diff --git a/src/app/modules/startup/login/module.nim b/src/app/modules/startup/login/module.nim index da1ebacc79..ea678aff7c 100644 --- a/src/app/modules/startup/login/module.nim +++ b/src/app/modules/startup/login/module.nim @@ -1,5 +1,7 @@ import NimQml -import io_interface, view, controller +import io_interface +import ../io_interface as delegate_interface +import view, controller, account_item import ../../../../app/boot/global_singleton import ../../../../app_service/[main] @@ -8,42 +10,68 @@ import ../../../../app_service/service/accounts/service_interface as accounts_se export io_interface type - Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface - delegate: T + Module* = ref object of io_interface.AccessInterface + delegate: delegate_interface.AccessInterface view: View viewVariant: QVariant controller: controller.AccessInterface moduleLoaded: bool -proc newModule*[T](delegate: T, +proc newModule*(delegate: delegate_interface.AccessInterface, appService: AppService, accountsService: accounts_service.ServiceInterface): - Module[T] = - result = Module[T]() + Module = + result = Module() result.delegate = delegate result.view = view.newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newController[Module[T]](result, appService, - accountsService) + result.controller = controller.newController(result, appService, accountsService) result.moduleLoaded = false singletonInstance.engine.setRootContextProperty("loginModule", result.viewVariant) -method delete*[T](self: Module[T]) = +method delete*(self: Module) = self.view.delete self.viewVariant.delete self.controller.delete -method load*[T](self: Module[T]) = +proc extractImages(self: Module, account: AccountDto, thumbnailImage: var string, + largeImage: var string) = + for img in account.images: + if(img.imgType == "thumbnail"): + thumbnailImage = img.uri + elif(img.imgType == "large"): + largeImage = img.uri + +method load*(self: Module) = singletonInstance.engine.setRootContextProperty("loginModule", self.viewVariant) self.controller.init() self.view.load() - self.moduleLoaded = true - self.delegate.loginDidLoad() + let openedAccounts = self.controller.getOpenedAccounts() + if(openedAccounts.len > 0): + var accounts: seq[AccountItem] + for acc in openedAccounts: + var thumbnailImage: string + var largeImage: string + self.extractImages(acc, thumbnailImage, largeImage) + accounts.add(newAccountItem(acc.name, acc.identicon, acc.keyUid, + thumbnailImage, largeImage)) -method isLoaded*[T](self: Module[T]): bool = + self.view.setAccountsList(accounts) + + # set the first account as a slected one + let selected = openedAccounts[0] + var thumbnailImage: string + var largeImage: string + self.extractImages(selected, thumbnailImage, largeImage) + + self.view.setSelectedAccount(selected.name, selected.identicon, selected.keyUid, + thumbnailImage, largeImage) + +method isLoaded*(self: Module): bool = return self.moduleLoaded method viewDidLoad*(self: Module) = - discard \ No newline at end of file + self.moduleLoaded = true + self.delegate.loginDidLoad() \ No newline at end of file diff --git a/src/app/modules/startup/login/private_interfaces/module_base_interface.nim b/src/app/modules/startup/login/private_interfaces/module_base_interface.nim new file mode 100644 index 0000000000..0634c53158 --- /dev/null +++ b/src/app/modules/startup/login/private_interfaces/module_base_interface.nim @@ -0,0 +1,5 @@ +type + AccessInterface* {.pure inheritable.} = ref object of RootObj + +# Since nim doesn't support using concepts in second level nested types we +# define delegate interfaces within access interface. \ No newline at end of file diff --git a/src/app/modules/startup/login/private_interfaces/module_controller_delegate_interface.nim b/src/app/modules/startup/login/private_interfaces/module_controller_delegate_interface.nim new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/modules/startup/login/private_interfaces/module_view_delegate_interface.nim b/src/app/modules/startup/login/private_interfaces/module_view_delegate_interface.nim new file mode 100644 index 0000000000..a5a66c0e55 --- /dev/null +++ b/src/app/modules/startup/login/private_interfaces/module_view_delegate_interface.nim @@ -0,0 +1,2 @@ +method viewDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/login/view.nim b/src/app/modules/startup/login/view.nim index 481558237c..6e1148cf95 100644 --- a/src/app/modules/startup/login/view.nim +++ b/src/app/modules/startup/login/view.nim @@ -1,22 +1,59 @@ import NimQml -import model +import account_item, model import io_interface QtObject: type View* = ref object of QObject delegate: io_interface.AccessInterface + selectedAccount: AccountItem + selectedAccountVariant: QVariant model: Model + modelVariant: QVariant proc delete*(self: View) = + self.selectedAccount.delete + self.selectedAccountVariant.delete self.model.delete + self.modelVariant.delete self.QObject.delete proc newView*(delegate: io_interface.AccessInterface): View = new(result, delete) result.QObject.setup result.delegate = delegate + result.selectedAccount = newAccountItem() + result.selectedAccountVariant = newQVariant(result.selectedAccount) result.model = newModel() + result.modelVariant = newQVariant(result.model) proc load*(self: View) = - self.delegate.viewDidLoad() \ No newline at end of file + self.delegate.viewDidLoad() + + proc selectedAccountChanged*(self: View) {.signal.} + + proc getSelectedAccount(self: View): QVariant {.slot.} = + return self.selectedAccountVariant + + proc setSelectedAccount*(self: View, name, identicon, keyUid, thumbnailImage, + largeImage: string) = + self.selectedAccount.setAccountItemData(name, identicon, keyUid, thumbnailImage, + largeImage) + self.selectedAccountChanged() + + QtProperty[QVariant] selectedAccount: + read = getSelectedAccount + notify = selectedAccountChanged + + proc modelChanged*(self: View) {.signal.} + + proc getModel(self: View): QVariant {.slot.} = + return self.modelVariant + + proc setAccountsList*(self: View, accounts: seq[AccountItem]) = + self.model.setItems(accounts) + self.modelChanged() + + QtProperty[QVariant] accountsModel: + read = getModel + notify = modelChanged \ No newline at end of file diff --git a/src/app/modules/startup/module.nim b/src/app/modules/startup/module.nim index 15a066b3bc..0cff0ae361 100644 --- a/src/app/modules/startup/module.nim +++ b/src/app/modules/startup/module.nim @@ -1,6 +1,7 @@ import NimQml -import io_interface, view, controller +import io_interface +import view, controller import ../../../app/boot/global_singleton import onboarding/module as onboarding_module @@ -20,20 +21,6 @@ type onboardingModule: onboarding_module.AccessInterface loginModule: login_module.AccessInterface -################################################# -# Forward declaration section - -# Controller Delegate Interface - - -# Onboarding Module Delegate Interface -proc onboardingDidLoad*[T](self: Module[T]) - -# Login Module Delegate Interface -proc loginDidLoad*[T](self: Module[T]) - -################################################# - proc newModule*[T](delegate: T, appService: AppService, accountsService: accounts_service.ServiceInterface): @@ -42,13 +29,11 @@ proc newModule*[T](delegate: T, result.delegate = delegate result.view = view.newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newController[Module[T]](result, accountsService) + result.controller = controller.newController(result, accountsService) # Submodules - result.onboardingModule = onboarding_module.newModule[Module[T]](result, - appService, accountsService) - result.loginModule = login_module.newModule[Module[T]](result, appService, - accountsService) + result.onboardingModule = onboarding_module.newModule(result, appService, accountsService) + result.loginModule = login_module.newModule(result, appService, accountsService) method delete*[T](self: Module[T]) = self.onboardingModule.delete @@ -61,14 +46,15 @@ method load*[T](self: Module[T]) = singletonInstance.engine.setRootContextProperty("startupModule", self.viewVariant) self.controller.init() self.view.load() - self.view.setStartWithOnboardingScreen(self.controller.shouldStartWithOnboardingScreen()) + + var initialAppState = AppState.OnboardingState + if(not self.controller.shouldStartWithOnboardingScreen()): + initialAppState = AppState.LoginState + self.view.setAppState(initialAppState) self.onboardingModule.load() self.loginModule.load() -method viewDidLoad*[T](self: Module[T]) = - discard - proc checkIfModuleDidLoad[T](self: Module[T]) = if(not self.onboardingModule.isLoaded()): return @@ -78,8 +64,17 @@ proc checkIfModuleDidLoad[T](self: Module[T]) = self.delegate.startupDidLoad() -proc onboardingDidLoad*[T](self: Module[T]) = +method viewDidLoad*[T](self: Module[T]) = self.checkIfModuleDidLoad() -proc loginDidLoad*[T](self: Module[T]) = - self.checkIfModuleDidLoad() \ No newline at end of file +method onboardingDidLoad*[T](self: Module[T]) = + self.checkIfModuleDidLoad() + +method loginDidLoad*[T](self: Module[T]) = + self.checkIfModuleDidLoad() + +method accountCreated*[T](self: Module[T]) = + self.delegate.accountCreated() + +method moveToAppState*[T](self: Module[T]) = + self.view.setAppState(AppState.MainAppState) \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/controller.nim b/src/app/modules/startup/onboarding/controller.nim index 54ecdcdf2d..d2ddc14111 100644 --- a/src/app/modules/startup/onboarding/controller.nim +++ b/src/app/modules/startup/onboarding/controller.nim @@ -1,6 +1,7 @@ -import Tables +import Tables, chronicles import controller_interface +import io_interface import status/[signals] import ../../../../app_service/[main] @@ -8,39 +9,62 @@ import ../../../../app_service/service/accounts/service_interface as accounts_se export controller_interface +logScope: + topics = "onboarding-controller" + type - Controller*[T: controller_interface.DelegateInterface] = + Controller* = ref object of controller_interface.AccessInterface - delegate: T + delegate: io_interface.AccessInterface appService: AppService accountsService: accounts_service.ServiceInterface selectedAccountId: string -proc newController*[T](delegate: T, +proc newController*(delegate: io_interface.AccessInterface, appService: AppService, accountsService: accounts_service.ServiceInterface): - Controller[T] = - result = Controller[T]() + Controller = + result = Controller() result.delegate = delegate result.appService = appService result.accountsService = accountsService -method delete*[T](self: Controller[T]) = +method delete*(self: Controller) = discard -method init*[T](self: Controller[T]) = +method init*(self: Controller) = self.appService.status.events.on(SignalType.NodeLogin.event) do(e:Args): - echo "-NEW-ONBOARDING-- OnNodeLoginEvent: ", repr(e) - #self.handleNodeLogin(NodeSignal(e)) + let signal = NodeSignal(e) + echo "-NEW-ONBOARDING-- OnNodeLoginEvent: ", repr(signal) + if signal.event.error == "": + echo "-NEW-ONBOARDING-- OnNodeLoginEventA: ", repr(signal.event.error) + self.delegate.accountCreated() + else: + error "error: ", methodName="init", errDesription = "onboarding login error " & signal.event.error -method getGeneratedAccounts*[T](self: Controller[T]): seq[GeneratedAccountDto] = +method getGeneratedAccounts*(self: Controller): seq[GeneratedAccountDto] = return self.accountsService.generatedAccounts() -method setSelectedAccountId*[T](self: Controller[T], id: string) = - self.selectedAccountId = id +method getImportedAccount*(self: Controller): GeneratedAccountDto = + return self.accountsService.getImportedAccount() -method storeSelectedAccountAndLogin*[T](self: Controller[T], password: string) = - let account = self.accountsService.setupAccount(self.appService.status.fleet.config, - self.selectedAccountId, password) +method setSelectedAccountByIndex*(self: Controller, index: int) = + let accounts = self.getGeneratedAccounts() + self.selectedAccountId = accounts[index].id - echo "RECEIVED ACCOUNT: ", repr(account) \ No newline at end of file +method storeSelectedAccountAndLogin*(self: Controller, password: string) = + if(not self.accountsService.setupAccount(self.appService.status.fleet.config, + self.selectedAccountId, password)): + self.delegate.setupAccountError() + +method validateMnemonic*(self: Controller, mnemonic: string): string = + return self.accountsService.validateMnemonic(mnemonic) + +method importMnemonic*(self: Controller, mnemonic: string) = + if(self.accountsService.importMnemonic(mnemonic)): + self.selectedAccountId = self.getImportedAccount().id + self.delegate.importAccountSuccess() + else: + self.delegate.importAccountError() + + \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/controller_interface.nim b/src/app/modules/startup/onboarding/controller_interface.nim index b12fd74cb5..0b552ea145 100644 --- a/src/app/modules/startup/onboarding/controller_interface.nim +++ b/src/app/modules/startup/onboarding/controller_interface.nim @@ -14,15 +14,19 @@ method getGeneratedAccounts*(self: AccessInterface): seq[GeneratedAccountDto] {.base.} = raise newException(ValueError, "No implementation available") -method setSelectedAccountId*(self: AccessInterface, id: string) {.base.} = +method setSelectedAccountByIndex*(self: AccessInterface, index: int) {.base.} = raise newException(ValueError, "No implementation available") method storeSelectedAccountAndLogin*(self: AccessInterface, password: string) {.base.} = raise newException(ValueError, "No implementation available") + +method getImportedAccount*(self: AccessInterface): GeneratedAccountDto {.base.} = + raise newException(ValueError, "No implementation available") -type - ## Abstract class (concept) which must be implemented by object/s used in this - ## module. - DelegateInterface* = concept c - \ No newline at end of file +method validateMnemonic*(self: AccessInterface, mnemonic: string): + string {.base.} = + raise newException(ValueError, "No implementation available") + +method importMnemonic*(self: AccessInterface, mnemonic: string) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/io_interface.nim b/src/app/modules/startup/onboarding/io_interface.nim index c9eae82654..680532c879 100644 --- a/src/app/modules/startup/onboarding/io_interface.nim +++ b/src/app/modules/startup/onboarding/io_interface.nim @@ -1,31 +1,12 @@ -type - AccessInterface* {.pure inheritable.} = ref object of RootObj - ## Abstract class for any input/interaction with this module. +# Defines how parent module accesses this module +include ./private_interfaces/module_base_interface +include ./private_interfaces/module_access_interface -method delete*(self: AccessInterface) {.base.} = - raise newException(ValueError, "No implementation available") +# Defines how this module view communicates with this module +include ./private_interfaces/module_view_delegate_interface -method load*(self: AccessInterface) {.base.} = - raise newException(ValueError, "No implementation available") +# Defines how this controller communicates with this module +include ./private_interfaces/module_controller_delegate_interface -method isLoaded*(self: AccessInterface): bool {.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") - -method setSelectedAccountId*(self: AccessInterface, id: string) {.base.} = - raise newException(ValueError, "No implementation available") - -method storeSelectedAccountAndLogin*(self: AccessInterface, password: string) - {.base.} = - raise newException(ValueError, "No implementation available") - -type - ## Abstract class (concept) which must be implemented by object/s used in this - ## module. - DelegateInterface* = concept c - c.onboardingDidLoad() +# Defines how submodules of this module communicate with this module +# will be added if needed \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/model.nim b/src/app/modules/startup/onboarding/model.nim index d73305888e..2e118d3f55 100644 --- a/src/app/modules/startup/onboarding/model.nim +++ b/src/app/modules/startup/onboarding/model.nim @@ -32,7 +32,7 @@ QtObject: method roleNames(self: Model): Table[int, string] = { ModelRole.Id.int:"accountId", - ModelRole.Alias.int:"alias", + ModelRole.Alias.int:"username", ModelRole.Identicon.int:"identicon", ModelRole.Address.int:"address", ModelRole.KeyUid.int:"keyUid" diff --git a/src/app/modules/startup/onboarding/module.nim b/src/app/modules/startup/onboarding/module.nim index f64eac5090..4ed83bcfe1 100644 --- a/src/app/modules/startup/onboarding/module.nim +++ b/src/app/modules/startup/onboarding/module.nim @@ -1,5 +1,7 @@ import NimQml -import io_interface, view, controller, item +import io_interface +import ../io_interface as delegate_interface +import view, controller, item import ../../../../app/boot/global_singleton import ../../../../app_service/[main] @@ -8,33 +10,32 @@ import ../../../../app_service/service/accounts/service_interface as accounts_se export io_interface type - Module* [T: io_interface.DelegateInterface] = ref object of io_interface.AccessInterface - delegate: T + Module* = ref object of io_interface.AccessInterface + delegate: delegate_interface.AccessInterface view: View viewVariant: QVariant controller: controller.AccessInterface moduleLoaded: bool -proc newModule*[T](delegate: T, +proc newModule*(delegate: delegate_interface.AccessInterface, appService: AppService, accountsService: accounts_service.ServiceInterface): - Module[T] = - result = Module[T]() + Module = + result = Module() result.delegate = delegate result.view = view.newView(result) result.viewVariant = newQVariant(result.view) - result.controller = controller.newController[Module[T]](result, appService, - accountsService) + result.controller = controller.newController(result, appService, accountsService) result.moduleLoaded = false singletonInstance.engine.setRootContextProperty("onboardingModule", result.viewVariant) -method delete*[T](self: Module[T]) = +method delete*(self: Module) = self.view.delete self.viewVariant.delete self.controller.delete -method load*[T](self: Module[T]) = +method load*(self: Module) = singletonInstance.engine.setRootContextProperty("onboardingModule", self.viewVariant) self.controller.init() self.view.load() @@ -44,19 +45,38 @@ method load*[T](self: Module[T]) = for acc in generatedAccounts: accounts.add(initItem(acc.id, acc.alias, acc.identicon, acc.address, acc.keyUid)) - self.view.setAccountList(accounts) + self.view.setAccountList(accounts) - self.moduleLoaded = true - self.delegate.onboardingDidLoad() - -method isLoaded*[T](self: Module[T]): bool = +method isLoaded*(self: Module): bool = return self.moduleLoaded method viewDidLoad*(self: Module) = - discard + self.moduleLoaded = true + self.delegate.onboardingDidLoad() -method setSelectedAccountId*[T](self: Module[T], id: string) = - self.controller.setSelectedAccountId(id) +method setSelectedAccountByIndex*(self: Module, index: int) = + self.controller.setSelectedAccountByIndex(index) -method storeSelectedAccountAndLogin*[T](self: Module[T], password: string) = - self.controller.storeSelectedAccountAndLogin(password) \ No newline at end of file +method storeSelectedAccountAndLogin*(self: Module, password: string) = + self.controller.storeSelectedAccountAndLogin(password) + +method accountCreated*(self: Module) = + self.delegate.accountCreated() + +method setupAccountError*(self: Module) = + self.view.setupAccountError() + +method getImportedAccount*(self: Module): GeneratedAccountDto = + return self.controller.getImportedAccount() + +method validateMnemonic*(self: Module, mnemonic: string): string = + return self.controller.validateMnemonic(mnemonic) + +method importMnemonic*(self: Module, mnemonic: string) = + self.controller.importMnemonic(mnemonic) + +method importAccountError*(self: Module) = + self.view.importAccountError() + +method importAccountSuccess*(self: Module) = + self.view.importAccountSuccess() \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/private_interfaces/module_base_interface.nim b/src/app/modules/startup/onboarding/private_interfaces/module_base_interface.nim new file mode 100644 index 0000000000..0634c53158 --- /dev/null +++ b/src/app/modules/startup/onboarding/private_interfaces/module_base_interface.nim @@ -0,0 +1,5 @@ +type + AccessInterface* {.pure inheritable.} = ref object of RootObj + +# Since nim doesn't support using concepts in second level nested types we +# define delegate interfaces within access interface. \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/private_interfaces/module_controller_delegate_interface.nim b/src/app/modules/startup/onboarding/private_interfaces/module_controller_delegate_interface.nim new file mode 100644 index 0000000000..c91c8335e6 --- /dev/null +++ b/src/app/modules/startup/onboarding/private_interfaces/module_controller_delegate_interface.nim @@ -0,0 +1,11 @@ +method accountCreated*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method setupAccountError*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method importAccountError*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method importAccountSuccess*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/startup/onboarding/private_interfaces/module_view_delegate_interface.nim b/src/app/modules/startup/onboarding/private_interfaces/module_view_delegate_interface.nim new file mode 100644 index 0000000000..fa0f9602f7 --- /dev/null +++ b/src/app/modules/startup/onboarding/private_interfaces/module_view_delegate_interface.nim @@ -0,0 +1,21 @@ +import ../../../../../app_service/service/accounts/service_interface + +method viewDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method setSelectedAccountByIndex*(self: AccessInterface, index: int) {.base.} = + raise newException(ValueError, "No implementation available") + +method storeSelectedAccountAndLogin*(self: AccessInterface, password: string) + {.base.} = + raise newException(ValueError, "No implementation available") + +method getImportedAccount*(self: AccessInterface): GeneratedAccountDto {.base.} = + raise newException(ValueError, "No implementation available") + +method validateMnemonic*(self: AccessInterface, mnemonic: string): + string {.base.} = + raise newException(ValueError, "No implementation available") + +method importMnemonic*(self: AccessInterface, mnemonic: string) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/onboarding/view.nim b/src/app/modules/startup/onboarding/view.nim index 53d3628cbf..a056d3c0e6 100644 --- a/src/app/modules/startup/onboarding/view.nim +++ b/src/app/modules/startup/onboarding/view.nim @@ -24,20 +24,63 @@ QtObject: proc load*(self: View) = self.delegate.viewDidLoad() - proc setAccountList*(self: View, accounts: seq[Item]) = - self.model.setItems(accounts) - proc modelChanged*(self: View) {.signal.} proc getModel(self: View): QVariant {.slot.} = return self.modelVariant + proc setAccountList*(self: View, accounts: seq[Item]) = + self.model.setItems(accounts) + self.modelChanged() + QtProperty[QVariant] accountsModel: read = getModel notify = modelChanged - proc setSelectedAccountId*(self: View, id: string) {.slot.} = - self.delegate.setSelectedAccountId(id) + proc importedAccountChanged*(self: View) {.signal.} + + proc getImportedAccountIdenticon*(self: View): string {.slot.} = + return self.delegate.getImportedAccount().identicon + + QtProperty[string] importedAccountIdenticon: + read = getImportedAccountIdenticon + notify = importedAccountChanged + + proc getImportedAccountAlias*(self: View): string {.slot.} = + return self.delegate.getImportedAccount().alias + + QtProperty[string] importedAccountAlias: + read = getImportedAccountAlias + notify = importedAccountChanged + + proc getImportedAccountAddress*(self: View): string {.slot.} = + return self.delegate.getImportedAccount().address + + QtProperty[string] importedAccountAddress: + read = getImportedAccountAddress + notify = importedAccountChanged + + proc setSelectedAccountByIndex*(self: View, index: int) {.slot.} = + self.delegate.setSelectedAccountByIndex(index) proc storeSelectedAccountAndLogin*(self: View, password: string) {.slot.} = - self.delegate.storeSelectedAccountAndLogin(password) \ No newline at end of file + self.delegate.storeSelectedAccountAndLogin(password) + + proc accountSetupError*(self: View) {.signal.} + + proc setupAccountError*(self: View) = + self.accountSetupError() + + proc validateMnemonic*(self: View, mnemonic: string): string {.slot.} = + return self.delegate.validateMnemonic(mnemonic) + + proc importMnemonic*(self: View, mnemonic: string) {.slot.} = + self.delegate.importMnemonic(mnemonic) + + proc accountImportError*(self: View) {.signal.} + + proc importAccountError*(self: View) = + self.accountImportError() # In QML we can connect to this signal and notify a user + + proc importAccountSuccess*(self: View) = + self.importedAccountChanged() diff --git a/src/app/modules/startup/private_interfaces/module_access_interface.nim b/src/app/modules/startup/private_interfaces/module_access_interface.nim new file mode 100644 index 0000000000..30139ef0f9 --- /dev/null +++ b/src/app/modules/startup/private_interfaces/module_access_interface.nim @@ -0,0 +1,8 @@ +method delete*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method load*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method moveToAppState*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/private_interfaces/module_base_interface.nim b/src/app/modules/startup/private_interfaces/module_base_interface.nim new file mode 100644 index 0000000000..0634c53158 --- /dev/null +++ b/src/app/modules/startup/private_interfaces/module_base_interface.nim @@ -0,0 +1,5 @@ +type + AccessInterface* {.pure inheritable.} = ref object of RootObj + +# Since nim doesn't support using concepts in second level nested types we +# define delegate interfaces within access interface. \ No newline at end of file diff --git a/src/app/modules/startup/private_interfaces/module_controller_delegate_interface.nim b/src/app/modules/startup/private_interfaces/module_controller_delegate_interface.nim new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/modules/startup/private_interfaces/module_login_delegate_interface.nim b/src/app/modules/startup/private_interfaces/module_login_delegate_interface.nim new file mode 100644 index 0000000000..ca2eddef8d --- /dev/null +++ b/src/app/modules/startup/private_interfaces/module_login_delegate_interface.nim @@ -0,0 +1,2 @@ +method loginDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/private_interfaces/module_onboarding_delegate_interface.nim b/src/app/modules/startup/private_interfaces/module_onboarding_delegate_interface.nim new file mode 100644 index 0000000000..dcd2bc1bcc --- /dev/null +++ b/src/app/modules/startup/private_interfaces/module_onboarding_delegate_interface.nim @@ -0,0 +1,5 @@ +method onboardingDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") + +method accountCreated*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/private_interfaces/module_view_delegate_interface.nim b/src/app/modules/startup/private_interfaces/module_view_delegate_interface.nim new file mode 100644 index 0000000000..a5a66c0e55 --- /dev/null +++ b/src/app/modules/startup/private_interfaces/module_view_delegate_interface.nim @@ -0,0 +1,2 @@ +method viewDidLoad*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/startup/view.nim b/src/app/modules/startup/view.nim index 876d154204..af4e0bff07 100644 --- a/src/app/modules/startup/view.nim +++ b/src/app/modules/startup/view.nim @@ -1,11 +1,17 @@ import NimQml import io_interface +type + AppState* {.pure.} = enum + OnboardingState = 0 + LoginState + MainAppState + QtObject: type View* = ref object of QObject delegate: io_interface.AccessInterface - startWithOnboardingScreen: bool + appState: AppState proc delete*(self: View) = self.QObject.delete @@ -14,24 +20,24 @@ QtObject: new(result, delete) result.QObject.setup result.delegate = delegate - result.startWithOnboardingScreen = true + result.appState = AppState.OnboardingState proc load*(self: View) = # In some point, here, we will setup some exposed main module related things. self.delegate.viewDidLoad() - proc startWithOnboardingScreenChanged*(self: View) {.signal.} + proc appStateChanged*(self: View, state: int) {.signal.} - proc getStartWithOnboardingScreen(self: View): bool {.slot.} = - return self.startWithOnboardingScreen + proc getAppState(self: View): int {.slot.} = + return self.appState.int - proc setStartWithOnboardingScreen*(self: View, value: bool) {.slot.} = - if(self.startWithOnboardingScreen == value): + proc setAppState*(self: View, state: AppState) = + if(self.appState == state): return - self.startWithOnboardingScreen = value - self.startWithOnboardingScreenChanged() + self.appState = state + self.appStateChanged(self.appState.int) - QtProperty[bool] startWithOnboardingScreen: - read = getStartWithOnboardingScreen - notify = startWithOnboardingScreenChanged \ No newline at end of file + QtProperty[int] appState: + read = getAppState + notify = appStateChanged \ No newline at end of file diff --git a/src/app_service/service/accounts/dto/accounts.nim b/src/app_service/service/accounts/dto/accounts.nim index 49d5bf4e53..47c0c1be0a 100644 --- a/src/app_service/service/accounts/dto/accounts.nim +++ b/src/app_service/service/accounts/dto/accounts.nim @@ -5,7 +5,7 @@ import json include ../../../common/json_utils type - Image* = ref object + Image* = object keyUid*: string imgType*: string uri*: string @@ -14,7 +14,7 @@ type fileSize: int resizeTarget: int -type AccountDto* = ref object +type AccountDto* = object name*: string timestamp*: int64 identicon*: string @@ -22,6 +22,9 @@ type AccountDto* = ref object keyUid*: string images*: seq[Image] +proc isValid*(self: AccountDto): bool = + result = self.name.len > 0 and self.keyUid.len > 0 + proc toImage(jsonObj: JsonNode): Image = result = Image() discard jsonObj.getProp("keyUid", result.keyUid) diff --git a/src/app_service/service/accounts/dto/generated_accounts.nim b/src/app_service/service/accounts/dto/generated_accounts.nim index 8e1df63dde..7084676984 100644 --- a/src/app_service/service/accounts/dto/generated_accounts.nim +++ b/src/app_service/service/accounts/dto/generated_accounts.nim @@ -17,7 +17,7 @@ type DerivedAccounts* = object defaultWallet*: DerivedAccountDetails eip1581*: DerivedAccountDetails -type GeneratedAccountDto* = ref object +type GeneratedAccountDto* = object id*: string publicKey*: string address*: string @@ -28,6 +28,10 @@ type GeneratedAccountDto* = ref object alias*: string identicon*: string +proc isValid*(self: GeneratedAccountDto): bool = + result = self.id.len > 0 and self.publicKey.len > 0 and + self.address.len > 0 and self.keyUid.len > 0 + proc toDerivedAccountDetails(jsonObj: JsonNode, derivationPath: string): DerivedAccountDetails = # Mapping this DTO is not strightforward since only keys are used for id. We diff --git a/src/app_service/service/accounts/service.nim b/src/app_service/service/accounts/service.nim index 210083ae36..66755ed557 100644 --- a/src/app_service/service/accounts/service.nim +++ b/src/app_service/service/accounts/service.nim @@ -4,6 +4,7 @@ import service_interface import ./dto/accounts import ./dto/generated_accounts import status/statusgo_backend_new/accounts as status_go +import status/statusgo_backend_new/general as status_go_general import ../../common/[account_constants, utils, string_utils] import ../../../constants as main_constants @@ -17,12 +18,25 @@ const PATHS = @[PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALL type Service* = ref object of ServiceInterface generatedAccounts: seq[GeneratedAccountDto] + loggedInAccount: AccountDto + importedAccount: GeneratedAccountDto + isFirstTimeAccountLogin: bool method delete*(self: Service) = discard proc newService*(): Service = result = Service() + result.isFirstTimeAccountLogin = false + +method getLoggedInAccount*(self: Service): AccountDto = + return self.loggedInAccount + +method getImportedAccount*(self: Service): GeneratedAccountDto = + return self.importedAccount + +method isFirstTimeAccountLogin*(self: Service): bool = + return self.isFirstTimeAccountLogin method init*(self: Service) = try: @@ -43,6 +57,20 @@ method init*(self: Service) = except Exception as e: error "error: ", methodName="init", errName = e.name, errDesription = e.msg +method validateMnemonic*(self: Service, mnemonic: string): string = + try: + let response = status_go_general.validateMnemonic(mnemonic) + + var error = "response doesn't contain \"error\"" + if(response.result.contains("error")): + error = response.result["error"].getStr + + # An empty error means that mnemonic is valid. + return error + + except Exception as e: + error "error: ", methodName="validateMnemonic", errName = e.name, errDesription = e.msg + method generatedAccounts*(self: Service): seq[GeneratedAccountDto] = if(self.generatedAccounts.len == 0): error "There was some issue initiating account service" @@ -82,6 +110,7 @@ proc saveAccountAndLogin(self: Service, hashedPassword: string, account, error = response.result["error"].getStr if error == "": debug "Account saved succesfully" + self.isFirstTimeAccountLogin = true result = toAccountDto(account) return @@ -91,70 +120,93 @@ proc saveAccountAndLogin(self: Service, hashedPassword: string, account, except Exception as e: error "error: ", methodName="saveAccountAndLogin", errName = e.name, errDesription = e.msg +proc prepareAccountJsonObject(self: Service, account: GeneratedAccountDto): JsonNode = + result = %* { + "name": account.alias, + "address": account.address, + "identicon": account.identicon, + "key-uid": account.keyUid, + "keycard-pairing": nil + } + proc getAccountDataForAccountId(self: Service, accountId: string): JsonNode = for acc in self.generatedAccounts: if(acc.id == accountId): - result = %* { - "name": acc.alias, - "address": acc.address, - "identicon": acc.identicon, - "key-uid": acc.keyUid, - "keycard-pairing": nil - } + return self.prepareAccountJsonObject(acc) + + if(self.importedAccount.isValid()): + if(self.importedAccount.id == accountId): + return self.prepareAccountJsonObject(self.importedAccount) + +proc prepareSubaccountJsonObject(self: Service, account: GeneratedAccountDto): + JsonNode = + result = %* [ + { + "public-key": account.derivedAccounts.defaultWallet.publicKey, + "address": account.derivedAccounts.defaultWallet.address, + "color": "#4360df", + "wallet": true, + "path": PATH_DEFAULT_WALLET, + "name": "Status account" + }, + { + "public-key": account.derivedAccounts.whisper.publicKey, + "address": account.derivedAccounts.whisper.address, + "name": account.alias, + "identicon": account.identicon, + "path": PATH_WHISPER, + "chat": true + } + ] proc getSubaccountDataForAccountId(self: Service, accountId: string): JsonNode = for acc in self.generatedAccounts: if(acc.id == accountId): - result = %* [ - { - "public-key": acc.derivedAccounts.defaultWallet.publicKey, - "address": acc.derivedAccounts.defaultWallet.address, - "color": "#4360df", - "wallet": true, - "path": PATH_DEFAULT_WALLET, - "name": "Status account" - }, - { - "public-key": acc.derivedAccounts.whisper.publicKey, - "address": acc.derivedAccounts.whisper.address, - "name": acc.alias, - "identicon": acc.identicon, - "path": PATH_WHISPER, - "chat": true - } - ] + return self.prepareSubaccountJsonObject(acc) + + if(self.importedAccount.isValid()): + if(self.importedAccount.id == accountId): + return self.prepareSubaccountJsonObject(self.importedAccount) +proc prepareAccountSettingsJsonObject(self: Service, account: GeneratedAccountDto, + installationId: string): JsonNode = + result = %* { + "key-uid": account.keyUid, + "mnemonic": account.mnemonic, + "public-key": account.derivedAccounts.whisper.publicKey, + "name": account.alias, + "address": account.address, + "eip1581-address": account.derivedAccounts.eip1581.address, + "dapps-address": account.derivedAccounts.defaultWallet.address, + "wallet-root-address": account.derivedAccounts.walletRoot.address, + "preview-privacy?": true, + "signing-phrase": generateSigningPhrase(3), + "log-level": "INFO", + "latest-derived-path": 0, + "networks/networks": DEFAULT_NETWORKS, + "currency": "usd", + "identicon": account.identicon, + "waku-enabled": true, + "wallet/visible-tokens": { + "mainnet": ["SNT"] + }, + "appearance": 0, + "networks/current-network": DEFAULT_NETWORK_NAME, + "installation-id": installationId + } + proc getAccountSettings(self: Service, accountId: string, installationId: string): JsonNode = for acc in self.generatedAccounts: if(acc.id == accountId): - result = %* { - "key-uid": acc.keyUid, - "mnemonic": acc.mnemonic, - "public-key": acc.derivedAccounts.whisper.publicKey, - "name": acc.alias, - "address": acc.address, - "eip1581-address": acc.derivedAccounts.eip1581.address, - "dapps-address": acc.derivedAccounts.defaultWallet.address, - "wallet-root-address": acc.derivedAccounts.walletRoot.address, - "preview-privacy?": true, - "signing-phrase": generateSigningPhrase(3), - "log-level": "INFO", - "latest-derived-path": 0, - "networks/networks": DEFAULT_NETWORKS, - "currency": "usd", - "identicon": acc.identicon, - "waku-enabled": true, - "wallet/visible-tokens": { - "mainnet": ["SNT"] - }, - "appearance": 0, - "networks/current-network": DEFAULT_NETWORK_NAME, - "installation-id": installationId - } + return self.prepareAccountSettingsJsonObject(acc, installationId) -proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig, installationId: string): - JsonNode = + if(self.importedAccount.isValid()): + if(self.importedAccount.id == accountId): + return self.prepareAccountSettingsJsonObject(self.importedAccount, installationId) + +proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig, + installationId: string): JsonNode = let networkConfig = getNetworkConfig(DEFAULT_NETWORK_NAME) let upstreamUrl = networkConfig["config"]["UpstreamConfig"]["URL"] let fleet = Fleet.PROD @@ -184,18 +236,50 @@ proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig, installation # result["ListenAddr"] = if existsEnv("STATUS_PORT"): newJString("0.0.0.0:" & $getEnv("STATUS_PORT")) else: newJString("0.0.0.0:30305") method setupAccount*(self: Service, fleetConfig: FleetConfig, accountId, - password: string): AccountDto = + password: string): bool = try: let installationId = $genUUID() let accountDataJson = self.getAccountDataForAccountId(accountId) let subaccountDataJson = self.getSubaccountDataForAccountId(accountId) - let settingsJSON = self.getAccountSettings(accountId, installationId) - let nodeConfig = self.getDefaultNodeConfig(fleetConfig, installationId) + let settingsJson = self.getAccountSettings(accountId, installationId) + let nodeConfigJson = self.getDefaultNodeConfig(fleetConfig, installationId) + + if(accountDataJson.isNil or subaccountDataJson.isNil or settingsJson.isNil or + nodeConfigJson.isNil): + let description = "at least one json object is not prepared well" + error "error: ", methodName="setupAccount", errDesription = description + return false let hashedPassword = hashString(password) discard self.storeDerivedAccounts(accountId, hashedPassword, PATHS) - return self.saveAccountAndLogin(hashedPassword, accountDataJson, - subaccountDataJson, settingsJSON, nodeConfig) + + self.loggedInAccount = self.saveAccountAndLogin(hashedPassword, + accountDataJson, subaccountDataJson, settingsJson, nodeConfigJson) + + return self.getLoggedInAccount.isValid() except Exception as e: error "error: ", methodName="setupAccount", errName = e.name, errDesription = e.msg + return false + +method importMnemonic*(self: Service, mnemonic: string): bool = + try: + let response = status_go.multiAccountImportMnemonic(mnemonic) + self.importedAccount = toGeneratedAccountDto(response.result) + + let responseDerived = status_go.deriveAccounts(self.importedAccount.id, PATHS) + self.importedAccount.derivedAccounts = toDerivedAccounts(responseDerived.result) + + let responseAlias = status_go.generateAlias( + self.importedAccount.derivedAccounts.whisper.publicKey) + self.importedAccount.alias = responseAlias.result.getStr + + let responseIdenticon = status_go.generateIdenticon( + self.importedAccount.derivedAccounts.whisper.publicKey) + self.importedAccount.identicon = responseIdenticon.result.getStr + + return self.importedAccount.isValid() + + except Exception as e: + error "error: ", methodName="importMnemonic", errName = e.name, errDesription = e.msg + return false \ No newline at end of file diff --git a/src/app_service/service/accounts/service_interface.nim b/src/app_service/service/accounts/service_interface.nim index 0accee7996..39d190d4ab 100644 --- a/src/app_service/service/accounts/service_interface.nim +++ b/src/app_service/service/accounts/service_interface.nim @@ -26,6 +26,22 @@ method generatedAccounts*(self: ServiceInterface): raise newException(ValueError, "No implementation available") method setupAccount*(self: ServiceInterface, fleetConfig: FleetConfig, - accountId, password: string): - AccountDto {.base.} = + accountId, password: string): bool {.base.} = raise newException(ValueError, "No implementation available") + +method getLoggedInAccount*(self: ServiceInterface): AccountDto {.base.} = + raise newException(ValueError, "No implementation available") + +method getImportedAccount*(self: ServiceInterface): GeneratedAccountDto + {.base.} = + raise newException(ValueError, "No implementation available") + +method isFirstTimeAccountLogin*(self: ServiceInterface): bool {.base.} = + raise newException(ValueError, "No implementation available") + +method validateMnemonic*(self: ServiceInterface, mnemonic: string): + string {.base.} = + raise newException(ValueError, "No implementation available") + +method importMnemonic*(self: ServiceInterface, mnemonic: string): bool {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index 383d9fcab4..de7b8c4e6d 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -269,7 +269,7 @@ proc mainProc() = # https://doc.qt.io/archives/qtjambi-4.5.2_01/com/trolltech/qt/qtjambi-linguist-programmers.html changeLanguage("en") - singletonInstance.engine.load(newQUrl("qrc:///main.qml")) + #singletonInstance.engine.load(newQUrl("qrc:///main.qml")) # Please note that this must use the `cdecl` calling convention because # it will be passed as a regular C function to statusgo_backend. This means that diff --git a/ui/app/AppLayouts/Onboarding/controls/AccountViewDelegate.qml b/ui/app/AppLayouts/Onboarding/controls/AccountViewDelegate.qml index f4eac0233e..637bfc884c 100644 --- a/ui/app/AppLayouts/Onboarding/controls/AccountViewDelegate.qml +++ b/ui/app/AppLayouts/Onboarding/controls/AccountViewDelegate.qml @@ -10,7 +10,7 @@ import shared.status 1.0 import StatusQ.Controls 0.1 as StatusQControls import StatusQ.Components 0.1 -Rectangle { +Rectangle { id: accountViewDelegate property string username: "Jotaro Kujo" @@ -20,7 +20,7 @@ Rectangle { property var onAccountSelect: function() {} property var isSelected: function() {} property bool selected: { - return isSelected(accountId, keyUid) + return isSelected(index, keyUid) } property bool isHovered: false @@ -85,7 +85,7 @@ Rectangle { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - onAccountSelect(accountId) + onAccountSelect(index) } onEntered: { accountViewDelegate.isHovered = true diff --git a/ui/app/AppLayouts/Onboarding/panels/AccountListPanel.qml b/ui/app/AppLayouts/Onboarding/panels/AccountListPanel.qml index 25a0a7470f..6ca6975af2 100644 --- a/ui/app/AppLayouts/Onboarding/panels/AccountListPanel.qml +++ b/ui/app/AppLayouts/Onboarding/panels/AccountListPanel.qml @@ -1,37 +1,31 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 -import "./samples/" + +import "../controls" import utils 1.0 ListView { - property var accounts: AccountsData {} + id: accountsView + property var isSelected: function () {} property var onAccountSelect: function () {} - id: accountsView anchors.fill: parent - model: accounts focus: true spacing: Style.current.smallPadding clip: true - delegate: AccountView { - username: model.alias + delegate: AccountViewDelegate { + username: model.username identicon: model.thumbnailImage || model.identicon keyUid: model.keyUid address: model.address || '' - isSelected: function (accountId, keyUid) { - return accountsView.isSelected(accountId, keyUid) + isSelected: function (index, keyUid) { + return accountsView.isSelected(index, keyUid) } - onAccountSelect: function (accountId) { - accountsView.onAccountSelect(accountId) + onAccountSelect: function (index) { + accountsView.onAccountSelect(index) } } } - -/*##^## -Designer { - D{i:0;autoSize:true;height:480;width:640} -} -##^##*/ diff --git a/ui/app/AppLayouts/Onboarding/popups/GenKeyModal.qml b/ui/app/AppLayouts/Onboarding/popups/GenKeyModal.qml index 3b67690b73..2f4e8858c0 100644 --- a/ui/app/AppLayouts/Onboarding/popups/GenKeyModal.qml +++ b/ui/app/AppLayouts/Onboarding/popups/GenKeyModal.qml @@ -1,31 +1,37 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 import QtGraphicalEffects 1.13 + import StatusQ.Controls 0.1 import utils 1.0 -import "../shared" -import "./Login" +import "../../../../shared" +import "../../../../shared/popups" +import "../panels" +import "../stores" + +// TODO: replace with StatusModal ModalPopup { - property string selectedId: "" + property int selectedIndex: 0 property var onClosed: function () {} property var onNextClick: function () {} id: popup //% "Choose a chat name" title: qsTrId("intro-wizard-title2") + height: 504 - AccountList { + AccountListPanel { id: accountList anchors.fill: parent interactive: false - accounts: onboardingModule.accountsModel - isSelected: function (accId) { - return accId === selectedId + model: OnboardingStore.onBoardingModul.accountsModel + isSelected: function (index) { + return index === selectedIndex } - onAccountSelect: function(accId) { - selectedId = accId + onAccountSelect: function(index) { + selectedIndex = index } } footer: StatusRoundButton { @@ -38,14 +44,8 @@ ModalPopup { icon.width: 20 icon.height: 16 onClicked : { - onNextClick(selectedId); + onNextClick(selectedIndex); popup.close() } } } - -/*##^## -Designer { - D{i:0;formeditorColor:"#ffffff";height:500;width:400} -} -##^##*/ diff --git a/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml b/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml index 5fb64b4b1c..e639cc541e 100644 --- a/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml +++ b/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml @@ -40,6 +40,7 @@ ModalPopup { StatusSmartIdenticon { id: identicon + source: OnboardingStore.onBoardingModul.importedAccountIdenticon anchors.top: info.bottom anchors.topMargin: Style.current.bigPadding anchors.horizontalCenter: parent.horizontalCenter @@ -53,7 +54,7 @@ ModalPopup { anchors.top: identicon.bottom anchors.topMargin: Style.current.padding anchors.horizontalCenter: identicon.horizontalCenter - text: OnboardingStore.currentAccount.username + text: OnboardingStore.onBoardingModul.importedAccountAlias font.weight: Font.Bold font.pixelSize: 15 } @@ -62,7 +63,7 @@ ModalPopup { anchors.top: username.bottom anchors.topMargin: Style.current.halfPadding anchors.horizontalCenter: username.horizontalCenter - text: OnboardingStore.currentAccount.address + text: OnboardingStore.onBoardingModul.importedAccountAddress width: 120 } diff --git a/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml b/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml index bdbaa92d5e..f926cc990e 100644 --- a/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml +++ b/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml @@ -149,16 +149,12 @@ ModalPopup { } } -// Connections { -// target: onboardingModel -// ignoreUnknownSignals: true -// onLoginResponseChanged: { -// if (error) { -// loading = false -// importLoginError.open() -// } -// } -// } + Connections { + target: onboardingModule + onAccountSetupError: { + importLoginError.open() + } + } onClicked: { if (storingPasswordModal) @@ -170,18 +166,16 @@ ModalPopup { else { loading = true -// loginModel.isCurrentFlow = false; -// onboardingModel.isCurrentFlow = true; const result = onboardingModule.storeSelectedAccountAndLogin(repeatPasswordField.text); const error = JSON.parse(result).error if (error) { importError.text += error return importError.open() } - onboardingModel.firstTimeLogin = true - applicationWindow.checkForStoringPassToKeychain(onboardingModel.currentAccount.username, - repeatPasswordField.text, true) + // NEED TO HANDLE IT +// applicationWindow.checkForStoringPassToKeychain(onboardingModel.currentAccount.username, +// repeatPasswordField.text, true) } } } diff --git a/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml b/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml index c8464c5807..a2e51c1200 100644 --- a/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml +++ b/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml @@ -3,15 +3,14 @@ pragma Singleton import QtQuick 2.13 QtObject { - property var onBoardingModel: onboardingModel - property var currentAccount: onboardingModel.currentAccount + property var onBoardingModul: onboardingModule function importMnemonic(mnemonic) { - onboardingModel.importMnemonic(mnemonic) + onBoardingModul.importMnemonic(mnemonic) } function setCurrentAccount(selectedAccountIdx) { - onboardingModel.setCurrentAccount(selectedAccountIdx) + onBoardingModul.setSelectedAccountByIndex(selectedAccountIdx) } property ListModel accountsSampleData: ListModel { diff --git a/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml b/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml index 9be1bdf426..335c5d2fcc 100644 --- a/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml +++ b/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml @@ -1,5 +1,9 @@ import QtQuick 2.13 +import "../popups" +import "../stores" +import "../shared" + Item { property var onClosed: function () {} id: genKeyView @@ -12,9 +16,9 @@ Item { GenKeyModal { property bool wentNext: false id: genKeyModal - onNextClick: function (accId) { + onNextClick: function (selectedIndex) { wentNext = true - onboardingModule.setSelectedAccountId(accId) + OnboardingStore.setCurrentAccount(selectedIndex) createPasswordModal.open() } onClosed: function () { @@ -31,9 +35,3 @@ Item { } } } - -/*##^## -Designer { - D{i:0;autoSize:true;formeditorColor:"#ffffff";height:480;width:640} -} -##^##*/ diff --git a/ui/app/AppLayouts/Onboarding/views/LoginView.qml b/ui/app/AppLayouts/Onboarding/views/LoginView.qml index d3550e64ec..18b94f1041 100644 --- a/ui/app/AppLayouts/Onboarding/views/LoginView.qml +++ b/ui/app/AppLayouts/Onboarding/views/LoginView.qml @@ -25,16 +25,10 @@ Item { id: loginView anchors.fill: parent - function setCurrentFlow(isLogin) { - LoginStore.loginModelInst.isCurrentFlow = isLogin; - OnboardingStore.onBoardingModel.isCurrentFlow = !isLogin; - } - function doLogin(password) { if (loading || password.length === 0) return - setCurrentFlow(true); loading = true LoginStore.login(password) applicationWindow.checkForStoringPassToKeychain(LoginStore.currentAccount.username, password, false) @@ -116,7 +110,6 @@ Item { ConfirmAddExistingKeyModal { id: confirmAddExstingKeyModal onOpenModalClick: function () { - setCurrentFlow(false); onExistingKeyClicked() } } @@ -128,7 +121,6 @@ Item { resetLogin() } onOpenModalClick: function () { - setCurrentFlow(true); onExistingKeyClicked() } } @@ -185,7 +177,7 @@ Item { anchors.top: changeAccountBtn.bottom anchors.topMargin: Style.current.padding * 2 enabled: !loading - placeholderText: loading ? + placeholderText: loading ? //% "Connecting..." qsTrId("connecting") : //% "Enter password" @@ -259,7 +251,6 @@ Item { anchors.topMargin: 16 anchors.horizontalCenter: parent.horizontalCenter onClicked: { - setCurrentFlow(false); onGenKeyClicked() } } diff --git a/ui/app/AppLayouts/Wallet/WalletLayout.qml b/ui/app/AppLayouts/Wallet/WalletLayout.qml index 9154566a93..e8ab163864 100644 --- a/ui/app/AppLayouts/Wallet/WalletLayout.qml +++ b/ui/app/AppLayouts/Wallet/WalletLayout.qml @@ -42,10 +42,11 @@ Item { width: walletView.width Component.onCompleted: { - if(RootStore.firstTimeLogin){ - RootStore.firstTimeLogin = false - RootStore.setInitialRange() - } + // Read in RootStore +// if(RootStore.firstTimeLogin){ +// RootStore.firstTimeLogin = false +// RootStore.setInitialRange() +// } } Timer { diff --git a/ui/app/AppLayouts/Wallet/stores/RootStore.qml b/ui/app/AppLayouts/Wallet/stores/RootStore.qml index b9ada81c0d..27dba904e3 100644 --- a/ui/app/AppLayouts/Wallet/stores/RootStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/RootStore.qml @@ -25,7 +25,12 @@ QtObject { property var historyView: walletModel.historyView - property bool firstTimeLogin: onboardingModel.isFirstTimeLogin + // This should be exposed to the UI via "walletModule", WalletModule should use + // Accounts Service which keeps the info about that. Then in the View of WalletModule + // we may have either QtProperty or Q_INVOKABLE function (proc marked as slot) + // depends on logic/need. + + //property bool firstTimeLogin: walletModule.isFirstTimeLogin property var tokens: { let count = walletModel.tokensView.defaultTokenList.rowCount() diff --git a/ui/app/AppLayouts/WalletV2/WalletV2Layout.qml b/ui/app/AppLayouts/WalletV2/WalletV2Layout.qml index 3819754839..30d10cb368 100644 --- a/ui/app/AppLayouts/WalletV2/WalletV2Layout.qml +++ b/ui/app/AppLayouts/WalletV2/WalletV2Layout.qml @@ -54,10 +54,11 @@ Item { width: walletView.width Component.onCompleted: { - if (walletView.store.onboardingModelInst.firstTimeLogin) { - walletView.store.onboardingModelInst.firstTimeLogin = false; - walletView.store.walletModelInst.setInitialRange(); - } + // Read in RootStore +// if (walletView.store.onboardingModelInst.firstTimeLogin) { +// walletView.store.onboardingModelInst.firstTimeLogin = false; +// walletView.store.walletModelInst.setInitialRange(); +// } } leftPanel: LeftTabView { diff --git a/ui/imports/shared/controls/SeedPhraseTextArea.qml b/ui/imports/shared/controls/SeedPhraseTextArea.qml index 6592066815..c1b7c61f44 100644 --- a/ui/imports/shared/controls/SeedPhraseTextArea.qml +++ b/ui/imports/shared/controls/SeedPhraseTextArea.qml @@ -24,7 +24,7 @@ Item { //% "Invalid seed phrase" errorText.text = qsTrId("custom-seed-phrase") } else { - errorText.text = onboardingModel.validateMnemonic(mnemonicTextField.textField.text) + errorText.text = onboardingModule.validateMnemonic(mnemonicTextField.textField.text) const regex = new RegExp('word [a-z]+ not found in the dictionary', 'i'); if (regex.test(errorText.text)) { //% "Invalid seed phrase" diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 4d6943b1aa..fb43ff2334 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -3,6 +3,10 @@ pragma Singleton import QtQuick 2.13 QtObject { + readonly property int onboardingAppState: 0 + readonly property int loginAppSate: 1 + readonly property int mainAppState: 2 + readonly property int communityImported: 0 readonly property int communityImportingInProgress: 1 readonly property int communityImportingError: 2 diff --git a/ui/main.qml b/ui/main.qml index 63a75c926d..92155fe177 100644 --- a/ui/main.qml +++ b/ui/main.qml @@ -20,7 +20,7 @@ import "./app/AppLayouts/Onboarding/views" import "./app" StatusWindow { - property bool hasAccounts: startupModule.startWithOnboardingScreen + property bool hasAccounts: startupModule.appState !== Constants.onboardingAppState property bool removeMnemonicAfterLogin: false property alias dragAndDrop: dragTarget property bool popupOpened: false @@ -361,7 +361,8 @@ StatusWindow { DSM.SignalTransition { targetState: appState - signal: onboardingModel.moveToAppState + signal: startupModule.appStateChanged + guard: state == Constants.mainAppState } } @@ -371,7 +372,8 @@ StatusWindow { DSM.SignalTransition { targetState: appState - signal: onboardingModel.moveToAppState + signal: startupModule.appStateChanged + guard: state == Constants.mainAppState } } @@ -381,7 +383,8 @@ StatusWindow { DSM.SignalTransition { targetState: appState - signal: onboardingModel.moveToAppState + signal: startupModule.appStateChanged + guard: state == Constants.mainAppState } } @@ -391,7 +394,8 @@ StatusWindow { DSM.SignalTransition { targetState: appState - signal: loginModel.moveToAppState + signal: startupModule.appStateChanged + guard: state == Constants.mainAppState } DSM.SignalTransition {