onboarding process updated, import account feature handled

This commit is contained in:
Sale Djenic 2021-10-14 10:04:15 +02:00 committed by Iuri Matias
parent e9bb9b256e
commit 30f11c06d4
51 changed files with 757 additions and 383 deletions

View File

@ -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()
@ -122,3 +125,7 @@ proc load*(self: AppController) =
self.communityService.init()
self.mainModule.load()
proc accountCreated*(self: AppController) =
echo "AppController account created"
self.load()

View File

@ -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
method shouldStartWithOnboardingScreen*(self: Controller): bool =
return self.accountsService.openedAccounts().len == 0

View File

@ -11,8 +11,3 @@ 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

View File

@ -1,22 +1,19 @@
# Defines how parent module accesses this module
include ./private_interfaces/module_base_interface
include ./private_interfaces/module_access_interface
# Defines how this module view communicates with this module
include ./private_interfaces/module_view_delegate_interface
# 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
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")
# 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.startupDidLoad()
c.accountCreated()

View File

@ -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

View File

@ -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())

View File

@ -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
@ -10,9 +10,5 @@ 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
method getOpenedAccounts*(self: AccessInterface): seq[AccountDto] {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -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

View File

@ -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

View File

@ -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
Model* = ref object of QAbstractListModel
sections: seq[Item]
items: seq[AccountItem]
proc delete(self: Model) =
self.items = @[]
self.QAbstractListModel.delete
proc setup(self: Model) =
self.QAbstractListModel.setup
proc delete*(self: Model) =
self.QAbstractListModel.delete
proc newModel*(): Model =
new(result, delete)
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()

View File

@ -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
self.moduleLoaded = true
self.delegate.loginDidLoad()

View File

@ -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.

View File

@ -0,0 +1,2 @@
method viewDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -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()
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

View File

@ -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]) =
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)

View File

@ -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 setSelectedAccountByIndex*(self: Controller, index: int) =
let accounts = self.getGeneratedAccounts()
self.selectedAccountId = accounts[index].id
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()
method storeSelectedAccountAndLogin*[T](self: Controller[T], password: string) =
let account = self.accountsService.setupAccount(self.appService.status.fleet.config,
self.selectedAccountId, password)
echo "RECEIVED ACCOUNT: ", repr(account)

View File

@ -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")
type
## Abstract class (concept) which must be implemented by object/s used in this
## module.
DelegateInterface* = concept c
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")

View File

@ -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

View File

@ -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"

View File

@ -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()
@ -46,17 +47,36 @@ method load*[T](self: Module[T]) =
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) =
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()

View File

@ -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.

View File

@ -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")

View File

@ -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")

View File

@ -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)
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()

View File

@ -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")

View File

@ -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.

View File

@ -0,0 +1,2 @@
method loginDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -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")

View File

@ -0,0 +1,2 @@
method viewDidLoad*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -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
QtProperty[int] appState:
read = getAppState
notify = appStateChanged

View File

@ -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)

View File

@ -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

View File

@ -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,59 +120,72 @@ proc saveAccountAndLogin(self: Service, hashedPassword: string, account,
except Exception as e:
error "error: ", methodName="saveAccountAndLogin", errName = e.name, errDesription = e.msg
proc getAccountDataForAccountId(self: Service, accountId: string): JsonNode =
for acc in self.generatedAccounts:
if(acc.id == accountId):
proc prepareAccountJsonObject(self: Service, account: GeneratedAccountDto): JsonNode =
result = %* {
"name": acc.alias,
"address": acc.address,
"identicon": acc.identicon,
"key-uid": acc.keyUid,
"name": account.alias,
"address": account.address,
"identicon": account.identicon,
"key-uid": account.keyUid,
"keycard-pairing": nil
}
proc getSubaccountDataForAccountId(self: Service, accountId: string): JsonNode =
proc getAccountDataForAccountId(self: Service, accountId: string): JsonNode =
for acc in self.generatedAccounts:
if(acc.id == accountId):
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": acc.derivedAccounts.defaultWallet.publicKey,
"address": acc.derivedAccounts.defaultWallet.address,
"public-key": account.derivedAccounts.defaultWallet.publicKey,
"address": account.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,
"public-key": account.derivedAccounts.whisper.publicKey,
"address": account.derivedAccounts.whisper.address,
"name": account.alias,
"identicon": account.identicon,
"path": PATH_WHISPER,
"chat": true
}
]
proc getAccountSettings(self: Service, accountId: string,
installationId: string): JsonNode =
proc getSubaccountDataForAccountId(self: Service, accountId: string): JsonNode =
for acc in self.generatedAccounts:
if(acc.id == accountId):
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": 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,
"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": acc.identicon,
"identicon": account.identicon,
"waku-enabled": true,
"wallet/visible-tokens": {
"mainnet": ["SNT"]
@ -153,8 +195,18 @@ proc getAccountSettings(self: Service, accountId: string,
"installation-id": installationId
}
proc getDefaultNodeConfig*(self: Service, fleetConfig: FleetConfig, installationId: string):
JsonNode =
proc getAccountSettings(self: Service, accountId: string,
installationId: string): JsonNode =
for acc in self.generatedAccounts:
if(acc.id == accountId):
return self.prepareAccountSettingsJsonObject(acc, installationId)
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

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -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}
}
##^##*/

View File

@ -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}
}
##^##*/

View File

@ -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
}

View File

@ -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)
}
}
}

View File

@ -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 {

View File

@ -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}
}
##^##*/

View File

@ -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()
}
}
@ -259,7 +251,6 @@ Item {
anchors.topMargin: 16
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
setCurrentFlow(false);
onGenKeyClicked()
}
}

View File

@ -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 {

View File

@ -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()

View File

@ -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 {

View File

@ -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"

View File

@ -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

View File

@ -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 {