status-desktop/src/nim_status_client.nim

240 lines
8.4 KiB
Nim
Raw Normal View History

import NimQml, chronicles, os, strformat, times, md5, json
import app/chat/core as chat
2021-08-13 20:04:04 +00:00
import app/wallet/v1/core as wallet
import app/wallet/v2/core as walletV2
import app/node/core as node
import app/utilsView/core as utilsView
2021-09-24 12:03:57 +00:00
import app/keycard/core as keycard
import status/types/[account]
import status_go
import status/status as statuslib
import eventemitter
import app_service/tasks/marathon/mailserver/controller as mailserver_controller
import app_service/tasks/marathon/mailserver/worker as mailserver_worker
import app_service/main
import constants
import app/core/global_singleton
import app/boot/app_controller
2020-05-18 18:48:20 +00:00
var signalsQObjPointer: pointer
2020-05-21 19:07:55 +00:00
logScope:
topics = "main"
2020-05-06 17:40:00 +00:00
proc mainProc() =
if defined(macosx) and defined(production):
setCurrentDir(getAppDir())
ensureDirectories(DATADIR, TMPDIR, LOGDIR)
let fleets =
feat: command-line option can be used to specify app's data directory In the repo: ``` $ bin/nim_status_client --help ``` In the packaged app (macOS example): ``` $ cd /Applications/Status.app/Contents/MacOS $ ./nim_status_client --help ``` Output: ``` Usage: nim_status_client [OPTIONS]... The following options are available: -d, --dataDir Status Desktop data directory. ``` **Using the option** ``` $ cd ~/status-ci-builds/master/Status.app/Contents/MacOS $ ./nim_status_client --dataDir:"${HOME}/status-dirs/master" ``` In another terminal: ``` $ cd ~/status-ci-builds/PR-4242/Status.app/Contents/MacOS $ ./nim_status_client --dataDir:"${HOME}/status-dirs/PR-4242" ``` The path supplied can be relative or absolute, and can be specified with `--dataDir:[path]`, `--dataDir=[path]`, `-d:[path]`, or `-d=[path]`. Either `:` or `=` must be used, i.e. this *will not* work: `--dataDir [path]` or `-d [path]`. The name of the option follows Nim's partial case-insensitivity rules, so `--dataDir`, `--datadir`, and `--data_dir` are all equivalent. See [Identifier equality][ieq] in the Nim Manual. It is possible to run the same build in multiple terminals by supplying different `--dataDir`, i.e. this works: ``` $ cd /Applications/Status.app/Contents/MacOS $ ./nim_status_client --dataDir="${HOME}/temp/some1" ``` In another terminal: ``` $ cd /Applications/Status.app/Contents/MacOS $ ./nim_status_client --dataDir="${HOME}/temp/some2" ``` **Windows** It is recommended to use a Git Bash or MSYS2 terminal when invoking `bin/nim_status_client.exe` (development build) or `bin/Status.exe` (production build) on the command-line. The reason is that if the exe is invoked in a session of `cmd.exe` it will return to the prompt immediately; the app will run but there will be no output in the terminal. In any case, the `--dataDir` option will take effect whether the exe is invoked in `cmd.exe` or a recommended terminal. For development builds, when invoking `bin/nim_status_client.exe` directly instead of via `make run`, because e.g. you wish to use the `--dataDir` option, it is required to first setup the `PATH` environment variable correctly. See the `run-windows` target in this repo's Makefile for more information. **Linux** The `--dataDir` option may be passed to command-line invocation of a production (AppImage) build in the same way as passing it to a development build: ``` $ Status.AppImage --dataDir:/path/to/wherever ``` For development builds, when invoking `bin/nim_status_client` directly instead of via `make run`, because e.g. you wish to use the `--dataDir` option, it is required to setup the `LD_LIBRARY_PATH` environment variable correctly. See the `run-linux` target in this repo's Makefile for more information. --- BREAKING CHANGE: The `qt` subdir of the app's data directory is now a sibling of the status-go directory rather than a subdir of the status-go directory: ``` Status (app data directory) ├── data (status-go directory) ├── qt └── tmp ``` Because app settings are stored in the `qt` directory that means that existing installations will lose their customized settings. At app startup, it would be possible to detect `Status/data/qt` and if `Status/qt` doesn't exist yet then copy `Status/data/qt` to `Status/qt`. However, there was some concern that behavior could lead to problems later on if we forget the workaround is in place. So for now that settings preservation strategy has not been implemented, but it might be before this commit is merged pending full team awareness/consensus. --- Command-line option support is provided by [nim-confutils](https://github.com/status-im/nim-confutils). The environment variable `NIM_STATUS_CLIENT_DEV` has been removed in favor of passing a "define" option to the Nim compiler: `-d:development` for development builds (e.g. `make V=1`) and `-d:production` for packaged builds (e.g. `make V=1 pkg`). Passing the correct option is handled automatically by the Makefile. A make variable named `RELEASE` has been introduced, which defaults to `false`. Presently the `RELEASE` variable should not be set on the command-line nor in CI as more work needs to be done to toggle the proper compiler flags. In the case of Status Desktop, "release vs. debug" is a concern orthogonal to "production vs. development". At present, production builds and development builds are all debug builds, but that will likely change in the future: we can have non-release CI production builds and local development builds be debug builds, while release builds in CI would be production builds with `RELEASE=true` (the compiled executable will be fully optimized). Prior to the changes in this PR, symmetry is somewhat lacking between development and production (packaged) builds with respect to the concept of the "data directory". In development builds the root of the repo effectively serves as the `Status` directory used by production builds, e.g. on macOS `~/Library/Application Support/Status`. Also, there's a bit of confusion as to whether "data directory" refers to a directory for the desktop app's overall data (including status-go data) or to the specific directory used by status-go. This PR attempts to provide symmetry and reduce confusion: * The term "data directory" means the directory used by the desktop app to store multiple kinds of data and is not a reference to the subdirectory used by status-go. * For development builds the "data directory" defaults to `./Status/` relative to the root of the repo. * For production builds the "data directory" default is the same as before, e.g. on macOS it's ` ~/Library/Application Support/Status/`. The directory used by status-go is `Status/data/`. To be clear, that should be referred to as the "status-go directory" and not the app's "data directory". It would nice if we could rename it from `Status/data/` to `Status/status-go/`. We can do that, I already checked that it works correctly; however, for existing installations it would require that at app launch we check for the presence of `Status/data/` and rename it to `Status/status-go`. While simple enough to do, I was concerned that there might be edge cases where the directory rename could cause a problem (e.g. if another copy of the app is running) so chose for now to stick with the status-go directory being `Status/data/`. --- **NOTES** More work needs to be done to ensure that all data written by the app is contained in the default or cli-specified data directory. Currently, both development and production (packaged) builds are writing to common directories outside of the data directory, e.g. located within `~/Library/` on macOS. Changing that behavior seems like it will mainly involve changing defaults related to Qt components such as the web engine. See: https://github.com/status-im/status-desktop/issues/1141. In general, additional refactoring could be done in the future. For example, implementing `StatusDesktopConfig` in `src/status/libstatus/accounts/constants.nim` (as done in this PR) works fine for now, but better code organization is desirable. --- Closes #2268 [ieq]: https://nim-lang.org/docs/manual.html#lexical-analysis-identifier-equality
2021-04-19 12:20:07 +00:00
if defined(windows) and defined(production):
"/../resources/fleets.json"
else:
"/../fleets.json"
let
fleetConfig = readFile(joinPath(getAppDir(), fleets))
status = statuslib.newStatusInstance(fleetConfig)
mailserverController = mailserver_controller.newController(status)
mailserverWorker = mailserver_worker.newMailserverWorker(cast[ByteAddress](mailserverController.vptr))
let appService = newAppService(status, mailserverWorker)
defer: appService.delete()
status.initNode(STATUSGODIR, KEYSTOREDIR)
let uiScaleFilePath = joinPath(DATADIR, "ui-scale")
enableHDPI(uiScaleFilePath)
initializeOpenGL()
2020-06-23 19:31:52 +00:00
let app = newQGuiApplication()
defer: app.delete()
let appController = newAppController(appService)
defer: appController.delete()
build: implement packaging steps for the Windows build Implement a `pkg-windows` target that ultimately results in `Status.zip` being written to `pkg/`. Note: this commit does not introduce code signing for the Windows build since that piece is still a work in progress. `pkg-windows` creates a portable folder in `tmp/windows/dist` with the help of [`windeployqt`][windeployqt], which copies the needed portions of Qt into the folder. Since DLL resolution is relatively inflexible, a launcher `Status.exe` is created at the top-level of the folder; the launcher opens `bin/Status.exe` while adding the portable folder's `bin/` to the `PATH`, allowing `bin/Status.exe` to resolve the DLLs in that folder. A few additional tools need to be installed (e.g. with [scoop][scoop]) and availble in `PATH`: * 7-zip * dos2unix (provides unix2dos) * findutils * go * rcedit * wget The above list builds on the tools list in PR #521, and the other requirements and instructions in that PR's description still apply. **Why not build an installer?** When starting work on packaging for the Windows build, my initial plan was to build an installer, and for that purpose I researched the [WiX Toolset][wix], the [Qt Installer Framework][qtif], and some other options. I found that building an installer is a bit complex. I then recalled, from personal experience, that [Cmder][cmder]'s [Mini download][mini] is installer-less. You simply unzip the download and place the `cmder_mini` folder wherever you prefer. Such an approach was also recommended to me in one of the Nim language's community chats. In addition to being simpler, the installer-less approach also gives installation of Status Desktop a lower profile than an installer-application would since nothing is written to the Windows registry, added to the *Add or remove programs* list, etc. I think that's a benefit given the privacy-security focus of Status, but others may feel differently so please provide feedback on this point! [windeployqt]: https://doc.qt.io/qt-5/windows-deployment.html [scoop]: https://scoop.sh/ [wix]: https://wixtoolset.org/ [qtif]: https://doc.qt.io/qtinstallerframework/index.html [cmder]: https://cmder.net/ [mini]: https://github.com/cmderdev/cmder/releases/download/v1.3.15/cmder_mini.zip
2020-07-15 22:45:56 +00:00
let resources =
feat: command-line option can be used to specify app's data directory In the repo: ``` $ bin/nim_status_client --help ``` In the packaged app (macOS example): ``` $ cd /Applications/Status.app/Contents/MacOS $ ./nim_status_client --help ``` Output: ``` Usage: nim_status_client [OPTIONS]... The following options are available: -d, --dataDir Status Desktop data directory. ``` **Using the option** ``` $ cd ~/status-ci-builds/master/Status.app/Contents/MacOS $ ./nim_status_client --dataDir:"${HOME}/status-dirs/master" ``` In another terminal: ``` $ cd ~/status-ci-builds/PR-4242/Status.app/Contents/MacOS $ ./nim_status_client --dataDir:"${HOME}/status-dirs/PR-4242" ``` The path supplied can be relative or absolute, and can be specified with `--dataDir:[path]`, `--dataDir=[path]`, `-d:[path]`, or `-d=[path]`. Either `:` or `=` must be used, i.e. this *will not* work: `--dataDir [path]` or `-d [path]`. The name of the option follows Nim's partial case-insensitivity rules, so `--dataDir`, `--datadir`, and `--data_dir` are all equivalent. See [Identifier equality][ieq] in the Nim Manual. It is possible to run the same build in multiple terminals by supplying different `--dataDir`, i.e. this works: ``` $ cd /Applications/Status.app/Contents/MacOS $ ./nim_status_client --dataDir="${HOME}/temp/some1" ``` In another terminal: ``` $ cd /Applications/Status.app/Contents/MacOS $ ./nim_status_client --dataDir="${HOME}/temp/some2" ``` **Windows** It is recommended to use a Git Bash or MSYS2 terminal when invoking `bin/nim_status_client.exe` (development build) or `bin/Status.exe` (production build) on the command-line. The reason is that if the exe is invoked in a session of `cmd.exe` it will return to the prompt immediately; the app will run but there will be no output in the terminal. In any case, the `--dataDir` option will take effect whether the exe is invoked in `cmd.exe` or a recommended terminal. For development builds, when invoking `bin/nim_status_client.exe` directly instead of via `make run`, because e.g. you wish to use the `--dataDir` option, it is required to first setup the `PATH` environment variable correctly. See the `run-windows` target in this repo's Makefile for more information. **Linux** The `--dataDir` option may be passed to command-line invocation of a production (AppImage) build in the same way as passing it to a development build: ``` $ Status.AppImage --dataDir:/path/to/wherever ``` For development builds, when invoking `bin/nim_status_client` directly instead of via `make run`, because e.g. you wish to use the `--dataDir` option, it is required to setup the `LD_LIBRARY_PATH` environment variable correctly. See the `run-linux` target in this repo's Makefile for more information. --- BREAKING CHANGE: The `qt` subdir of the app's data directory is now a sibling of the status-go directory rather than a subdir of the status-go directory: ``` Status (app data directory) ├── data (status-go directory) ├── qt └── tmp ``` Because app settings are stored in the `qt` directory that means that existing installations will lose their customized settings. At app startup, it would be possible to detect `Status/data/qt` and if `Status/qt` doesn't exist yet then copy `Status/data/qt` to `Status/qt`. However, there was some concern that behavior could lead to problems later on if we forget the workaround is in place. So for now that settings preservation strategy has not been implemented, but it might be before this commit is merged pending full team awareness/consensus. --- Command-line option support is provided by [nim-confutils](https://github.com/status-im/nim-confutils). The environment variable `NIM_STATUS_CLIENT_DEV` has been removed in favor of passing a "define" option to the Nim compiler: `-d:development` for development builds (e.g. `make V=1`) and `-d:production` for packaged builds (e.g. `make V=1 pkg`). Passing the correct option is handled automatically by the Makefile. A make variable named `RELEASE` has been introduced, which defaults to `false`. Presently the `RELEASE` variable should not be set on the command-line nor in CI as more work needs to be done to toggle the proper compiler flags. In the case of Status Desktop, "release vs. debug" is a concern orthogonal to "production vs. development". At present, production builds and development builds are all debug builds, but that will likely change in the future: we can have non-release CI production builds and local development builds be debug builds, while release builds in CI would be production builds with `RELEASE=true` (the compiled executable will be fully optimized). Prior to the changes in this PR, symmetry is somewhat lacking between development and production (packaged) builds with respect to the concept of the "data directory". In development builds the root of the repo effectively serves as the `Status` directory used by production builds, e.g. on macOS `~/Library/Application Support/Status`. Also, there's a bit of confusion as to whether "data directory" refers to a directory for the desktop app's overall data (including status-go data) or to the specific directory used by status-go. This PR attempts to provide symmetry and reduce confusion: * The term "data directory" means the directory used by the desktop app to store multiple kinds of data and is not a reference to the subdirectory used by status-go. * For development builds the "data directory" defaults to `./Status/` relative to the root of the repo. * For production builds the "data directory" default is the same as before, e.g. on macOS it's ` ~/Library/Application Support/Status/`. The directory used by status-go is `Status/data/`. To be clear, that should be referred to as the "status-go directory" and not the app's "data directory". It would nice if we could rename it from `Status/data/` to `Status/status-go/`. We can do that, I already checked that it works correctly; however, for existing installations it would require that at app launch we check for the presence of `Status/data/` and rename it to `Status/status-go`. While simple enough to do, I was concerned that there might be edge cases where the directory rename could cause a problem (e.g. if another copy of the app is running) so chose for now to stick with the status-go directory being `Status/data/`. --- **NOTES** More work needs to be done to ensure that all data written by the app is contained in the default or cli-specified data directory. Currently, both development and production (packaged) builds are writing to common directories outside of the data directory, e.g. located within `~/Library/` on macOS. Changing that behavior seems like it will mainly involve changing defaults related to Qt components such as the web engine. See: https://github.com/status-im/status-desktop/issues/1141. In general, additional refactoring could be done in the future. For example, implementing `StatusDesktopConfig` in `src/status/libstatus/accounts/constants.nim` (as done in this PR) works fine for now, but better code organization is desirable. --- Closes #2268 [ieq]: https://nim-lang.org/docs/manual.html#lexical-analysis-identifier-equality
2021-04-19 12:20:07 +00:00
if defined(windows) and defined(production):
build: implement packaging steps for the Windows build Implement a `pkg-windows` target that ultimately results in `Status.zip` being written to `pkg/`. Note: this commit does not introduce code signing for the Windows build since that piece is still a work in progress. `pkg-windows` creates a portable folder in `tmp/windows/dist` with the help of [`windeployqt`][windeployqt], which copies the needed portions of Qt into the folder. Since DLL resolution is relatively inflexible, a launcher `Status.exe` is created at the top-level of the folder; the launcher opens `bin/Status.exe` while adding the portable folder's `bin/` to the `PATH`, allowing `bin/Status.exe` to resolve the DLLs in that folder. A few additional tools need to be installed (e.g. with [scoop][scoop]) and availble in `PATH`: * 7-zip * dos2unix (provides unix2dos) * findutils * go * rcedit * wget The above list builds on the tools list in PR #521, and the other requirements and instructions in that PR's description still apply. **Why not build an installer?** When starting work on packaging for the Windows build, my initial plan was to build an installer, and for that purpose I researched the [WiX Toolset][wix], the [Qt Installer Framework][qtif], and some other options. I found that building an installer is a bit complex. I then recalled, from personal experience, that [Cmder][cmder]'s [Mini download][mini] is installer-less. You simply unzip the download and place the `cmder_mini` folder wherever you prefer. Such an approach was also recommended to me in one of the Nim language's community chats. In addition to being simpler, the installer-less approach also gives installation of Status Desktop a lower profile than an installer-application would since nothing is written to the Windows registry, added to the *Add or remove programs* list, etc. I think that's a benefit given the privacy-security focus of Status, but others may feel differently so please provide feedback on this point! [windeployqt]: https://doc.qt.io/qt-5/windows-deployment.html [scoop]: https://scoop.sh/ [wix]: https://wixtoolset.org/ [qtif]: https://doc.qt.io/qtinstallerframework/index.html [cmder]: https://cmder.net/ [mini]: https://github.com/cmderdev/cmder/releases/download/v1.3.15/cmder_mini.zip
2020-07-15 22:45:56 +00:00
"/../resources/resources.rcc"
else:
"/../resources.rcc"
QResource.registerResource(app.applicationDirPath & resources)
var eventStr = ""
if OPENURI.len > 0:
eventStr = $(%* { "uri": OPENURI })
let singleInstance = newSingleInstance($toMD5(DATADIR), eventStr)
2021-09-06 13:37:00 +00:00
defer: singleInstance.delete()
if singleInstance.secondInstance():
info "Terminating the app as the second instance"
quit()
let statusAppIcon =
if defined(production):
if defined(macosx):
"" # not used in macOS
elif defined(windows):
"/../resources/status.svg"
else:
"/../status.svg"
else:
if defined(macosx):
"" # not used in macOS
else:
"/../status-dev.svg"
if not defined(macosx):
app.icon(app.applicationDirPath & statusAppIcon)
2020-06-23 22:54:21 +00:00
2020-11-23 14:24:09 +00:00
let networkAccessFactory = newQNetworkAccessManagerFactory(TMPDIR & "netcache")
feat: load installed stickers while offline When the network connection is changed, the sticker packs are cleared and then re-loaded (either loading the offline (installed) sticker packs, or all the sticker packs from the network). Stickers can be sent while offline, though the sticker images do not load once offline (this is likely a side effect of the bug described below). There is a known bug in QNetworkAccessManager (https://bugreports.qt.io/browse/QTBUG-55180) that was re-introduced in 5.14.1 that does not allow us to download resources if we go offline then come back online. The workaround employed in this PR manually sets the NetworkAccessible property of QNetworkAccessManager once we have been connected back online. The NetworkAccessible property is marked as obsolete and will be removed in Qt6, so it is something that we need to be aware of when we upgrade. However the hope is that the bug has been fixed. Close StickersPopup when disconnected from network (so that re-loading of sticker packs doesn't look out of place). fix: set network status correctly at load feat: stickers gas estimate async feat: When network re-connected, any http images that were not properly loaded in an ImageLoader component will automatically be reloaded. fix: Sticker button loading icon chore: Bump nimqml and dotherside NOTE: This PR uses an updated nimqml and dotherside. The respective changes should be merged first, and the commit hash should be bumped in this PR prior to merging. Relevant PRs: [https://github.com/status-im/dotherside/pull/20](https://github.com/status-im/dotherside/pull/20) [https://github.com/status-im/nimqml/pull/17](https://github.com/status-im/nimqml/pull/17)
2020-12-14 05:50:47 +00:00
singletonInstance.engine.addImportPath("qrc:/./StatusQ/src")
singletonInstance.engine.addImportPath("qrc:/./imports")
singletonInstance.engine.setNetworkAccessManagerFactory(networkAccessFactory)
singletonInstance.engine.setRootContextProperty("uiScaleFilePath", newQVariant(uiScaleFilePath))
2021-09-24 12:03:57 +00:00
# Register events objects
let dockShowAppEvent = newStatusDockShowAppEventObject(singletonInstance.engine)
defer: dockShowAppEvent.delete()
let osThemeEvent = newStatusOSThemeEventObject(singletonInstance.engine)
defer: osThemeEvent.delete()
app.installEventFilter(dockShowAppEvent)
app.installEventFilter(osThemeEvent)
feat: load installed stickers while offline When the network connection is changed, the sticker packs are cleared and then re-loaded (either loading the offline (installed) sticker packs, or all the sticker packs from the network). Stickers can be sent while offline, though the sticker images do not load once offline (this is likely a side effect of the bug described below). There is a known bug in QNetworkAccessManager (https://bugreports.qt.io/browse/QTBUG-55180) that was re-introduced in 5.14.1 that does not allow us to download resources if we go offline then come back online. The workaround employed in this PR manually sets the NetworkAccessible property of QNetworkAccessManager once we have been connected back online. The NetworkAccessible property is marked as obsolete and will be removed in Qt6, so it is something that we need to be aware of when we upgrade. However the hope is that the bug has been fixed. Close StickersPopup when disconnected from network (so that re-loading of sticker packs doesn't look out of place). fix: set network status correctly at load feat: stickers gas estimate async feat: When network re-connected, any http images that were not properly loaded in an ImageLoader component will automatically be reloaded. fix: Sticker button loading icon chore: Bump nimqml and dotherside NOTE: This PR uses an updated nimqml and dotherside. The respective changes should be merged first, and the commit hash should be bumped in this PR prior to merging. Relevant PRs: [https://github.com/status-im/dotherside/pull/20](https://github.com/status-im/dotherside/pull/20) [https://github.com/status-im/nimqml/pull/17](https://github.com/status-im/nimqml/pull/17)
2020-12-14 05:50:47 +00:00
let netAccMgr = newQNetworkAccessManager(singletonInstance.engine.getNetworkAccessManager())
feat: load installed stickers while offline When the network connection is changed, the sticker packs are cleared and then re-loaded (either loading the offline (installed) sticker packs, or all the sticker packs from the network). Stickers can be sent while offline, though the sticker images do not load once offline (this is likely a side effect of the bug described below). There is a known bug in QNetworkAccessManager (https://bugreports.qt.io/browse/QTBUG-55180) that was re-introduced in 5.14.1 that does not allow us to download resources if we go offline then come back online. The workaround employed in this PR manually sets the NetworkAccessible property of QNetworkAccessManager once we have been connected back online. The NetworkAccessible property is marked as obsolete and will be removed in Qt6, so it is something that we need to be aware of when we upgrade. However the hope is that the bug has been fixed. Close StickersPopup when disconnected from network (so that re-loading of sticker packs doesn't look out of place). fix: set network status correctly at load feat: stickers gas estimate async feat: When network re-connected, any http images that were not properly loaded in an ImageLoader component will automatically be reloaded. fix: Sticker button loading icon chore: Bump nimqml and dotherside NOTE: This PR uses an updated nimqml and dotherside. The respective changes should be merged first, and the commit hash should be bumped in this PR prior to merging. Relevant PRs: [https://github.com/status-im/dotherside/pull/20](https://github.com/status-im/dotherside/pull/20) [https://github.com/status-im/nimqml/pull/17](https://github.com/status-im/nimqml/pull/17)
2020-12-14 05:50:47 +00:00
status.events.on("network:connected") do(e: Args):
# This is a workaround for Qt bug https://bugreports.qt.io/browse/QTBUG-55180
# that was apparently reintroduced in 5.14.1 Unfortunately, the only workaround
# that could be found uses obsolete properties and methods
# (https://doc.qt.io/qt-5/qnetworkaccessmanager-obsolete.html), so this will
# need to be something we keep in mind when upgrading to Qt 6.
# The workaround is to manually set the NetworkAccessible property of the
# QNetworkAccessManager once peers have dropped (network connection is lost).
netAccMgr.clearConnectionCache()
netAccMgr.setNetworkAccessible(NetworkAccessibility.Accessible)
2020-05-18 18:48:20 +00:00
# We need this global variable in order to be able to access the application
2021-09-11 21:34:27 +00:00
# from the non-closure callback passed to `statusgo_backend.setSignalEventCallback`
signalsQObjPointer = cast[pointer](appService.signalController.vptr)
defer:
signalsQObjPointer = nil
2020-05-18 18:48:20 +00:00
when compiles(defaultChroniclesStream.output.writer):
defaultChroniclesStream.output.writer =
proc (logLevel: LogLevel, msg: LogOutputStr) {.gcsafe, raises: [Defect].} =
try:
if signalsQObjPointer != nil:
signal_handler(signalsQObjPointer, ($(%* {"type": "chronicles-log", "event": msg})).cstring, "receiveSignal")
except:
logLoggingFailure(cstring(msg), getCurrentException())
2021-09-24 12:03:57 +00:00
let logFile = fmt"app_{getTime().toUnix}.log"
discard defaultChroniclesStream.outputs[1].open(LOGDIR & logFile, fmAppend)
var wallet = wallet.newController(status, appService)
defer: wallet.delete()
singletonInstance.engine.setRootContextProperty("walletModel", wallet.variant)
2020-05-13 19:14:35 +00:00
var wallet2 = walletV2.newController(status, appService)
2021-08-13 20:04:04 +00:00
defer: wallet2.delete()
singletonInstance.engine.setRootContextProperty("walletV2Model", wallet2.variant)
2021-08-13 20:04:04 +00:00
var chat = chat.newController(status, appService, OPENURI)
defer: chat.delete()
singletonInstance.engine.setRootContextProperty("chatsModel", chat.variant)
var node = node.newController(appService, netAccMgr)
defer: node.delete()
singletonInstance.engine.setRootContextProperty("nodeModel", node.variant)
2020-05-20 17:11:30 +00:00
var utilsController = utilsView.newController(status, appService)
defer: utilsController.delete()
singletonInstance.engine.setRootContextProperty("utilsModel", utilsController.variant)
2021-09-24 12:03:57 +00:00
var keycard = keycard.newController(status)
defer: keycard.delete()
status.events.once("loginCompleted") do(a: Args):
var args = AccountArgs(a)
# At the end of refactoring all this will be in the AppController class.
status.startMessenger()
2020-06-25 13:26:58 +00:00
wallet.init()
2021-08-13 20:04:04 +00:00
wallet2.init()
2020-06-25 13:26:58 +00:00
chat.init()
utilsController.init()
2021-07-12 12:10:12 +00:00
node.init()
2021-07-05 12:34:56 +00:00
wallet.onLogin()
2020-09-11 17:23:57 +00:00
2021-08-12 11:26:08 +00:00
# this should be the last defer in the scope
defer:
info "Status app is shutting down..."
singletonInstance.delete()
2021-08-12 11:26:08 +00:00
singletonInstance.engine.setRootContextProperty("keycardModel", keycard.variant)
singletonInstance.engine.setRootContextProperty("singleInstance", newQVariant(singleInstance))
2020-05-21 20:52:00 +00:00
let isExperimental = if getEnv("EXPERIMENTAL") == "1": "1" else: "0" # value explicity passed to avoid trusting input
let experimentalFlag = newQVariant(isExperimental)
singletonInstance.engine.setRootContextProperty("isExperimental", experimentalFlag)
2021-09-24 12:03:57 +00:00
# Initialize only controllers whose init functions
# do not need a running node
proc initControllers() =
2021-09-24 12:03:57 +00:00
keycard.init()
build: implement packaging steps for the Windows build Implement a `pkg-windows` target that ultimately results in `Status.zip` being written to `pkg/`. Note: this commit does not introduce code signing for the Windows build since that piece is still a work in progress. `pkg-windows` creates a portable folder in `tmp/windows/dist` with the help of [`windeployqt`][windeployqt], which copies the needed portions of Qt into the folder. Since DLL resolution is relatively inflexible, a launcher `Status.exe` is created at the top-level of the folder; the launcher opens `bin/Status.exe` while adding the portable folder's `bin/` to the `PATH`, allowing `bin/Status.exe` to resolve the DLLs in that folder. A few additional tools need to be installed (e.g. with [scoop][scoop]) and availble in `PATH`: * 7-zip * dos2unix (provides unix2dos) * findutils * go * rcedit * wget The above list builds on the tools list in PR #521, and the other requirements and instructions in that PR's description still apply. **Why not build an installer?** When starting work on packaging for the Windows build, my initial plan was to build an installer, and for that purpose I researched the [WiX Toolset][wix], the [Qt Installer Framework][qtif], and some other options. I found that building an installer is a bit complex. I then recalled, from personal experience, that [Cmder][cmder]'s [Mini download][mini] is installer-less. You simply unzip the download and place the `cmder_mini` folder wherever you prefer. Such an approach was also recommended to me in one of the Nim language's community chats. In addition to being simpler, the installer-less approach also gives installation of Status Desktop a lower profile than an installer-application would since nothing is written to the Windows registry, added to the *Add or remove programs* list, etc. I think that's a benefit given the privacy-security focus of Status, but others may feel differently so please provide feedback on this point! [windeployqt]: https://doc.qt.io/qt-5/windows-deployment.html [scoop]: https://scoop.sh/ [wix]: https://wixtoolset.org/ [qtif]: https://doc.qt.io/qtinstallerframework/index.html [cmder]: https://cmder.net/ [mini]: https://github.com/cmderdev/cmder/releases/download/v1.3.15/cmder_mini.zip
2020-07-15 22:45:56 +00:00
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
# TODO: implement all controller resets
# chat.reset()
# node.reset()
# wallet.reset()
2021-08-13 20:04:04 +00:00
# wallet2.reset()
# profile.reset()
build: implement packaging steps for the Windows build Implement a `pkg-windows` target that ultimately results in `Status.zip` being written to `pkg/`. Note: this commit does not introduce code signing for the Windows build since that piece is still a work in progress. `pkg-windows` creates a portable folder in `tmp/windows/dist` with the help of [`windeployqt`][windeployqt], which copies the needed portions of Qt into the folder. Since DLL resolution is relatively inflexible, a launcher `Status.exe` is created at the top-level of the folder; the launcher opens `bin/Status.exe` while adding the portable folder's `bin/` to the `PATH`, allowing `bin/Status.exe` to resolve the DLLs in that folder. A few additional tools need to be installed (e.g. with [scoop][scoop]) and availble in `PATH`: * 7-zip * dos2unix (provides unix2dos) * findutils * go * rcedit * wget The above list builds on the tools list in PR #521, and the other requirements and instructions in that PR's description still apply. **Why not build an installer?** When starting work on packaging for the Windows build, my initial plan was to build an installer, and for that purpose I researched the [WiX Toolset][wix], the [Qt Installer Framework][qtif], and some other options. I found that building an installer is a bit complex. I then recalled, from personal experience, that [Cmder][cmder]'s [Mini download][mini] is installer-less. You simply unzip the download and place the `cmder_mini` folder wherever you prefer. Such an approach was also recommended to me in one of the Nim language's community chats. In addition to being simpler, the installer-less approach also gives installation of Status Desktop a lower profile than an installer-application would since nothing is written to the Windows registry, added to the *Add or remove programs* list, etc. I think that's a benefit given the privacy-security focus of Status, but others may feel differently so please provide feedback on this point! [windeployqt]: https://doc.qt.io/qt-5/windows-deployment.html [scoop]: https://scoop.sh/ [wix]: https://wixtoolset.org/ [qtif]: https://doc.qt.io/qtinstallerframework/index.html [cmder]: https://cmder.net/ [mini]: https://github.com/cmderdev/cmder/releases/download/v1.3.15/cmder_mini.zip
2020-07-15 22:45:56 +00:00
# 2. Re-init controllers that don't require a running node
initControllers()
singletonInstance.engine.setRootContextProperty("signals", appService.signalController.variant)
singletonInstance.engine.setRootContextProperty("mailserver", mailserverController.variant)
2020-05-18 15:07:30 +00:00
var prValue = newQVariant(if defined(production): true else: false)
singletonInstance.engine.setRootContextProperty("production", prValue)
# # We're applying default language before we load qml. Also we're aware that
# # switch language at runtime will have some impact to cpu usage.
# # https://doc.qt.io/archives/qtjambi-4.5.2_01/com/trolltech/qt/qtjambi-linguist-programmers.html
# changeLanguage("en")
appController.start()
2020-05-18 18:48:20 +00:00
# Please note that this must use the `cdecl` calling convention because
2021-09-11 21:34:27 +00:00
# it will be passed as a regular C function to statusgo_backend. This means that
2020-05-18 18:48:20 +00:00
# we cannot capture any local variables here (we must rely on globals)
var callback: SignalCallback = proc(p0: cstring) {.cdecl.} =
2021-08-06 10:08:24 +00:00
if signalsQObjPointer != nil:
signal_handler(signalsQObjPointer, p0, "receiveSignal")
status_go.setSignalEventCallback(callback)
2020-05-10 23:24:06 +00:00
# Qt main event loop is entered here
# The termination of the loop will be performed when exit() or quit() is called
2020-05-21 19:07:55 +00:00
info "Starting application..."
2020-05-06 17:40:00 +00:00
app.exec()
when isMainModule:
mainProc()