status-desktop/src/nim_status_client.nim

176 lines
5.3 KiB
Nim

import NimQml, chronicles, os, strformat
import app/chat/core as chat
import app/wallet/core as wallet
import app/node/core as node
import app/utilsView/core as utilsView
import app/profile/core as profile
import app/onboarding/core as onboarding
import app/login/core as login
import app/provider/core as provider
import status/signals/core as signals
import status/libstatus/types
import nim_status
import status/status as statuslib
import ./eventemitter
var signalsQObjPointer: pointer
logScope:
topics = "main"
proc mainProc() =
let status = statuslib.newStatusInstance(readFile(joinPath(getAppDir(), "../fleets.json")))
status.initNode()
enableHDPI()
initializeOpenGL()
let app = newQApplication("Status Desktop")
let resources =
if defined(windows) and getEnv("NIM_STATUS_CLIENT_DEV").string == "":
"/../resources/resources.rcc"
else:
"/../resources.rcc"
QResource.registerResource(app.applicationDirPath & resources)
let statusAppIcon =
if defined(macosx):
if getEnv("NIM_STATUS_CLIENT_DEV").string == "":
"/../Resources/status-icon.icns"
else:
"/../status-icon.icns"
elif defined(windows) and getEnv("NIM_STATUS_CLIENT_DEV").string == "":
"/../resources/status.svg"
else:
"/../status.svg"
app.icon(app.applicationDirPath & statusAppIcon)
var i18nPath = ""
if (getEnv("NIM_STATUS_CLIENT_DEV").string != ""):
i18nPath = joinPath(getAppDir(), "../ui/i18n")
elif (defined(windows)):
i18nPath = joinPath(getAppDir(), "../resources/i18n")
elif (defined(macosx)):
i18nPath = joinPath(getAppDir(), "../i18n")
elif (defined(linux)):
i18nPath = joinPath(getAppDir(), "../i18n")
let engine = newQQmlApplicationEngine()
let signalController = signals.newController(status)
# We need this global variable in order to be able to access the application
# from the non-closure callback passed to `libstatus.setSignalEventCallback`
signalsQObjPointer = cast[pointer](signalController.vptr)
var wallet = wallet.newController(status)
engine.setRootContextProperty("walletModel", wallet.variant)
var chat = chat.newController(status)
engine.setRootContextProperty("chatsModel", chat.variant)
var node = node.newController(status)
engine.setRootContextProperty("nodeModel", node.variant)
var utilsController = utilsView.newController(status)
engine.setRootContextProperty("utilsModel", utilsController.variant)
proc changeLanguage(locale: string) =
engine.setTranslationPackage(joinPath(i18nPath, fmt"qml_{locale}.qm"))
var profile = profile.newController(status, changeLanguage)
engine.setRootContextProperty("profileModel", profile.variant)
var provider = provider.newController(status)
engine.setRootContextProperty("web3Provider", provider.variant)
var login = login.newController(status)
var onboarding = onboarding.newController(status)
status.events.once("login") do(a: Args):
var args = AccountArgs(a)
# Delete login and onboarding from memory to remove any mnemonic that would have been saved in the accounts list
login.delete()
onboarding.delete()
status.startMessenger()
profile.init(args.account)
wallet.init()
provider.init()
chat.init()
utilsController.init()
wallet.checkPendingTransactions()
wallet.start()
engine.setRootContextProperty("loginModel", login.variant)
engine.setRootContextProperty("onboardingModel", onboarding.variant)
let isExperimental = if getEnv("EXPERIMENTAL") == "1": "1" else: "0" # value explicity passed to avoid trusting input
let experimentalFlag = newQVariant(isExperimental)
engine.setRootContextProperty("isExperimental", experimentalFlag)
defer:
error "TODO: if user is logged in, logout"
provider.delete()
engine.delete()
app.delete()
signalController.delete()
login.delete()
onboarding.delete()
wallet.delete()
chat.delete()
profile.delete()
utilsController.delete()
# Initialize only controllers whose init functions
# do not need a running node
proc initControllers() =
node.init()
login.init()
onboarding.init()
initControllers()
# Handle node.stopped signal when user has logged out
status.events.once("nodeStopped") do(a: Args):
# TODO: remove this once accounts are not tracked in the AccountsModel
status.reset()
# 1. Reset controller data
login.reset()
onboarding.reset()
# TODO: implement all controller resets
# chat.reset()
# node.reset()
# wallet.reset()
# profile.reset()
# 2. Re-init controllers that don't require a running node
initControllers()
engine.setRootContextProperty("signals", signalController.variant)
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 libstatus. This means that
# we cannot capture any local variables here (we must rely on globals)
var callback: SignalCallback = proc(p0: cstring) {.cdecl.} =
setupForeignThreadGc()
signal_handler(signalsQObjPointer, p0, "receiveSignal")
tearDownForeignThreadGc()
nim_status.setSignalEventCallback(callback)
# Qt main event loop is entered here
# The termination of the loop will be performed when exit() or quit() is called
info "Starting application..."
app.exec()
when isMainModule:
mainProc()
GC_fullcollect()