Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c882e39fd | ||
|
|
faa42f5a40 | ||
|
|
d0654f3bf9 | ||
|
|
1c57a367ee | ||
|
|
3f3e2b252a | ||
|
|
8e1f7156d7 |
@@ -31,7 +31,7 @@ reagent.dom/dom-node
|
||||
reagent.dom/force-update-all
|
||||
status-im.multiaccounts.create.core/get-new-key-code
|
||||
status-im.ethereum.decode/string
|
||||
status-im.ui.screens.network.views/mainnet?
|
||||
status-im.network.ui.views/mainnet?
|
||||
status-im.data-store.chats/event->string
|
||||
status-im.mailserver.constants/seven-days
|
||||
status-im.mailserver.constants/connection-timeout
|
||||
@@ -65,7 +65,7 @@ mocks.js-dependencies/emoji-picker
|
||||
mocks.js-dependencies/i18n
|
||||
mocks.js-dependencies/qr-code
|
||||
mocks.js-dependencies/svg
|
||||
mocks.js-dependencies/icons
|
||||
mocks.js-dependencies/vector-icons
|
||||
mocks.js-dependencies/webview
|
||||
mocks.js-dependencies/desktop-linking
|
||||
mocks.js-dependencies/desktop-shortcuts
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{:lint-as {status-im.utils.views/defview clojure.core/defn
|
||||
status-im.utils.views/letsubs clojure.core/let
|
||||
reagent.core/with-let clojkure.core/let
|
||||
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
|
||||
quo.react/with-deps-check clojure.core/fn
|
||||
quo.previews.preview/list-comp clojure.core/for
|
||||
|
||||
@@ -13,7 +13,7 @@ update_configs:
|
||||
update_type: "security"
|
||||
# Keep /mobile/js_files/yarn.lock up to date, batching pull requests weekly
|
||||
- package_manager: "javascript"
|
||||
directory: "/"
|
||||
directory: "/mobile/js_files"
|
||||
update_schedule: "weekly"
|
||||
allowed_updates:
|
||||
- match:
|
||||
|
||||
@@ -7,6 +7,7 @@ ETHEREUM_DEV_CLUSTER=1
|
||||
EXTENSIONS=0
|
||||
FLEET=eth.prod
|
||||
GROUP_CHATS_ENABLED=1
|
||||
HARDWALLET_ENABLED=1
|
||||
LOG_LEVEL=info
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||
PFS_ENCRYPTION_ENABLED=1
|
||||
@@ -17,18 +18,8 @@ SNOOPY=0
|
||||
RPC_NETWORKS_ONLY=0
|
||||
PARTITIONED_TOPIC=0
|
||||
CONTRACT_NODES=1
|
||||
MOBILE_UI_FOR_DESKTOP=1
|
||||
STATUS_GO_PROTOCOL=0
|
||||
STATUS_GO_ENABLE_NIMBUS=0
|
||||
KEYCARD_TEST_MENU=0
|
||||
QR_READ_TEST_MENU=1
|
||||
ENABLE_ROOT_ALERT=1
|
||||
ENABLE_REFERRAL_INVITE=1
|
||||
ENABLE_QUO_PREVIEW=1
|
||||
MAX_IMAGES_BATCH=5
|
||||
APN_TOPIC=im.status.ethereum.pr
|
||||
COMMUNITIES_ENABLED=1
|
||||
DATABASE_MANAGEMENT_ENABLED=1
|
||||
METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
COLLECTIBLES_ENABLED=1
|
||||
COMMANDS_ENABLED=1
|
||||
|
||||
@@ -3,8 +3,9 @@ DEFAULT_NETWORK=testnet_rpc
|
||||
ERC20_CONTRACT_WARNINGS=1
|
||||
ETHEREUM_DEV_CLUSTER=1
|
||||
EXTENSIONS=0
|
||||
FLEET=eth.staging
|
||||
FLEET=eth.prod
|
||||
GROUP_CHATS_ENABLED=1
|
||||
HARDWALLET_ENABLED=1
|
||||
LOG_LEVEL=info
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=0
|
||||
PAIRING_POPUP_DISABLED=1
|
||||
@@ -16,20 +17,9 @@ SNOOPY=0
|
||||
STICKERS_ENABLED=1
|
||||
PARTITIONED_TOPIC=0
|
||||
CONTRACT_NODES=1
|
||||
MOBILE_UI_FOR_DESKTOP=1
|
||||
BLANK_PREVIEW=0
|
||||
TOOLTIP_EVENTS=1
|
||||
COMMANDS_ENABLED=1
|
||||
KEYCARD_TEST_MENU=1
|
||||
QR_READ_TEST_MENU=1
|
||||
ENABLE_ROOT_ALERT=0
|
||||
ENABLE_REFERRAL_INVITE=1
|
||||
MAX_IMAGES_BATCH=5
|
||||
APN_TOPIC=im.status.ethereum.pr
|
||||
VERIFY_TRANSACTION_CHAIN_ID=3
|
||||
VERIFY_ENS_CHAIN_ID=3
|
||||
TEST_STATEOFUS=1
|
||||
DATABASE_MANAGEMENT_ENABLED=1
|
||||
COMMUNITIES_ENABLED=1
|
||||
COMMUNITIES_MANAGEMENT_ENABLED=1
|
||||
METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
QR_READ_TEST_MENU=1
|
||||
@@ -1,11 +1,12 @@
|
||||
CACHED_WEBVIEWS_ENABLED=1
|
||||
DEBUG_WEBVIEW=1
|
||||
DEFAULT_NETWORK=testnet_rpc
|
||||
DEFAULT_NETWORK=mainnet_rpc
|
||||
ERC20_CONTRACT_WARNINGS=0
|
||||
ETHEREUM_DEV_CLUSTER=1
|
||||
EXTENSIONS=0
|
||||
FLEET=eth.prod
|
||||
GROUP_CHATS_ENABLED=1
|
||||
HARDWALLET_ENABLED=1
|
||||
LOG_LEVEL=info
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||
MAINNET_WARNING_ENABLED=1
|
||||
@@ -17,21 +18,6 @@ SNOOPY=0
|
||||
RPC_NETWORKS_ONLY=0
|
||||
PARTITIONED_TOPIC=0
|
||||
CONTRACT_NODES=1
|
||||
MOBILE_UI_FOR_DESKTOP=1
|
||||
STATUS_GO_ENABLE_NIMBUS=0
|
||||
COMMANDS_ENABLED=1
|
||||
KEYCARD_TEST_MENU=0
|
||||
ENABLE_ROOT_ALERT=1
|
||||
ENABLE_REFERRAL_INVITE=1
|
||||
DISABLE_WALLET_ON_MOBILE_NETWORK=1
|
||||
APN_TOPIC=im.status.ethereum.pr
|
||||
VERIFY_TRANSACTION_CHAIN_ID=3
|
||||
VERIFY_ENS_CHAIN_ID=3
|
||||
TEST_STATEOFUS=1
|
||||
BLANK_PREVIEW=0
|
||||
MAX_IMAGES_BATCH=5
|
||||
GOOGLE_FREE=0
|
||||
DATABASE_MANAGEMENT_ENABLED=1
|
||||
COMMUNITIES_ENABLED=1
|
||||
COMMUNITIES_MANAGEMENT_ENABLED=1
|
||||
METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
|
||||
@@ -16,11 +16,5 @@ SNOOPY=0
|
||||
RPC_NETWORKS_ONLY=0
|
||||
PARTITIONED_TOPIC=0
|
||||
CONTRACT_NODES=1
|
||||
ENABLE_ROOT_ALERT=1
|
||||
ENABLE_REFERRAL_INVITE=0
|
||||
MAX_IMAGES_BATCH=5
|
||||
BLANK_PREVIEW=0
|
||||
COMMUNITIES_ENABLED=1
|
||||
DATABASE_MANAGEMENT_ENABLED=1
|
||||
METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
MOBILE_UI_FOR_DESKTOP=1
|
||||
HARDWALLET_ENABLED=1
|
||||
|
||||
@@ -15,9 +15,5 @@ POW_TIME=1
|
||||
SNOOPY=0
|
||||
RPC_NETWORKS_ONLY=1
|
||||
PARTITIONED_TOPIC=0
|
||||
ENABLE_ROOT_ALERT=1
|
||||
MAX_IMAGES_BATCH=1
|
||||
ENABLE_REFERRAL_INVITE=0
|
||||
METRICS_ENABLED=0
|
||||
DELETE_MESSAGE_ENABLED=1
|
||||
COLLECTIBLES_ENABLED=1
|
||||
MOBILE_UI_FOR_DESKTOP=1
|
||||
HARDWALLET_ENABLED=1
|
||||
|
||||
@@ -94,4 +94,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)? *\\(site=[a-z,_]*
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
|
||||
[version]
|
||||
^0.122.0
|
||||
^0.105.0
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
# the repo. Unless a later match takes precedence,
|
||||
# @global-owner1 and @global-owner2 will be requested for
|
||||
# review when someone opens a pull request.
|
||||
* @status-im/status-core
|
||||
|
||||
/ci @jakubgs
|
||||
/fastlane @jakubgs
|
||||
/scripts @jakubgs
|
||||
@@ -22,4 +24,12 @@
|
||||
|
||||
/components @status-im/status-core-ui
|
||||
|
||||
/test/appium/ @churik
|
||||
desktop/ @vkjr
|
||||
modules/react-native-desktop*/ @vkjr
|
||||
modules/react-native-desktop*/ @vkjr
|
||||
|
||||
/doc @oskarth @yenda @jeluard
|
||||
|
||||
/deployment @vkjr
|
||||
|
||||
/test/appium/ @antdanchenko @churik
|
||||
|
||||
@@ -8,9 +8,10 @@ These are just guidelines, not rules. Use your best judgment, and feel free to p
|
||||
|
||||
#### What should I know before I get started?
|
||||
|
||||
* [Mission and Principles](https://status.im/about)
|
||||
* [Mission and Core Values](https://status.im/contribute)
|
||||
* [Principles](https://status.im/contribute/our_principles.html)
|
||||
* [Read our FAQ](https://status.im/docs/FAQs.html)
|
||||
* [Join our Chat](http://join.status.im/chat/public/status-core-dev)
|
||||
* [Developer Introduction](https://status.im/developer_tools/)
|
||||
* [Build Status Yourself](https://status.im/technical/build_status)
|
||||
* [Build Status Yourself](https://status.im/build_status)
|
||||
* [Find issues to work on](https://github.com/status-im/)
|
||||
|
||||
@@ -9,27 +9,46 @@ assignees: ''
|
||||
|
||||
# Bug Report
|
||||
|
||||
## Problem
|
||||
|
||||
## Problem
|
||||
[comment]: # (A problem description)
|
||||
|
||||
An overview of the background required to understand the problem.
|
||||
A problem description.
|
||||
|
||||
#### Expected behavior
|
||||
|
||||
[comment]: # (Describe what you expected to happen. Please include designs if possible.)
|
||||
|
||||
#### Actual behavior
|
||||
|
||||
[comment]: # (Describe what actually happened. Please include screenshots if possible.)
|
||||
|
||||
#### Notes
|
||||
|
||||
For the developer who will be investigating. Is it related to another PR? Tips on where to start?
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
Rules for the future PR to be accepted.
|
||||
|
||||
### Reproduction
|
||||
|
||||
1) Open Status
|
||||
2)
|
||||
[comment]: # (Describe how we can replicate the bug step by step.)
|
||||
|
||||
- Open Status
|
||||
- ...
|
||||
- Step 3, etc.
|
||||
|
||||
### Additional Information
|
||||
|
||||
- Status version: nightly
|
||||
- Operating System: Android, iOS
|
||||
[comment]: # (Please do your best to fill this out.)
|
||||
- Status version: ...
|
||||
[comment]: # (Android or iOS.)
|
||||
- Operating System: <Android|iOS>
|
||||
|
||||
#### Logs
|
||||
|
||||
[comment]: # (Please, add logs/notes if necessary)
|
||||
[comment]: # (if on Android please replicate bug whilst running adb logcat)
|
||||
|
||||
```
|
||||
...
|
||||
```
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
---
|
||||
name: Release umbrella issue
|
||||
about: Release Issue
|
||||
title: 'Mobile release '
|
||||
labels: release
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
Issue to manage mobile release <version>
|
||||
|
||||
### Scope
|
||||
[comment]: # (Add milestone from github)
|
||||
https://github.com/status-im/status-react/milestone/
|
||||
|
||||
- release notes:
|
||||
- release branch:
|
||||
|
||||
|
||||
### Testing info
|
||||
[comment]: # (TestRail info, added by QA)
|
||||
Main test suite:
|
||||
Upgrade (e2e):
|
||||
|
||||
### Builds in TestFlight and PlayStore to push as a release
|
||||
[comment]: # (Will be added by QA after testing approving of build)
|
||||
|
||||
### Process
|
||||
#### 1) Kick-off
|
||||
- [ ] 1. Translation PRs is merged before cutting branch (Jinho)
|
||||
- [ ] 2. Prepare scope of visible changes based on commits history, started from previous release branch cut ([example]( https://notes.status.im/1.14-release-notes?view))
|
||||
- [ ] 3. Update [RELEASES.md](https://github.com/status-im/status-react/blob/develop/RELEASES.md) with release notes (make PR based on previous step)
|
||||
- [ ] 4. Create release branch using this [guide](https://github.com/status-im/status-react/blob/develop/doc/RELEASE_GUIDE.md), bump VERSION (merge created PR ([example](https://github.com/status-im/status-react/pull/12504) ) to develop) and get successful release builds (so, testing can be started)
|
||||
- [ ] 5. Based on release scope, ask for comms (Jonny)
|
||||
- [ ] 6. Make sure that assets (screenshots, video) in stores are up to date. If should be updated, ask @cammellos for help
|
||||
|
||||
#### 2) Testing
|
||||
[comment]: # (Section will be maintained by QA)
|
||||
- [ ] Dogfooding (add notes, if it was held)
|
||||
- [ ] Regression testing for release candidate build
|
||||
- [ ] Upgrade tests
|
||||
- [ ] Fix known blocker(s) found during regression testing
|
||||
|
||||
##### Blockers
|
||||
[comment]: # (Section for blocker issues; should be fixed and merged by release-manager. Remove if no blockers found)
|
||||
- [ ] 1 blocker:
|
||||
|
||||
=============================================================================================
|
||||
|
||||
- [ ] Cherry-pick fix(es) to the release branch
|
||||
- [ ] Verify fix(es) on new release candidate build
|
||||
- [ ] Retest
|
||||
- [ ] Keep release build forever (button in Jenkins)
|
||||
|
||||
#### 3) Submission
|
||||
|
||||
- [ ] 1. Release notes written and added (500 character limit for updates (Android) and PR for [RELEASES.md](https://github.com/status-im/status-react/blob/develop/RELEASES.md) is ready to be merged (from 1.3 step)
|
||||
- [ ] 2. Submit beta version for Android (Open Testing in Play Store)
|
||||
- [ ] 3. Submit iOS build to Apple review ([instruction](https://drive.google.com/file/d/10Cl7PBB7TFPkZiVbfzdFGpfMRP9bxXuq/view?usp=sharing), be careful - low quality of audio)
|
||||
- [ ] 4. Play store content reviewed and updated
|
||||
- [ ] 5. Privacy policy reviewed and updated (ask in channel)
|
||||
- [ ] 6. Countries to be excluded (ask in channel)
|
||||
- [ ] 7. Changes to our FAQ made (should be checked and if any changes needed, ask Jakub to made them)
|
||||
- [ ] 8. Prepare PR for F-droid build ([instruction]( https://github.com/status-im/status-react/blob/develop/doc/FDROID.md))
|
||||
|
||||
#### 4) Before publishing
|
||||
- [ ] 1. Translations for comms available (marketing, ask in the channel)
|
||||
- [ ] 2. Promotional content ready (marketing, ask in channel)
|
||||
- [ ] 3. Upload builds for DO store, https://dev.status.im/ (Jakub)
|
||||
|
||||
#### 5) At time of publishing
|
||||
- [ ] 1. Notify marketing to push comms and blog post (Jonny + get review on blog from QA team)
|
||||
- [ ] 2. Publish release to app store and playstore
|
||||
- [ ] 3. Final push to update prod site https://status.im/, [instructions](https://github.com/status-im/infra-docs/blob/master/articles/status_release_upload.md) (Jakub - requires credentials to upload)
|
||||
- [ ] 4. Add the link to the post about the release and publish the release: https://github.com/status-im/status-react/releases (Jakub)
|
||||
- [ ] 5. Merge PR for updating [RELEASES.md](https://github.com/status-im/status-react/blob/develop/RELEASES.md) (from 1.3 step)
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
name: Zenhub integration assigned
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- assigned
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: status-im/zenhub-automations@master
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ZENHUB_API_KEY: ${{ secrets.ZENHUB_TOKEN }}
|
||||
INPROG_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyODI1Mg
|
||||
NEXT_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyNzk2MQ
|
||||
REVIEW_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzIyNjk0MTA
|
||||
@@ -1,15 +0,0 @@
|
||||
name: Zenhub integration branch
|
||||
on:
|
||||
create:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: status-im/zenhub-automations@master
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ZENHUB_API_KEY: ${{ secrets.ZENHUB_TOKEN }}
|
||||
INPROG_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyODI1Mg
|
||||
NEXT_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyNzk2MQ
|
||||
REVIEW_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzIyNjk0MTA
|
||||
@@ -1,17 +0,0 @@
|
||||
name: Zenhub integration milestoned
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- milestoned
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: status-im/zenhub-automations@master
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ZENHUB_API_KEY: ${{ secrets.ZENHUB_TOKEN }}
|
||||
INPROG_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyODI1Mg
|
||||
NEXT_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyNzk2MQ
|
||||
REVIEW_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzIyNjk0MTA
|
||||
@@ -1,20 +0,0 @@
|
||||
name: Zenhub integration PR
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
types:
|
||||
- ready_for_review
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: status-im/zenhub-automations@master
|
||||
if: github.event.pull_request.draft == false
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ZENHUB_API_KEY: ${{ secrets.ZENHUB_TOKEN }}
|
||||
INPROG_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyODI1Mg
|
||||
NEXT_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzMyNzk2MQ
|
||||
REVIEW_COLUMN: Z2lkOi8vcmFwdG9yL1BpcGVsaW5lLzIyNjk0MTA
|
||||
@@ -25,6 +25,7 @@ DerivedData
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
project.xcworkspace
|
||||
xcshareddata
|
||||
|
||||
# Android/IJ
|
||||
#
|
||||
@@ -67,6 +68,9 @@ env/dev/env/config.cljs
|
||||
externs/
|
||||
shim.js
|
||||
|
||||
# Desktop build
|
||||
index.desktop.js
|
||||
|
||||
# Generated by lein voom
|
||||
#
|
||||
/pom.xml
|
||||
@@ -100,7 +104,6 @@ Statusgo.framework
|
||||
/ios/Pods/
|
||||
/ios/StatusIm.xcworkspace
|
||||
/ios/react-native-xcode.log
|
||||
/ios/set_xcode_version.log
|
||||
.ruby-version
|
||||
status-e2e/
|
||||
|
||||
@@ -125,8 +128,12 @@ fastlane/README.md
|
||||
# emacs
|
||||
.dir-locals.el
|
||||
|
||||
# We don't use NPM
|
||||
#ignore platform-specific files in the root since they are only symlinks to files in folders 'desktop/js_files' and 'mobile/js_files'
|
||||
/DEPENDENCIES.md
|
||||
/package-lock.json
|
||||
/package.json
|
||||
/metro.config.js
|
||||
/yarn.lock
|
||||
/.re-natal
|
||||
/re-natal
|
||||
|
||||
@@ -134,6 +141,27 @@ fastlane/README.md
|
||||
pkg
|
||||
/BUILD_NUMBER
|
||||
|
||||
# Status Desktop
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
**/CMakeFiles/
|
||||
/StatusImPackage/*
|
||||
*.AppImage
|
||||
Status-Windows-x86_64.exe
|
||||
/desktop/bin/*
|
||||
/desktop/lib/*
|
||||
/desktop/modules/*
|
||||
/desktop/Makefile
|
||||
/desktop/graph_info.json
|
||||
/desktop/run-app.bat
|
||||
/desktop/run-app.sh
|
||||
/desktop/CMakeFiles/
|
||||
/desktop/reportApp/Makefile
|
||||
/deployment/windows/Status.rc
|
||||
*_autogen/
|
||||
CompleteBundleWin.cmake
|
||||
logger_settings.ini
|
||||
|
||||
# Conan
|
||||
conan*.txt
|
||||
conanbuildinfo.*
|
||||
@@ -165,7 +193,3 @@ trace.edn
|
||||
|
||||
/app/
|
||||
project.clj
|
||||
|
||||
##appium
|
||||
test/appium/report/
|
||||
result.xml
|
||||
@@ -1,4 +1,4 @@
|
||||
.PHONY: nix-add-gcroots clean nix-clean run-metro test release _list _fix-node-perms _tmpdir-mk _tmpdir-rm
|
||||
.PHONY: nix-add-gcroots clean nix-clean run-metro react-native-desktop test release _list _fix-node-perms _tmpdir-mk _tmpdir-rm
|
||||
|
||||
help: SHELL := /bin/sh
|
||||
help: ##@other Show this help
|
||||
@@ -42,7 +42,7 @@ export NIX_CONF_DIR = $(PWD)/nix
|
||||
# Location of symlinks to derivations that should not be garbage collected
|
||||
export _NIX_GCROOTS = /nix/var/nix/gcroots/per-user/$(USER)/status-react
|
||||
# Defines which variables will be kept for Nix pure shell, use semicolon as divider
|
||||
export _NIX_KEEP ?= TMPDIR,BUILD_ENV,STATUS_GO_SRC_OVERRIDE
|
||||
export _NIX_KEEP ?= TMPDIR,BUILD_ENV,STATUS_GO_SRC_OVERRIDE,NIMBUS_SRC_OVERRIDE
|
||||
|
||||
# Useful for Andoird release builds
|
||||
TMP_BUILD_NUMBER := $(shell ./scripts/version/gen_build_no.sh | cut -c1-10)
|
||||
@@ -57,10 +57,13 @@ endif
|
||||
# Nix targets
|
||||
#----------------
|
||||
|
||||
# WARNING: This has to be located right before all the targets.
|
||||
# WARNING: This has to be located right before the targets
|
||||
ifdef IN_NIX_SHELL
|
||||
SHELL := env bash
|
||||
else
|
||||
SHELL := ./nix/scripts/shell.sh
|
||||
endif
|
||||
|
||||
shell: export TARGET ?= default
|
||||
shell: ##@prepare Enter into a pre-configured shell
|
||||
ifndef IN_NIX_SHELL
|
||||
@ENTER_NIX_SHELL
|
||||
@@ -124,17 +127,10 @@ _tmpdir-rm: SHELL := /bin/sh
|
||||
_tmpdir-rm: ##@prepare Remove TMPDIR
|
||||
rm -fr "$(TMPDIR)"
|
||||
|
||||
# Remove directories and ignored files
|
||||
clean: SHELL := /bin/sh
|
||||
clean: _fix-node-perms _tmpdir-rm ##@prepare Remove all output folders
|
||||
git clean -dXf
|
||||
|
||||
# Remove directories, ignored and non-ignored files
|
||||
purge: SHELL := /bin/sh
|
||||
purge: _fix-node-perms _tmpdir-rm ##@prepare Remove all output folders
|
||||
git clean -dxf
|
||||
|
||||
|
||||
watchman-clean: export TARGET := watchman
|
||||
watchman-clean: ##@prepare Delete repo directory from watchman
|
||||
watchman watch-del $${STATUS_REACT_HOME}
|
||||
@@ -153,64 +149,40 @@ keystore: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
|
||||
keystore: ##@prepare Generate a Keystore for signing Android APKs
|
||||
@./scripts/generate-keystore.sh
|
||||
|
||||
fdroid-max-watches: SHELL := /bin/sh
|
||||
fdroid-max-watches: ##@prepare Bump max_user_watches to avoid ENOSPC errors
|
||||
sysctl fs.inotify.max_user_watches=524288
|
||||
|
||||
fdroid-nix-dir: SHELL := /bin/sh
|
||||
fdroid-nix-dir: ##@prepare Create /nix directory for F-Droid Vagrant builders
|
||||
mkdir -m 0755 /nix
|
||||
chown vagrant /nix
|
||||
|
||||
fdroid-fix-tmp: SHELL := /bin/sh
|
||||
fdroid-fix-tmp: ##@prepare Fix TMPDIR permissions so Vagrant user is the owner
|
||||
chown -R vagrant "$(TMPDIR)"
|
||||
|
||||
fdroid-build-env: fdroid-max-watches fdroid-nix-dir fdroid-fix-tmp ##@prepare Setup build environment for F-Droud build
|
||||
|
||||
fdroid-pr: export TARGET := android
|
||||
fdroid-pr: ##@prepare Create F-Droid release PR
|
||||
ifndef APK
|
||||
$(error APK env var not defined)
|
||||
endif
|
||||
scripts/fdroid-pr.sh "$(APK)"
|
||||
|
||||
xcode-clean: SHELL := /bin/sh
|
||||
xcode-clean: XCODE_HOME := $(HOME)/Library/Developer/Xcode
|
||||
xcode-clean: ##@prepare Clean XCode derived data and archives
|
||||
rm -fr $(XCODE_HOME)/DerivedData/StatusIm-* $(XCODE_HOME)/Archives/*/StatusIm*
|
||||
|
||||
#----------------
|
||||
# Release builds
|
||||
#----------------
|
||||
release: release-android release-ios ##@build Build release for Android and iOS
|
||||
release: release-android release-ios ##@build build release for Android and iOS
|
||||
|
||||
release-android: export TARGET := default
|
||||
release-android: export BUILD_ENV ?= prod
|
||||
release-android: export BUILD_TYPE ?= nightly
|
||||
release-android: export BUILD_NUMBER ?= $(TMP_BUILD_NUMBER)
|
||||
release-android: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
|
||||
release-android: export ANDROID_APK_SIGNED ?= true
|
||||
release-android: export ANDROID_ABI_SPLIT ?= false
|
||||
release-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
|
||||
release-android: keystore ##@build Build release for Android
|
||||
scripts/release-android.sh
|
||||
|
||||
release-fdroid: export BUILD_ENV = prod
|
||||
release-fdroid: export BUILD_TYPE = release
|
||||
release-fdroid: export ANDROID_APK_SIGNED = false
|
||||
release-fdroid: export ANDROID_ABI_SPLIT = false
|
||||
release-fdroid: export ANDROID_ABI_INCLUDE = armeabi-v7a;arm64-v8a;x86;x86_64
|
||||
release-fdroid: ##@build Build release for F-Droid
|
||||
sed -i -e '$$aGOOGLE_FREE=1' .env.release
|
||||
release-android: keystore ##@build build release for Android
|
||||
scripts/release-android.sh
|
||||
|
||||
release-ios: export TARGET := ios
|
||||
release-ios: export BUILD_ENV ?= prod
|
||||
release-ios: watchman-clean ##@build Build release for iOS release
|
||||
release-ios: watchman-clean ##@build build release for iOS release
|
||||
@git clean -dxf -f target/ios && \
|
||||
$(MAKE) jsbundle-ios && \
|
||||
xcodebuild -workspace ios/StatusIm.xcworkspace -scheme StatusIm -configuration Release -destination 'generic/platform=iOS' -UseModernBuildSystem=N clean archive
|
||||
|
||||
release-desktop: export TARGET ?= $(HOST_OS)
|
||||
release-desktop: ##@build build release for desktop release based on TARGET
|
||||
@$(MAKE) jsbundle-desktop && \
|
||||
scripts/build-desktop.sh; \
|
||||
$(MAKE) watchman-clean
|
||||
|
||||
release-windows-desktop: export TARGET ?= windows
|
||||
release-windows-desktop: ##@build build release for windows desktop release
|
||||
@$(MAKE) jsbundle-desktop && \
|
||||
scripts/build-desktop.sh; \
|
||||
$(MAKE) watchman-clean
|
||||
|
||||
jsbundle-android: SHELL := /bin/sh
|
||||
jsbundle-android: export TARGET := android
|
||||
jsbundle-android: export BUILD_ENV ?= prod
|
||||
@@ -236,6 +208,10 @@ status-go-ios: SHELL := /bin/sh
|
||||
status-go-ios: ##@status-go Compile status-go for iOS app
|
||||
nix/scripts/build.sh targets.status-go.mobile.ios
|
||||
|
||||
status-go-desktop: SHELL := /bin/sh
|
||||
status-go-desktop: ##@status-go Compile status-go for desktop app
|
||||
nix/scripts/build.sh targets.status-go.desktop
|
||||
|
||||
#--------------
|
||||
# Watch, Build & Review changes
|
||||
#--------------
|
||||
@@ -244,6 +220,10 @@ run-clojure: export TARGET := clojure
|
||||
run-clojure: ##@run Watch for and build Clojure changes for mobile
|
||||
yarn shadow-cljs watch mobile
|
||||
|
||||
run-clojure-desktop: export TARGET ?= $(HOST_OS)
|
||||
run-clojure-desktop: #@run Watch for and build Clojure changes for desktop
|
||||
clj -R:dev build.clj watch --platform desktop
|
||||
|
||||
run-metro: export TARGET := clojure
|
||||
run-metro: ##@run Start Metro to build React Native changes
|
||||
@scripts/start-react-native.sh
|
||||
@@ -266,6 +246,10 @@ else
|
||||
npx react-native run-ios
|
||||
endif
|
||||
|
||||
run-desktop: export TARGET ?= $(HOST_OS)
|
||||
run-desktop: ##@run Run Desktop build
|
||||
npx react-native run-desktop
|
||||
|
||||
#--------------
|
||||
# Tests
|
||||
#--------------
|
||||
@@ -273,12 +257,15 @@ endif
|
||||
lint: export TARGET := clojure
|
||||
lint: ##@test Run code style checks
|
||||
yarn clj-kondo --confg .clj-kondo/config.edn --lint src && \
|
||||
TARGETS=$$(git diff --diff-filter=d --cached --name-only src && echo src) && \
|
||||
clojure -Scp "$$CLASS_PATH" -m cljfmt.main check --indents indentation.edn $$TARGETS
|
||||
clojure -Sdeps '{:deps {cljfmt {:mvn/version "0.6.7"}}}' \
|
||||
-m cljfmt.main check $$(git diff --diff-filter=d --cached --name-only src && echo src) \
|
||||
--indents indentation.edn
|
||||
|
||||
lint-fix: export TARGET := clojure
|
||||
lint-fix: ##@test Run code style checks and fix issues
|
||||
clojure -Scp "$$CLASS_PATH" -m cljfmt.main fix src --indents indentation.edn
|
||||
clojure -Sdeps '{:deps {cljfmt {:mvn/version "0.6.7"}}}' \
|
||||
-m cljfmt.main fix src \
|
||||
--indents indentation.edn
|
||||
|
||||
test: export TARGET := clojure
|
||||
test: ##@test Run tests once in NodeJS
|
||||
@@ -293,6 +280,15 @@ coverage: ##@test Run tests once in NodeJS generating coverage
|
||||
# Other
|
||||
#--------------
|
||||
|
||||
start-desktop-server: export TARGET ?= $(HOST_OS)
|
||||
start-desktop-server: #@other Start ubuntu-server.js for desktop
|
||||
node ubuntu-server.js
|
||||
|
||||
react-native-desktop: export TARGET ?= $(HOST_OS)
|
||||
react-native-desktop: export _NIX_PURE ?= true
|
||||
react-native-desktop: ##@other Start react native packager
|
||||
@scripts/start-react-native.sh
|
||||
|
||||
geth-connect: export TARGET := android-env
|
||||
geth-connect: ##@other Connect to Geth on the device
|
||||
adb forward tcp:8545 tcp:8545 && \
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
# Status - a Mobile Ethereum Operating System
|
||||
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" alt="Get it on Google Play" height="80"/>](https://play.google.com/store/apps/details?id=im.status.ethereum)
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="80"/>](https://f-droid.org/packages/im.status.ethereum/)
|
||||
[<img src="doc/github_badge.png" alt="Get it on Github" height="80"/>](https://github.com/status-im/status-react/releases)
|
||||
# Status - a Mobile Ethereum Operating System
|
||||
|
||||
Join us in creating a browser, messenger, and gateway to a decentralized world. Status is a free (libre) open source mobile client targeting Android & iOS built entirely on [Ethereum](https://ethereum.org/) technologies. That's right, no middle men and `go-ethereum` running directly on your device.
|
||||
|
||||
@@ -27,7 +24,7 @@ Developers are the heart of software and to keep Status beating we need all the
|
||||
Want to learn more about it? Start by reading our [Developer Introduction](https://status.im/developer_tools/) which guides you through the technology stack and start browsing [beginner issues](https://github.com/status-im/status-react/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22good%20first%20issue%22%20). Then you can read how to [Build Status](https://status.im/technical/build_status/), which talks about managing project dependencies, coding guidelines and testing procedures.
|
||||
|
||||
- **Community Management**
|
||||
Metcalfe's law states that the value of a network is proportional to the square of the number of connected users of the system - without community Status is meaningless. We're looking to create a positive, fun environment to explore new ideas, experiment and grow the Status community. Building a community takes a lot of work but the people you'll meet and long lasting relationships you form will be well worth it, check out our [Mission and Community Principles](https://status.im/about)
|
||||
Metcalfe's law states that the value of a network is proportional to the square of the number of connected users of the system - without community Status is meaningless. We're looking to create a positive, fun environment to explore new ideas, experiment and grow the Status community. Building a community takes a lot of work but the people you'll meet and long lasting relationships you form will be well worth it, check out our [Community Principles](https://status.im/contribute/our_principles.html)
|
||||
|
||||
- **Specification / Documentation**
|
||||
John Dewey once said "Education is not preparation for life; education is life *itself* ". Developers & Designers need guidance and it all starts from documentation and specifications. Our software is only as good as its documentation, head over to our [docs](https://status.im/docs) and see how you can improve what we have.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Description
|
||||
|
||||
This document explains some of the steps that are involved in relseases.
|
||||
|
||||
## PlayStore Metadata Updates
|
||||
|
||||
You can update Play Store releae metadata using `fastlane android upload_metadata`.
|
||||
|
||||
But that requires credentials necessary for accessing Play Store API. The simpler way is to edit files contained within [`fastlane/metadata`](metadata) and run the following CI job:
|
||||
|
||||
https://ci.status.im/job/status-tools/job/update-playstore-metadata/
|
||||
@@ -67,6 +67,8 @@ info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this
|
||||
Update yarn.lock file. In order to do this, perform the following steps on a clean `status-react` repo:
|
||||
```
|
||||
cd status-react
|
||||
ln -sf mobile/js_files/package.json .
|
||||
ln -sf mobile/js_files/yarn.lock .
|
||||
yarn install
|
||||
```
|
||||
and don't forget to commit updated `yarn.lock` together with `package.json`.
|
||||
@@ -123,18 +123,6 @@ def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
*/
|
||||
def enableHermes = project.ext.react.get("enableHermes", false);
|
||||
|
||||
/**
|
||||
* Exclude google library so we can publish to external android stores
|
||||
*/
|
||||
def googleFree = project.env.get("GOOGLE_FREE", false)
|
||||
|
||||
def getCommitHash = { ->
|
||||
if (project.hasProperty("commitHash")) {
|
||||
return project.commitHash
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
def getVersionCode = { ->
|
||||
new ByteArrayOutputStream().withStream { stdOut ->
|
||||
if (project.hasProperty("versionCode")) {
|
||||
@@ -191,7 +179,6 @@ android {
|
||||
versionCode getVersionCode()
|
||||
versionName getVersionName()
|
||||
missingDimensionStrategy 'react-native-camera', 'general'
|
||||
manifestPlaceholders = [commitHash: getCommitHash()]
|
||||
/* this needs to be empty if we want APKs split by ABIs */
|
||||
if (!getEnvOrConfig('ANDROID_ABI_SPLIT').toBoolean()) {
|
||||
ndk {
|
||||
@@ -241,8 +228,6 @@ android {
|
||||
keyAlias 'androiddebugkey'
|
||||
keyPassword 'android'
|
||||
}
|
||||
/* Caution! In production, you need to generate your own keystore file.
|
||||
* See: https://facebook.github.io/react-native/docs/signed-apk-android */
|
||||
release {
|
||||
/* environment variables take precedence over gradle.properties file */
|
||||
storeFile file(getEnvOrConfig('KEYSTORE_PATH').replaceAll("~", System.properties['user.home']))
|
||||
@@ -268,11 +253,11 @@ android {
|
||||
resValue "string", "build_config_package", "im.status.ethereum"
|
||||
}
|
||||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
// see https://facebook.github.io/react-native/docs/signed-apk-android.
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
if (getEnvOrConfig('ANDROID_APK_SIGNED').toBoolean()) {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
pr {
|
||||
initWith release
|
||||
@@ -335,14 +320,6 @@ dependencies {
|
||||
implementation jscFlavor
|
||||
}
|
||||
|
||||
if (googleFree) {
|
||||
implementation(project(':react-native-device-info')) {
|
||||
exclude group: 'com.google.firebase'
|
||||
exclude group: 'com.google.android.gms'
|
||||
exclude group: 'com.android.installreferrer'
|
||||
}
|
||||
}
|
||||
|
||||
// react-native-screens
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
|
||||
@@ -356,8 +333,8 @@ dependencies {
|
||||
implementation project(':react-native-status')
|
||||
implementation project(':react-native-status-keycard')
|
||||
implementation 'com.github.status-im:function:0.0.1'
|
||||
implementation 'com.facebook.fresco:fresco:2.2.0'
|
||||
implementation 'com.facebook.fresco:animated-gif:2.2.0'
|
||||
implementation 'com.facebook.fresco:fresco:2.0.0'
|
||||
implementation 'com.facebook.fresco:animated-gif:2.0.0'
|
||||
}
|
||||
|
||||
def getLocalNDKDir = { ->
|
||||
@@ -379,7 +356,7 @@ task hemroidBuild(type: Exec) {
|
||||
def localNdkDir = getLocalNDKDir()
|
||||
def ndkDir = System.env.ANDROID_NDK_ROOT
|
||||
if (localNdkDir != null) {
|
||||
ndkDir = localNdkDir
|
||||
ndkDir = localNdkDir
|
||||
}
|
||||
|
||||
def execPath = "$ndkDir/ndk-build"
|
||||
|
||||
@@ -64,15 +64,3 @@
|
||||
-dontwarn java.nio.file.*
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||
-dontwarn okio.**
|
||||
|
||||
# fast-image
|
||||
|
||||
-keep public class com.dylanvann.fastimage.* {*;}
|
||||
-keep public class com.dylanvann.fastimage.** {*;}
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep public class com.bumptech.glide.annotation.GlideModule
|
||||
-keep public class * extends com.bumptech.glide.module.AppGlideModule
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
@@ -17,12 +17,15 @@
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
|
||||
<!-- these permissions should be removed -->
|
||||
<!-- React Native unnecessary permissions (https://github.com/facebook/react-native/issues/5886) -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
|
||||
|
||||
<application
|
||||
tools:replace="android:allowBackup"
|
||||
@@ -32,8 +35,8 @@
|
||||
android:theme="@style/AppTheme"
|
||||
android:name=".MainApplication"
|
||||
android:largeHeap="true"
|
||||
android:usesCleartextTraffic="true">
|
||||
<meta-data android:name="commitHash" android:value="${commitHash}"/>
|
||||
android:usesCleartextTraffic="true"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
@@ -69,7 +72,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
|
||||
<service android:name="im.status.ethereum.pushnotifications.ForegroundService"></service>
|
||||
<service android:name="im.status.ethereum.module.ForegroundService"></service>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
||||
@@ -23,21 +23,17 @@ import android.provider.Settings;
|
||||
import android.os.Bundle;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
||||
|
||||
import com.facebook.react.ReactFragmentActivity;
|
||||
import com.reactnativenavigation.NavigationActivity;
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
import org.devio.rn.splashscreen.SplashScreen;
|
||||
|
||||
import java.util.Properties;
|
||||
import im.status.ethereum.module.StatusThreadPoolExecutor;
|
||||
import im.status.ethereum.MainApplication;
|
||||
|
||||
public class MainActivity extends NavigationActivity
|
||||
public class MainActivity extends ReactFragmentActivity
|
||||
implements ActivityCompat.OnRequestPermissionsResultCallback{
|
||||
|
||||
|
||||
@@ -101,16 +97,6 @@ public class MainActivity extends NavigationActivity
|
||||
return intent;
|
||||
}
|
||||
|
||||
private void tryToEmit(String eventName, WritableMap event) {
|
||||
try {
|
||||
((MainApplication) getApplication()).getReactNativeHost()
|
||||
.getReactInstanceManager()
|
||||
.getCurrentReactContext()
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit("url", event);
|
||||
} catch(Exception e) {/* we expect NPE on first start, which is OK because we have a fallback */}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(final Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
@@ -181,16 +167,6 @@ public class MainActivity extends NavigationActivity
|
||||
@Override
|
||||
public void run() {
|
||||
System.loadLibrary("status-logs");
|
||||
|
||||
// when app is started but the Activity has been destroyed, the deep linking url event is
|
||||
// not emitted when coming back to foreground. This is a workaround. If the problem is
|
||||
// resolved in react-native this code should be removed
|
||||
if (getIntent().getData() != null) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
event.putString("url", getIntent().getDataString());
|
||||
// on first start emit will (silently) fail, but the regular deep linking handler will work
|
||||
tryToEmit("url", event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -202,7 +178,14 @@ public class MainActivity extends NavigationActivity
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript.
|
||||
* This is used to schedule rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected String getMainComponentName() {
|
||||
return "StatusIm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
@@ -216,7 +199,7 @@ public class MainActivity extends NavigationActivity
|
||||
private static final Integer FREQUENCY_OF_REMINDER_IN_PERCENT = 5;
|
||||
|
||||
private boolean shouldShowRootedNotification() {
|
||||
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
|
||||
if (RootUtil.isDeviceRooted()) {
|
||||
if (userRejectedRootedNotification()) {
|
||||
return ((Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT);
|
||||
} else return true;
|
||||
@@ -259,4 +242,14 @@ public class MainActivity extends NavigationActivity
|
||||
mPermissionListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new ReactActivityDelegate(this, getMainComponentName()) {
|
||||
@Override
|
||||
protected ReactRootView createRootView() {
|
||||
return new RNGestureHandlerEnabledRootView(MainActivity.this);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,22 +9,19 @@ import com.facebook.react.PackageList;
|
||||
|
||||
import com.aakashns.reactnativedialogs.ReactNativeDialogsPackage;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import cl.json.RNSharePackage;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.reactnativenavigation.NavigationApplication;
|
||||
import com.reactnativenavigation.react.NavigationReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import im.status.ethereum.keycard.RNStatusKeycardPackage;
|
||||
import im.status.ethereum.module.StatusPackage;
|
||||
import im.status.ethereum.pushnotifications.PushNotificationPackage;
|
||||
|
||||
public class MainApplication extends NavigationApplication {
|
||||
public class MainApplication extends MultiDexApplication implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost = new NavigationReactNativeHost(this) {
|
||||
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
@@ -33,12 +30,10 @@ public class MainApplication extends NavigationApplication {
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
StatusPackage statusPackage = new StatusPackage(RootUtil.isDeviceRooted());
|
||||
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
packages.add(statusPackage);
|
||||
packages.add(new ReactNativeDialogsPackage());
|
||||
packages.add(new RNStatusKeycardPackage());
|
||||
packages.add(new PushNotificationPackage());
|
||||
return packages;
|
||||
}
|
||||
|
||||
@@ -56,7 +51,7 @@ public class MainApplication extends NavigationApplication {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG_WEBVIEW == "1");
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* Project-wide gradle configuration properties for use by all modules
|
||||
*/
|
||||
ext {
|
||||
RNNKotlinVersion = "1.4.31"
|
||||
buildToolsVersion = project.buildToolsVersion
|
||||
minSdkVersion = Integer.valueOf(project.minSdkVersion)
|
||||
compileSdkVersion = Integer.valueOf(project.compileSdkVersion)
|
||||
@@ -20,7 +19,6 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31"
|
||||
classpath "com.android.tools.build:gradle:${project.ext.gradlePluginVersion}"
|
||||
// WARNING: Do not place your application dependencies here!
|
||||
// They belong in the individual module build.gradle files.
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
# Version requirements used throughout the Gradle scripts
|
||||
kotlinVersion=1.3.50
|
||||
minSdkVersion=23
|
||||
compileSdkVersion=30
|
||||
targetSdkVersion=30
|
||||
buildToolsVersion=31.0.0
|
||||
compileSdkVersion=29
|
||||
targetSdkVersion=29
|
||||
buildToolsVersion=29.0.2
|
||||
supportLibVersion=28.0.0
|
||||
# This should match version from nix/mobile/android/maven-and-npm-deps/maven/default.nix
|
||||
gradlePluginVersion=3.5.4
|
||||
gradlePluginVersion=3.5.3
|
||||
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
@@ -42,13 +42,10 @@ KEYSTORE_KEY_PASSWORD=password
|
||||
ANDROID_ABI_SPLIT=false
|
||||
# Some platforms are excluded though
|
||||
ANDROID_ABI_INCLUDE=armeabi-v7a;arm64-v8a;x86
|
||||
# F-Droid builds need to be unsigned
|
||||
ANDROID_APK_SIGNED=true
|
||||
|
||||
org.gradle.jvmargs=-Xmx8704M
|
||||
|
||||
versionCode=9999
|
||||
commitHash=unknown
|
||||
|
||||
# Flipper
|
||||
FLIPPER_VERSION=0.54.0
|
||||
FLIPPER_VERSION=0.35.0
|
||||
@@ -1,6 +1,4 @@
|
||||
pluginManagement {
|
||||
include ':react-native-share'
|
||||
project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android')
|
||||
repositories {
|
||||
mavenLocal() // Let's prioritize local Maven repos so that Nix can provide them offline
|
||||
gradlePluginPortal()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.3.3'
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
@@ -6,7 +6,7 @@ pipeline {
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
timeout(time: 45, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
@@ -101,13 +101,12 @@ pipeline {
|
||||
} else { /* if no universal is available pick first */
|
||||
env.PKG_URL = urls.first()
|
||||
}
|
||||
jenkins.setBuildDesc(APK: env.PKG_URL)
|
||||
/* e2e builds get tested in SauceLabs */
|
||||
if (utils.isE2EBuild()) {
|
||||
env.SAUCE_URL = android.uploadToSauceLabs()
|
||||
}
|
||||
if (utils.isNightlyBuild()) {
|
||||
env.DIAWI_URL = android.uploadToDiawi()
|
||||
/* build type specific */
|
||||
switch (btype) {
|
||||
case 'nightly':
|
||||
env.DIAWI_URL = android.uploadToDiawi(); break;
|
||||
case 'e2e':
|
||||
env.SAUCE_URL = android.uploadToSauceLabs(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +115,7 @@ pipeline {
|
||||
}
|
||||
stage('Cleanup') {
|
||||
steps {
|
||||
sh 'make purge'
|
||||
sh 'make clean'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.3.3'
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
@@ -7,7 +7,7 @@ pipeline {
|
||||
timestamps()
|
||||
disableConcurrentBuilds()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 40, unit: 'MINUTES')
|
||||
timeout(time: 45, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
@@ -16,20 +16,6 @@ pipeline {
|
||||
))
|
||||
}
|
||||
|
||||
/* WARNING: Defining parameters here with the ?: trick causes them to remember last value. */
|
||||
parameters {
|
||||
choice(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Makefile target to build. Optional Parameter.',
|
||||
choices: genChoices(params.BUILD_TYPE, ['manual', 'nightly', 'release', 'pr', 'e2e']),
|
||||
)
|
||||
booleanParam(
|
||||
name: 'PUBLISH',
|
||||
description: 'Trigger publishing of build results for nightly or release.',
|
||||
defaultValue: getPublishDefault(params.PUBLISH),
|
||||
)
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps { script {
|
||||
@@ -41,13 +27,13 @@ pipeline {
|
||||
stage('Build') {
|
||||
parallel {
|
||||
stage('iOS') { steps { script {
|
||||
ios = jenkins.Build('status-react/platforms/ios')
|
||||
ios = jenkins.Build('status-react/combined/mobile-ios')
|
||||
} } }
|
||||
stage('Android') { steps { script {
|
||||
apk = jenkins.Build('status-react/platforms/android')
|
||||
apk = jenkins.Build('status-react/combined/mobile-android')
|
||||
} } }
|
||||
stage('Android e2e') { steps { script {
|
||||
apke2e = jenkins.Build('status-react/platforms/android-e2e')
|
||||
apke2e = jenkins.Build('status-react/combined/mobile-android-e2e')
|
||||
} } }
|
||||
}
|
||||
}
|
||||
@@ -58,10 +44,9 @@ pipeline {
|
||||
//jenkins.copyArts(iose2e)
|
||||
jenkins.copyArts(apk)
|
||||
jenkins.copyArts(apke2e)
|
||||
sha = "pkg/${utils.pkgFilename(ext: 'sha256')}"
|
||||
dir('pkg') {
|
||||
/* generate sha256 checksums for upload */
|
||||
sh "sha256sum * | tee ../${sha}"
|
||||
sh "sha256sum * | tee ${utils.pkgFilename(btype, 'sha256')}"
|
||||
archiveArtifacts('*')
|
||||
}
|
||||
} }
|
||||
@@ -75,29 +60,27 @@ pipeline {
|
||||
iOS: utils.pkgUrl(ios), /*iOSe2e: utils.pkgUrl(iose2e),*/
|
||||
Diawi: utils.utils.getEnv(ios, 'DIAWI_URL'),
|
||||
/* upload the sha256 checksums file too */
|
||||
SHA: s3.uploadArtifact(sha),
|
||||
SHA: s3.uploadArtifact(utils.pkgFind('sha256')),
|
||||
]
|
||||
/* add URLs to the build description */
|
||||
jenkins.setBuildDesc(urls)
|
||||
/* Create JSON file with newest build URLs */
|
||||
switch (btype) {
|
||||
/* legacy naming, should have named it nightly.json */
|
||||
case 'nightly': s3.updateBucketJSON(urls, 'latest.json'); break
|
||||
}
|
||||
} }
|
||||
}
|
||||
stage('Publish') {
|
||||
when { expression { params.PUBLISH } }
|
||||
steps { script {
|
||||
switch (btype) {
|
||||
case 'nightly':
|
||||
/* Create JSON file with newest build URLs */
|
||||
s3.updateBucketJSON(urls, 'latest.json');
|
||||
build(job: 'website/status.im', wait: false);
|
||||
break;
|
||||
case 'release':
|
||||
github.publishReleaseFiles(repo: 'status-react');
|
||||
break;
|
||||
case 'nightly': build(job: 'misc/status.im', wait: false); break
|
||||
case 'release': github.publishReleaseMobile(); break
|
||||
}
|
||||
} }
|
||||
}
|
||||
stage('Run e2e') {
|
||||
when { expression { btype == 'nightly' && params.PUBLISH } }
|
||||
when { expression { btype == 'nightly' } }
|
||||
steps { script {
|
||||
e2eApk = utils.getEnv(apke2e, 'SAUCE_URL')
|
||||
build(
|
||||
@@ -109,24 +92,3 @@ pipeline {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper that generates list of available choices for a parameter
|
||||
* but re-orders them based on the currently set value. First is default. */
|
||||
def List genChoices(String previousChoice, List defaultChoices) {
|
||||
if (previousChoice == null) {
|
||||
return defaultChoices
|
||||
}
|
||||
choices = defaultChoices.minus(previousChoice)
|
||||
choices.add(0, previousChoice)
|
||||
return choices
|
||||
}
|
||||
|
||||
/* Helper that makes PUBLISH default to 'false' unless:
|
||||
* - The build is for a release branch
|
||||
* - A user explicitly specified a value
|
||||
* Since release builds create and re-create GitHub drafts every time. */
|
||||
def Boolean getPublishDefault(Boolean previousValue) {
|
||||
if (env.JOB_NAME.startsWith('status-react/release')) { return true }
|
||||
if (previousValue != null) { return previousValue }
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
library 'status-jenkins-lib@v1.3.3'
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos && x86_64 && xcode-12.5' }
|
||||
agent { label 'macos-xcode-11.5' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
@@ -14,7 +14,7 @@ pipeline {
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 25, unit: 'MINUTES')
|
||||
timeout(time: 45, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
@@ -99,9 +99,8 @@ pipeline {
|
||||
steps {
|
||||
script {
|
||||
env.PKG_URL = s3.uploadArtifact(api)
|
||||
jenkins.setBuildDesc(IPA: env.PKG_URL)
|
||||
/* e2e builds get tested in SauceLabs */
|
||||
if (utils.isE2EBuild()) {
|
||||
if (btype == 'e2e') {
|
||||
env.SAUCE_URL = ios.uploadToSauceLabs()
|
||||
} else {
|
||||
env.DIAWI_URL = ios.uploadToDiawi()
|
||||
@@ -114,7 +113,7 @@ pipeline {
|
||||
stage('Cleanup') {
|
||||
steps {
|
||||
sh 'make watchman-clean'
|
||||
sh 'make purge'
|
||||
sh 'make clean'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Specify build type. Values: pr / nightly / release',
|
||||
defaultValue: 'pr',
|
||||
)
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 40, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '20',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
/* Allows combined build to copy */
|
||||
copyArtifactPermission('/status-react/*')
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: Jenkins ignores PATH changes in Docker
|
||||
* https://issues.jenkins-ci.org/browse/JENKINS-49076
|
||||
**/
|
||||
environment {
|
||||
LANG = "en_US.UTF-8"
|
||||
LC_ALL = "en_US.UTF-8"
|
||||
LANGUAGE = "en_US.UTF-8"
|
||||
TARGET = 'linux'
|
||||
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
|
||||
VERBOSE_LEVEL = '3'
|
||||
/* We use EXECUTOR_NUMBER to avoid multiple instances clashing */
|
||||
YARN_CACHE_FOLDER = "/var/tmp/yarn-${EXECUTOR_NUMBER}"
|
||||
GRADLE_USER_HOME = "/var/tmp/gradle-${EXECUTOR_NUMBER}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Parallel Assemble') {
|
||||
parallel {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
sh 'make lint'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script {
|
||||
sh 'make test'
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
stage('Build') { stages {
|
||||
stage('JSBundle') {
|
||||
steps {
|
||||
script { desktop.buildJSBundle() }
|
||||
}
|
||||
}
|
||||
stage('Compile') {
|
||||
steps {
|
||||
script { desktop.compile() }
|
||||
}
|
||||
}
|
||||
stage('Bundle') {
|
||||
steps {
|
||||
script { app = desktop.bundleLinux(btype) }
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
stage('Parallel Upload') {
|
||||
parallel {
|
||||
stage('Archive') {
|
||||
steps {
|
||||
archiveArtifacts app
|
||||
}
|
||||
}
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script { env.PKG_URL = s3.uploadArtifact(app) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Cleanup') {
|
||||
steps {
|
||||
sh 'make watchman-clean'
|
||||
sh 'make clean'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos-xcode-11.5' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Specify build type. Values: pr / nightly / release',
|
||||
defaultValue: 'pr',
|
||||
)
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 30, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '20',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
/* Allows combined build to copy */
|
||||
copyArtifactPermission('/status-react/*')
|
||||
}
|
||||
|
||||
environment {
|
||||
LANG = "en_US.UTF-8"
|
||||
LC_ALL = "en_US.UTF-8"
|
||||
LANGUAGE = "en_US.UTF-8"
|
||||
TARGET = 'macos'
|
||||
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
|
||||
/* See nix/README.md */
|
||||
NIX_IGNORE_SYMLINK_STORE = 1
|
||||
VERBOSE_LEVEL = '3'
|
||||
/* We use EXECUTOR_NUMBER to avoid multiple instances clashing */
|
||||
YARN_CACHE_FOLDER = "/var/tmp/yarn-${EXECUTOR_NUMBER}"
|
||||
GRADLE_USER_HOME = "/var/tmp/gradle-${EXECUTOR_NUMBER}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Parallel Assemble') {
|
||||
parallel {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
sh 'make lint'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script {
|
||||
sh 'make test'
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
stage('Build') { stages {
|
||||
stage('JSBundle') {
|
||||
steps {
|
||||
script { desktop.buildJSBundle() }
|
||||
}
|
||||
}
|
||||
stage('Compile') {
|
||||
steps {
|
||||
script { desktop.compile() }
|
||||
}
|
||||
}
|
||||
stage('Bundle') {
|
||||
steps {
|
||||
script { dmg = desktop.bundleMacOS(btype) }
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
stage('Parallel Upload') {
|
||||
parallel {
|
||||
stage('Archive') {
|
||||
steps {
|
||||
archiveArtifacts dmg
|
||||
}
|
||||
}
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script { env.PKG_URL = s3.uploadArtifact(dmg) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Cleanup') {
|
||||
steps {
|
||||
sh 'make watchman-clean'
|
||||
sh 'make clean'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,16 @@
|
||||
library 'status-jenkins-lib@v1.3.3'
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'NIX_CACHE_HOST',
|
||||
description: 'FQDN of Nix binary cache host.',
|
||||
defaultValue: params.NIX_CACHE_HOST ?: 'cache-01.do-ams3.nix.ci.statusim.net'
|
||||
)
|
||||
string(
|
||||
name: 'NIX_CACHE_USER',
|
||||
description: 'Username for Nix binary cache host.',
|
||||
defaultValue: params.NIX_CACHE_USER ?: 'nix-cache'
|
||||
)
|
||||
}
|
||||
|
||||
environment {
|
||||
/* See nix/README.md */
|
||||
NIX_IGNORE_SYMLINK_STORE = 1
|
||||
/* we source .bash_profile to be able to use nix-store */
|
||||
NIX_SSHOPTS = "-o StrictHostKeyChecking=no source .profile;"
|
||||
NIX_SSHOPTS = "-o StrictHostKeyChecking=no source .bash_profile;"
|
||||
/* where our /nix/store is hosted */
|
||||
NIX_CACHE_USER = 'nix-cache'
|
||||
NIX_CACHE_HOST = 'master-01.do-ams3.ci.misc.statusim.net'
|
||||
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
|
||||
}
|
||||
|
||||
@@ -39,14 +29,14 @@ pipeline {
|
||||
stages {
|
||||
stage('Setup') {
|
||||
steps { script {
|
||||
nix.shell('nix-env -i openssh', sandbox: false, pure: false)
|
||||
nix.shell('nix-env -i openssh', pure: false)
|
||||
/* some build targets don't build on MacOS */
|
||||
uname = sh(script: 'uname', returnStdout: true)
|
||||
} }
|
||||
}
|
||||
stage('Build status-go') {
|
||||
steps { script {
|
||||
def platforms = ['mobile.android', 'mobile.ios']
|
||||
def platforms = ['mobile.android', 'mobile.ios', 'desktop']
|
||||
if (uname != "Darwin") {
|
||||
platforms.removeAll { it == "ios" }
|
||||
}
|
||||
@@ -98,8 +88,7 @@ pipeline {
|
||||
nix.shell("""
|
||||
find /nix/store/ -mindepth 1 -maxdepth 1 -type d \
|
||||
-not -name '*.links' -and -not -name '*-status-react-*' \
|
||||
| xargs nix-copy-closure -v \
|
||||
--to ${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}
|
||||
| xargs nix-copy-closure -v --to ${NIX_CACHE_USER}@${NIX_CACHE_HOST}
|
||||
""",
|
||||
pure: false
|
||||
)
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Specify build type. Values: pr / nightly / release',
|
||||
defaultValue: 'pr',
|
||||
)
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 45, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '10',
|
||||
daysToKeepStr: '20',
|
||||
artifactNumToKeepStr: '10',
|
||||
))
|
||||
/* Allows combined build to copy */
|
||||
copyArtifactPermission('/status-react/*')
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: Jenkins ignores PATH changes in Docker
|
||||
* https://issues.jenkins-ci.org/browse/JENKINS-49076
|
||||
**/
|
||||
environment {
|
||||
LANG = "en_US.UTF-8"
|
||||
LC_ALL = "en_US.UTF-8"
|
||||
LANGUAGE = "en_US.UTF-8"
|
||||
TARGET = 'windows'
|
||||
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
|
||||
VERBOSE_LEVEL = '3'
|
||||
/* Conan settings */
|
||||
CONAN_PRINT_RUN_COMMANDS = '1'
|
||||
CONAN_SYSREQUIRES_MODE = 'disabled'
|
||||
CONAN_SYSREQUIRES_SUDO = '0'
|
||||
/* We use EXECUTOR_NUMBER to avoid multiple instances clashing */
|
||||
YARN_CACHE_FOLDER = "/var/tmp/yarn-${EXECUTOR_NUMBER}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Parallel Assemble') {
|
||||
parallel {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
sh 'make lint'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script {
|
||||
sh 'make test'
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
stage('Build') { stages {
|
||||
stage('JSBundle') {
|
||||
steps {
|
||||
script { desktop.buildJSBundle() }
|
||||
}
|
||||
}
|
||||
stage('Compile') {
|
||||
steps {
|
||||
script { desktop.compile() }
|
||||
}
|
||||
}
|
||||
stage('Bundle') {
|
||||
steps {
|
||||
script { app = desktop.bundleWindows(btype) }
|
||||
}
|
||||
}
|
||||
} }
|
||||
}
|
||||
}
|
||||
stage('Parallel Upload') {
|
||||
parallel {
|
||||
stage('Archive') {
|
||||
steps {
|
||||
archiveArtifacts app
|
||||
}
|
||||
}
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script { env.PKG_URL = s3.uploadArtifact(app) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Cleanup') {
|
||||
steps {
|
||||
sh 'make watchman-clean'
|
||||
sh 'make clean'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ This folder contains files defininf [Jenkins pipelines](https://jenkins.io/doc/b
|
||||
|
||||
All `Jenkinsfile`s contain the following line:
|
||||
```groovy
|
||||
library 'status-jenkins-lib@master'
|
||||
library 'status-react-jenkins@master'
|
||||
```
|
||||
|
||||
Which loads the used methods - like `nix.shell()` - from a separate private repo:
|
||||
|
||||
https://github.com/status-im/status-jenkins-lib
|
||||
https://github.com/status-im/status-react-jenkins
|
||||
|
||||
This is done to improve security of our CI setup.
|
||||
|
||||
@@ -44,19 +44,13 @@ pipeline {
|
||||
credentialsId: 'etherscan-api-key',
|
||||
variable: 'ETHERSCAN_API_KEY'
|
||||
),
|
||||
string(
|
||||
credentialsId: 'infura-e2e-token',
|
||||
variable: 'WEB3_INFURA_PROJECT_ID'
|
||||
),
|
||||
]) {
|
||||
dir('test/appium/tests') {
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 15 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-m testrail_id \
|
||||
python3 -m pytest -m testrail_id \
|
||||
-m "not upgrade" \
|
||||
-n24 --rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
--network=${params.NETWORK} \
|
||||
--apk=${params.APK_NAME}
|
||||
"""
|
||||
|
||||
@@ -62,7 +62,7 @@ pipeline {
|
||||
|
||||
withCredentials([
|
||||
usernamePassword(
|
||||
credentialsId: 'status-im-auto',
|
||||
credentialsId: 'status-im-auto-token',
|
||||
usernameVariable: 'GIT_HUB_USER', /* ignored */
|
||||
passwordVariable: 'GIT_HUB_TOKEN'
|
||||
),
|
||||
@@ -80,15 +80,10 @@ pipeline {
|
||||
credentialsId: 'etherscan-api-key',
|
||||
variable: 'ETHERSCAN_API_KEY'
|
||||
),
|
||||
string(
|
||||
credentialsId: 'infura-e2e-token',
|
||||
variable: 'WEB3_INFURA_PROJECT_ID'
|
||||
),
|
||||
]) {
|
||||
dir('test/appium/tests') {
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
--numprocesses 15 \
|
||||
python3 -m pytest -n24 \
|
||||
--rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
-m "${params.TEST_MARKERS}" \
|
||||
|
||||
@@ -48,17 +48,11 @@ pipeline {
|
||||
credentialsId: 'etherscan-api-key',
|
||||
variable: 'ETHERSCAN_API_KEY'
|
||||
),
|
||||
string(
|
||||
credentialsId: 'infura-e2e-token',
|
||||
variable: 'WEB3_INFURA_PROJECT_ID'
|
||||
),
|
||||
]) {
|
||||
dir('test/appium/tests') {
|
||||
sh """
|
||||
python3 -m pytest \
|
||||
-m upgrade \
|
||||
--numprocesses 15 \
|
||||
--rerun_count=2 \
|
||||
python3 -m pytest -m upgrade \
|
||||
-n24 --rerun_count=2 \
|
||||
--testrail_report=True \
|
||||
--network=${params.NETWORK} \
|
||||
--apk=${params.APK_NAME} \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.3.3'
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
library 'status-jenkins-lib@v1.3.3'
|
||||
library 'status-react-jenkins@v1.1.7'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
@@ -38,7 +38,7 @@ pipeline {
|
||||
steps { script {
|
||||
withCredentials([
|
||||
string(
|
||||
credentialsId: 'google-play-api-key-json',
|
||||
credentialsId: 'SUPPLY_JSON_KEY_DATA',
|
||||
variable: 'GOOGLE_PLAY_JSON_KEY'
|
||||
),
|
||||
]) {
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* This job runs daily and executes `pod repo update` on MacOS
|
||||
* This is done to avoid issues with out of date repo causing errors like:
|
||||
*
|
||||
* Failed with exit code 1 (in target 'StatusImPR' from project 'StatusIm')
|
||||
**/
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label params.HOST_LABEL
|
||||
}
|
||||
|
||||
triggers {
|
||||
/* Run daily at 2am */
|
||||
cron('H 2 * * *')
|
||||
}
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
timeout(time: 5, unit: 'MINUTES')
|
||||
/* Limit builds retained */
|
||||
buildDiscarder(logRotator(
|
||||
numToKeepStr: '20',
|
||||
))
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'HOST_LABEL',
|
||||
description: 'Label of host to run on',
|
||||
/* Using startTimeInMillis to randomize which host gets the update. */
|
||||
defaultValue: "maci7-0${(currentBuild.startTimeInMillis % 3) + 1}",
|
||||
)
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Update') {
|
||||
steps {
|
||||
sh 'pod repo update'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Status
|
||||
Comment=Status Desktop
|
||||
Exec=Status
|
||||
Icon=Status
|
||||
Categories=Network;
|
||||
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Status</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Status</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>status-icon</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>im.status.statusim</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Status</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1</string>
|
||||
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.9.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>status-im</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>im.status.ethereum.applink-desktop</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function make_icns {
|
||||
local file="../status-icon.png"
|
||||
local iconset="$(mktemp -d)"
|
||||
local output_icon="status-icon.icns"
|
||||
|
||||
for size in {16,32,64,128,256,512}; do
|
||||
sips --resampleHeightWidth "${size}" "${size}" "${file}" --out "${iconset}/icon_${size}x${size}.png" &> /dev/null
|
||||
sips --resampleHeightWidth "$((size * 2))" "$((size * 2))" "${file}" --out "${iconset}/icon_${size}x${size}@2x.png" &> /dev/null
|
||||
done
|
||||
|
||||
mv "${iconset}" "${iconset}.iconset"
|
||||
iconutil --convert icns "${iconset}.iconset" --output "${output_icon}"
|
||||
|
||||
echo "${output_icon}" # so its path is returned when the function ends
|
||||
}
|
||||
|
||||
make_icns
|
||||
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,4 @@
|
||||
[Paths]
|
||||
Plugins = ../PlugIns
|
||||
Imports = ../Resources/qml
|
||||
Qml2Imports = ../Resources/qml
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"title": "Status",
|
||||
"background": "dmg-background.png",
|
||||
"contents": [
|
||||
{
|
||||
"x": 385,
|
||||
"y": 235,
|
||||
"type": "link",
|
||||
"path": "/Applications"
|
||||
},
|
||||
{
|
||||
"x": 170,
|
||||
"y": 236,
|
||||
"type": "file",
|
||||
"path": "../../StatusImPackage/Status.app"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 121 KiB |
@@ -0,0 +1,24 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68">
|
||||
<defs>
|
||||
<ellipse id="b" cx="31.969" cy="31.938" rx="31.969" ry="31.938"/>
|
||||
<filter id="a" width="114.1%" height="114.1%" x="-7%" y="-3.9%" filterUnits="objectBoundingBox">
|
||||
<feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/>
|
||||
<feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation=".5"/>
|
||||
<feColorMatrix in="shadowBlurOuter1" result="shadowMatrixOuter1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.22 0"/>
|
||||
<feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter2"/>
|
||||
<feGaussianBlur in="shadowOffsetOuter2" result="shadowBlurOuter2" stdDeviation="1"/>
|
||||
<feColorMatrix in="shadowBlurOuter2" result="shadowMatrixOuter2" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="shadowMatrixOuter1"/>
|
||||
<feMergeNode in="shadowMatrixOuter2"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="nonzero">
|
||||
<g transform="translate(2 1)">
|
||||
<use fill="#000" filter="url(#a)" xlink:href="#b"/>
|
||||
<use fill="#FFF" xlink:href="#b"/>
|
||||
</g>
|
||||
<path fill="#4360DF" d="M34 1.062c-17.673 0-32 14.313-32 31.97C2 50.686 16.327 65 34 65c17.673 0 32-14.313 32-31.969 0-8.478-3.371-16.61-9.373-22.605A32.016 32.016 0 0 0 34 1.062zm-4.902 46.17c-4.013.225-8.023-2.192-8.243-6.118-.213-3.859 2.799-6.44 7.779-6.72 3.674-.207 5.97.628 9.65.421.911-.05 1.817-.18 2.706-.386-.543 6.633-5.352 12.435-11.892 12.803zm10.298-14.497c-3.834.222-6.238-.671-10.076-.45-.951.053-1.896.191-2.823.413.56-7.084 5.587-13.288 12.414-13.68 4.189-.243 8.376 2.342 8.604 6.536.224 4.124-2.922 6.883-8.119 7.18z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,71 @@
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE resource.
|
||||
//
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
#include "targetver.h"
|
||||
#endif
|
||||
#define APSTUDIO_HIDDEN_SYMBOLS
|
||||
#include "windows.h"
|
||||
#undef APSTUDIO_HIDDEN_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE 9, 1
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
|
||||
IDI_STATUS ICON "${ICO_RESOURCE_PATH}"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#ifndef APSTUDIO_INVOKED\r\n"
|
||||
"#include ""targetver.h""\r\n"
|
||||
"#endif\r\n"
|
||||
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE resource.
|
||||
//
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
@@ -0,0 +1,23 @@
|
||||
!include LogicLib.nsh
|
||||
!include WordFunc.nsh
|
||||
|
||||
Function SnoreWinVer
|
||||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
|
||||
${VersionCompare} "6.2" $R0 $R0
|
||||
${If} $R0 == 1
|
||||
Push "NotWin8"
|
||||
${Else}
|
||||
Push "AtLeastWin8"
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
!macro SnoreShortcut path exe appID
|
||||
Call SnoreWinVer
|
||||
Pop $0
|
||||
${If} $0 == "AtLeastWin8"
|
||||
nsExec::ExecToLog '"${SnoreToastExe}" -install "${path}" "${exe}" "${appID}"'
|
||||
${Else}
|
||||
DetailPrint "Creating shortcut to ${exe}"
|
||||
CreateShortCut "${path}" "${exe}"
|
||||
${EndIf}
|
||||
!macroend
|
||||
@@ -0,0 +1,299 @@
|
||||
/*** UAC Plug-in ***
|
||||
|
||||
Interactive User (MediumIL) Admin user (HighIL)
|
||||
***[Setup.exe]************* ***[Setup.exe]**************
|
||||
* * * *
|
||||
* +++[.OnInit]+++++++++++ * * +++[.OnInit]++++++++++++ *
|
||||
* + UAC_RunElevated >---+-+----> * + + *
|
||||
* + NSIS.Quit + * * + + *
|
||||
* +++++++++++++++++++++++ * * ++++++++++++++++++++++++ *
|
||||
* * * *
|
||||
* * * *
|
||||
* +++[Section]+++++++++++ * * +++[Section]++++++++++++ *
|
||||
* + + * /--+-+-<UAC_AsUser_ExecShell+ *
|
||||
* +++++++++++++++++++++++ * | * ++++++++++++++++++++++++ *
|
||||
* * | * *
|
||||
* Win32.ShellExecute <---+--/ * *
|
||||
* * * *
|
||||
*************************** ****************************
|
||||
|
||||
*/
|
||||
|
||||
!ifndef UAC_HDR__INC
|
||||
!verbose push
|
||||
!verbose 3
|
||||
!ifndef UAC_VERBOSE
|
||||
!define UAC_VERBOSE 3
|
||||
!endif
|
||||
!verbose ${UAC_VERBOSE}
|
||||
|
||||
!define UAC_HDR__INC 0x00020400 ;MMmmbbrr
|
||||
|
||||
!include LogicLib.nsh
|
||||
|
||||
|
||||
|
||||
/* UAC_RunElevated
|
||||
**
|
||||
** Starts the elevation operation.
|
||||
**
|
||||
** Return values:
|
||||
**
|
||||
** $0: Win32 error code (0 on success, 1223 if user aborted elevation dialog, anything else should be treated as a fatal error)
|
||||
** $1: If $0==0:
|
||||
** 0 UAC is not supported by the OS
|
||||
** 1 Started a elevated child process, the current process should act like a wrapper (Call Quit without any further processing)
|
||||
** 2 The process is already running @ HighIL (Member of admin group)
|
||||
** 3 You should call RunElevated again (This can happen if a user without admin priv. is used in the runas dialog)
|
||||
** $2: If $0==0 && $1==1: ExitCode of the elevated fork process (The NSIS errlvl is also set)
|
||||
** $3: If $0==0: 1 if the user is a member of the admin group or 0 otherwise
|
||||
**/
|
||||
!macro UAC_RunElevated
|
||||
UAC::_ 0
|
||||
!macroend
|
||||
!macro UAC_PageElevation_RunElevated
|
||||
UAC::_ 0
|
||||
!macroend
|
||||
/*!macro UAC_OnInitElevation_RunElevated
|
||||
UAC::_ 0
|
||||
!macroend
|
||||
!macro UAC_OnInitElevation_OnGuiInit
|
||||
!macroend*/
|
||||
|
||||
|
||||
|
||||
/* UAC_GetIntegrityLevel <NSISVar:Output | "s">
|
||||
**
|
||||
** Get integrity level of current process
|
||||
**
|
||||
**/
|
||||
!macro UAC_GetIntegrityLevel outvar
|
||||
UAC::_ 6
|
||||
!if "${outvar}" != "s"
|
||||
Pop ${outvar}
|
||||
!endif
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/* UAC_IsAdmin
|
||||
**
|
||||
** Is the current process running with administrator privileges? Result in $0
|
||||
**
|
||||
** ${If} ${UAC_IsAdmin} ...
|
||||
**
|
||||
**/
|
||||
!macro UAC_IsAdmin
|
||||
UAC::_ 2
|
||||
!macroend
|
||||
!define UAC_IsAdmin `"" UAC_IsAdmin ""`
|
||||
!macro _UAC_IsAdmin _a _b _t _f
|
||||
!insertmacro _UAC_MakeLL_Cmp _!= 0 2s
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/* UAC_IsInnerInstance
|
||||
**
|
||||
** Does the current process have a NSIS/UAC parent process that is part of the elevation operation?
|
||||
**
|
||||
** ${If} ${UAC_IsInnerInstance} ...
|
||||
**
|
||||
**/
|
||||
!macro UAC_IsInnerInstance
|
||||
UAC::_ 3
|
||||
!macroend
|
||||
!define UAC_IsInnerInstance `"" UAC_IsInnerInstance ""`
|
||||
!macro _UAC_IsInnerInstance _a _b _t _f
|
||||
!insertmacro _UAC_MakeLL_Cmp _!= 0 3s
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/* UAC_PageElevation_OnInit, UAC_PageElevation_OnGuiInit,
|
||||
**
|
||||
** Helper macros for elevation on a custom elevation page, see the DualMode example for more information.
|
||||
**
|
||||
**/
|
||||
!macro UAC_Notify_OnGuiInit
|
||||
UAC::_ 4
|
||||
!macroend
|
||||
!macro UAC_PageElevation_OnGuiInit
|
||||
!insertmacro UAC_Notify_OnGuiInit
|
||||
!macroend
|
||||
!macro UAC_PageElevation_OnInit
|
||||
UAC::_ 5
|
||||
${IfThen} ${Errors} ${|} Quit ${|}
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/* UAC_AsUser_Call <Function|Label> <NSISAddressName> <UAC_* flags>
|
||||
**
|
||||
** Calls a function or label in the user process instance.
|
||||
** All the UAC_AsUser_* macros use this helper macro.
|
||||
**
|
||||
**/
|
||||
!define UAC_SYNCREGISTERS 0x1
|
||||
;define UAC_SYNCSTACK 0x2
|
||||
!define UAC_SYNCOUTDIR 0x4
|
||||
!define UAC_SYNCINSTDIR 0x8
|
||||
;define UAC_CLEARERRFLAG 0x10
|
||||
!macro UAC_AsUser_Call type name flags
|
||||
push $0
|
||||
Get${type}Address $0 ${name}
|
||||
!verbose push
|
||||
!verbose ${UAC_VERBOSE}
|
||||
!insertmacro _UAC_ParseDefineFlagsToInt _UAC_AsUser_Call__flags ${flags}
|
||||
!verbose pop
|
||||
StrCpy $0 "1$0:${_UAC_AsUser_Call__flags}"
|
||||
!undef _UAC_AsUser_Call__flags
|
||||
Exch $0
|
||||
UAC::_
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** UAC_AsUser_GetSection <Flags|InstTypes|Size|Text> <SectionIndex> <NSISVar:Output>
|
||||
*/
|
||||
!macro UAC_AsUser_GetSection secprop secidx outvar
|
||||
!insertmacro _UAC_AsUser_GenOp ${outvar} SectionGet${secprop} ${secidx} ""
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** UAC_AsUser_GetGlobalVar <NSISVar:SourceAndOutput>
|
||||
** UAC_AsUser_GetGlobal <NSISVar:Output> <NSISVar:Source>
|
||||
*/
|
||||
!macro UAC_AsUser_GetGlobalVar var
|
||||
!insertmacro _UAC_AsUser_GenOp ${var} StrCpy "" ${var}
|
||||
!macroend
|
||||
!macro UAC_AsUser_GetGlobal outvar srcvar
|
||||
!insertmacro _UAC_AsUser_GenOp ${outvar} StrCpy "" ${srcvar}
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** UAC_AsUser_ExecShell <Verb> <ApplicationOrFile> <Parameters> <Working Directory> <SW_*>
|
||||
**
|
||||
** Call ExecShell in the user process instance.
|
||||
**
|
||||
*/
|
||||
!macro UAC_AsUser_ExecShell verb command params workdir show
|
||||
!insertmacro _UAC_IncL
|
||||
goto _UAC_L_E_${__UAC_L}
|
||||
_UAC_L_F_${__UAC_L}:
|
||||
ExecShell "${verb}" "${command}" '${params}' ${show}
|
||||
return
|
||||
_UAC_L_E_${__UAC_L}:
|
||||
!if "${workdir}" != ""
|
||||
push $outdir
|
||||
SetOutPath "${workdir}"
|
||||
!endif
|
||||
!insertmacro UAC_AsUser_Call Label _UAC_L_F_${__UAC_L} ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} #|${UAC_CLEARERRFLAG}
|
||||
!if "${workdir}" != ""
|
||||
pop $outdir
|
||||
SetOutPath $outdir
|
||||
!endif
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!macro _UAC_MakeLL_Cmp cmpop cmp pluginparams
|
||||
!insertmacro _LOGICLIB_TEMP
|
||||
UAC::_ ${pluginparams}
|
||||
pop $_LOGICLIB_TEMP
|
||||
!insertmacro ${cmpop} $_LOGICLIB_TEMP ${cmp} `${_t}` `${_f}`
|
||||
!macroend
|
||||
!macro _UAC_definemath def val1 op val2
|
||||
!define /math _UAC_definemath "${val1}" ${op} ${val2}
|
||||
!ifdef ${def}
|
||||
!undef ${def}
|
||||
!endif
|
||||
!define ${def} "${_UAC_definemath}"
|
||||
!undef _UAC_definemath
|
||||
!macroend
|
||||
!macro _UAC_ParseDefineFlags_orin parse outflags
|
||||
!searchparse /noerrors ${${parse}} "" _UAC_ParseDefineFlags_orin_f1 "|" _UAC_ParseDefineFlags_orin_f2
|
||||
!define _UAC_ParseDefineFlags_orin_this ${_UAC_ParseDefineFlags_orin_f1}
|
||||
!undef ${parse}
|
||||
!define ${parse} ${_UAC_ParseDefineFlags_orin_f2}
|
||||
!define _UAC_ParseDefineFlags_orin_saveout ${${outflags}}
|
||||
!undef ${outflags}
|
||||
!define /math ${outflags} "${_UAC_ParseDefineFlags_orin_saveout}" | "${_UAC_ParseDefineFlags_orin_this}"
|
||||
!undef _UAC_ParseDefineFlags_orin_saveout
|
||||
!undef _UAC_ParseDefineFlags_orin_this
|
||||
!ifdef _UAC_ParseDefineFlags_orin_f1
|
||||
!undef _UAC_ParseDefineFlags_orin_f1
|
||||
!endif
|
||||
!ifdef _UAC_ParseDefineFlags_orin_f2
|
||||
!undef _UAC_ParseDefineFlags_orin_f2
|
||||
!endif
|
||||
!macroend
|
||||
!macro _UAC_ParseDefineFlags_Begin _outdef _in
|
||||
!define _UAC_PDF${_outdef}_parse "${_in}"
|
||||
!define _UAC_PDF${_outdef}_flags ""
|
||||
!define _UAC_PDF${_outdef}_r 0
|
||||
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x1
|
||||
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x2
|
||||
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x4
|
||||
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x8
|
||||
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x10
|
||||
!macroend
|
||||
!macro _UAC_ParseDefineFlags_End _outdef
|
||||
!define ${_outdef} ${_UAC_PDF${_outdef}_r}
|
||||
!undef _UAC_PDF${_outdef}_r
|
||||
!undef _UAC_PDF${_outdef}_flags
|
||||
!undef _UAC_PDF${_outdef}_parse
|
||||
!macroend
|
||||
!macro _UAC_ParseDefineFlags_IncludeFlag _outdef flag
|
||||
!if ${_UAC_PDF${_outdef}_flags} & ${flag}
|
||||
!insertmacro _UAC_definemath _UAC_PDF${_outdef}_r ${_UAC_PDF${_outdef}_r} | ${flag}
|
||||
!endif
|
||||
!macroend
|
||||
!macro _UAC_ParseDefineFlagsToInt _outdef _in
|
||||
!insertmacro _UAC_ParseDefineFlags_Begin _UAC_ParseDefineFlagsToInt_tmp "${_in}"
|
||||
!define ${_outdef} ${_UAC_PDF_UAC_ParseDefineFlagsToInt_tmp_flags}
|
||||
!insertmacro _UAC_ParseDefineFlags_End _UAC_ParseDefineFlagsToInt_tmp
|
||||
!undef _UAC_ParseDefineFlagsToInt_tmp
|
||||
!macroend
|
||||
!macro _UAC_IncL
|
||||
!insertmacro _UAC_definemath __UAC_L "${__UAC_L}" + 1
|
||||
!macroend
|
||||
!macro _UAC_AsUser_GenOp outvar op opparam1 opparam2
|
||||
!define _UAC_AUGOGR_ID _UAC_AUGOGR_OP${outvar}${op}${opparam1}${opparam2}
|
||||
!ifndef ${_UAC_AUGOGR_ID} ;Has this exact action been done before?
|
||||
!if ${outvar} == $0
|
||||
!define ${_UAC_AUGOGR_ID} $1
|
||||
!else
|
||||
!define ${_UAC_AUGOGR_ID} $0
|
||||
!endif
|
||||
!if "${opparam1}" == ""
|
||||
!define _UAC_AUGOGR_OPP1 ${${_UAC_AUGOGR_ID}}
|
||||
!define _UAC_AUGOGR_OPP2 ${opparam2}
|
||||
!else
|
||||
!define _UAC_AUGOGR_OPP1 ${opparam1}
|
||||
!define _UAC_AUGOGR_OPP2 ${${_UAC_AUGOGR_ID}}
|
||||
!endif
|
||||
goto ${_UAC_AUGOGR_ID}_C
|
||||
${_UAC_AUGOGR_ID}_F:
|
||||
${op} ${_UAC_AUGOGR_OPP1} ${_UAC_AUGOGR_OPP2}
|
||||
return
|
||||
${_UAC_AUGOGR_ID}_C:
|
||||
!undef _UAC_AUGOGR_OPP1
|
||||
!undef _UAC_AUGOGR_OPP2
|
||||
!endif
|
||||
push ${${_UAC_AUGOGR_ID}}
|
||||
!insertmacro UAC_AsUser_Call Label ${_UAC_AUGOGR_ID}_F ${UAC_SYNCREGISTERS}
|
||||
StrCpy ${outvar} ${${_UAC_AUGOGR_ID}}
|
||||
pop ${${_UAC_AUGOGR_ID}}
|
||||
!undef _UAC_AUGOGR_ID
|
||||
!macroend
|
||||
|
||||
|
||||
|
||||
!verbose pop
|
||||
!endif /* UAC_HDR__INC */
|
||||
@@ -0,0 +1,28 @@
|
||||
!define nsProcess::FindProcess `!insertmacro nsProcess::FindProcess`
|
||||
|
||||
!macro nsProcess::FindProcess _FILE _ERR
|
||||
nsProcess::_FindProcess /NOUNLOAD `${_FILE}`
|
||||
Pop ${_ERR}
|
||||
!macroend
|
||||
|
||||
|
||||
!define nsProcess::KillProcess `!insertmacro nsProcess::KillProcess`
|
||||
|
||||
!macro nsProcess::KillProcess _FILE _ERR
|
||||
nsProcess::_KillProcess /NOUNLOAD `${_FILE}`
|
||||
Pop ${_ERR}
|
||||
!macroend
|
||||
|
||||
!define nsProcess::CloseProcess `!insertmacro nsProcess::CloseProcess`
|
||||
|
||||
!macro nsProcess::CloseProcess _FILE _ERR
|
||||
nsProcess::_CloseProcess /NOUNLOAD `${_FILE}`
|
||||
Pop ${_ERR}
|
||||
!macroend
|
||||
|
||||
|
||||
!define nsProcess::Unload `!insertmacro nsProcess::Unload`
|
||||
|
||||
!macro nsProcess::Unload
|
||||
nsProcess::_Unload
|
||||
!macroend
|
||||
@@ -0,0 +1,20 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// clang-format off
|
||||
// Used by Status.rc
|
||||
|
||||
#define IDI_STATUS 107
|
||||
#ifndef IDC_STATIC
|
||||
#define IDC_STATIC -1
|
||||
#endif
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#define _APS_NO_MFC 130
|
||||
#define _APS_NEXT_RESOURCE_VALUE 129
|
||||
#define _APS_NEXT_COMMAND_VALUE 32771
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 110
|
||||
#endif
|
||||
#endif
|
||||
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <sdkddkver.h>
|
||||
@@ -0,0 +1,99 @@
|
||||
|
||||
# Copyright (C) 2016, Canonical Ltd.
|
||||
# All rights reserved.
|
||||
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
cmake_minimum_required(VERSION 3.12.1)
|
||||
|
||||
set(APP_NAME Status)
|
||||
set(JS_APP_NAME StatusIm)
|
||||
set(REACT_BUILD_STATIC_LIB ON)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -std=c++11")
|
||||
if(STATUS_NO_LOGGING)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSTATUS_NO_LOGGING")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUNICODE -std=c11")
|
||||
set(CMAKE_INSTALL_PREFIX bin)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_PREFIX}" CACHE PATH "Where to place compiled executables.")
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")
|
||||
|
||||
project(${APP_NAME} C CXX)
|
||||
set(${APP_NAME}_BINARY_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
|
||||
set(USED_QT_MODULES Core Concurrent Qml Quick WebSockets Svg)
|
||||
include(QtConfiguration)
|
||||
|
||||
set(ICON_PNG_RESOURCE_PATH "${CMAKE_SOURCE_DIR}/../deployment/status-icon.png")
|
||||
if (WIN32)
|
||||
set(ICO_RESOURCE_PATH "${CMAKE_SOURCE_DIR}/../deployment/windows/status.ico")
|
||||
set(APPLICATION_MAIN_RC_PATH "${CMAKE_SOURCE_DIR}/../deployment/windows/Status.rc")
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/../deployment/windows/Status.rc.in
|
||||
${APPLICATION_MAIN_RC_PATH}
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "EXTERNAL_MODULES_DIR: ${EXTERNAL_MODULES_DIR}")
|
||||
|
||||
string(REGEX MATCH "BUILD_FOR_BUNDLE" BUILD_FOR_BUNDLE "${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# It is important to distinguish between directory hierarchies
|
||||
# in release and dev builds. Release contains .env
|
||||
# in the root dir of the build, while dev build's current dir
|
||||
# is status-react/desktop/bin, hence the need
|
||||
# to jump two levels up.
|
||||
# This is required by react-native-config library which references ENVFILE
|
||||
# from its own CMakeLists.txt file, so it will read the value set here
|
||||
if(${BUILD_FOR_BUNDLE} MATCHES "BUILD_FOR_BUNDLE")
|
||||
set(ENVFILE "/.env")
|
||||
else()
|
||||
set(ENVFILE "/../../.env")
|
||||
endif()
|
||||
|
||||
foreach(external_module ${EXTERNAL_MODULES_DIR})
|
||||
message(STATUS "external_module: ${external_module}")
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../${external_module} ${CMAKE_CURRENT_BINARY_DIR}/${external_module})
|
||||
endforeach(external_module)
|
||||
|
||||
add_subdirectory(reportApp)
|
||||
|
||||
# Import any new Qt modules that have been added by external dependencies
|
||||
import_qt_modules()
|
||||
|
||||
# APPLICATION_MAIN_CPP_PATH contains absolute path to generated template copy of main.cpp for application executable
|
||||
get_filename_component(APPLICATION_MAIN_CPP_PATH main.cpp ABSOLUTE)
|
||||
|
||||
set(REACTQT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../node_modules/react-native/React)
|
||||
include_directories(${REACTQT_DIR}/Layout)
|
||||
add_subdirectory(${REACTQT_DIR}Qt/runtime/src ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||
add_subdirectory(${REACTQT_DIR}Qt/application/src ${CMAKE_CURRENT_BINARY_DIR}/bin)
|
||||
|
||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif(Qt5_POSITION_INDEPENDENT_CODE)
|
||||
|
||||
target_sources(${APP_NAME}
|
||||
PRIVATE
|
||||
"${CMAKE_CURRENT_LIST_DIR}/appconfig.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/appconfig.cpp")
|
||||
|
||||
#set(SOURCE_ROOT ${CMAKE_SOURCE_DIR})
|
||||
include(CompleteBundle)
|
||||
|
||||
if (WIN32)
|
||||
set(RUN_SCRIPT_FILE_NAME "run-app.bat")
|
||||
else()
|
||||
set(RUN_SCRIPT_FILE_NAME "run-app.sh")
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${RUN_SCRIPT_FILE_NAME}.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${RUN_SCRIPT_FILE_NAME}
|
||||
@ONLY
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
if(APPLE)
|
||||
set(SCRIPT CompleteBundleOSX)
|
||||
elseif(WIN32)
|
||||
set(SCRIPT CompleteBundleWin)
|
||||
elseif(UNIX)
|
||||
set(SCRIPT CompleteBundleLinux)
|
||||
endif(APPLE)
|
||||
|
||||
if(SCRIPT AND EXISTS ${CMAKE_SOURCE_DIR}/CMakeModules/${SCRIPT}.cmake.in)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/CMakeModules/${SCRIPT}.cmake.in ${SCRIPT}.cmake @ONLY)
|
||||
include(${CMAKE_CURRENT_BINARY_DIR}/${SCRIPT}.cmake)
|
||||
endif()
|
||||
@@ -0,0 +1,62 @@
|
||||
# windeployqt should be used here, but since we get the `Not implemented` error from it, we're trying to manually copy artifacts to output directory
|
||||
set(TARGET_DIR "${@APP_NAME@_BINARY_DIR}")
|
||||
|
||||
##########################################################################################################
|
||||
#
|
||||
# NOTE: Remember to reflect any changes on the setup generation procedure in /deployment/windows/nsis/setup.nsi
|
||||
#
|
||||
##########################################################################################################
|
||||
|
||||
set(qtmodules Core Quick QuickTemplates2 QuickControls2 WebSockets Widgets Gui Network Svg Qml Concurrent)
|
||||
if(USE_QTWEBKIT)
|
||||
set(qtmodules ${qtmodules} Multimedia WebKit WebKitWidgets WebChannel)
|
||||
|
||||
add_custom_command(TARGET @APP_NAME@ POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"@CONAN_BIN_DIRS_QT5-MXE@/QtWebProcess.exe"
|
||||
${TARGET_DIR}
|
||||
BYPRODUCTS ${TARGET_DIR}/QtWebProcess.exe)
|
||||
endif()
|
||||
foreach(qtmodule ${qtmodules})
|
||||
message(STATUS "Copying ${qtmodule} module to ${TARGET_DIR}")
|
||||
file(COPY "@CONAN_BIN_DIRS_QT5-MXE@/Qt5${qtmodule}.dll" DESTINATION "${TARGET_DIR}")
|
||||
endforeach(qtmodule ${qtmodules})
|
||||
if(EXISTS "@QTROOT@/translations")
|
||||
message(STATUS "Copying translations module to ${TARGET_DIR}")
|
||||
file(COPY "@QTROOT@/translations" DESTINATION "${TARGET_DIR}")
|
||||
endif()
|
||||
|
||||
set(qtplugindirs "bearer" "platforms" "styles" "iconengines" "imageformats")
|
||||
foreach(qtplugindir ${qtplugindirs})
|
||||
message(STATUS "Copying plugin ${qtplugindir} to ${TARGET_DIR}/${qtplugindir}")
|
||||
file(COPY "@CONAN_BIN_DIRS_QT5-MXE@/../plugins/${qtplugindir}/" DESTINATION "${TARGET_DIR}/${qtplugindir}")
|
||||
endforeach()
|
||||
|
||||
set(qtqmldirs "QtQuick" "QtQuick.2" "QtGraphicalEffects" "QtWebSockets" "QtQml")
|
||||
if(USE_QTWEBKIT)
|
||||
set(qtqmldirs ${qtqmldirs} "QtWebKit" "QtWebChannel")
|
||||
endif()
|
||||
foreach(qtqmldir ${qtqmldirs})
|
||||
message(STATUS "Copying QML dir for ${qtqmldir} to ${TARGET_DIR}/${qtqmldir}")
|
||||
file(COPY "@CONAN_BIN_DIRS_QT5-MXE@/../qml/${qtqmldir}/" DESTINATION "${TARGET_DIR}/${qtqmldir}")
|
||||
endforeach()
|
||||
|
||||
set(deps_qt5 "libpng16-16" "libharfbuzz-0" "zlib1" "libpcre2-16-0"
|
||||
"libpcre-1" "libcrypto-1_1-x64" "libssl-1_1-x64" "libfreetype-6"
|
||||
"libglib-2.0-0" "libstdc++-6" "libbz2" "libintl-8" "libiconv-2"
|
||||
"icuin56" "icuuc56" "icudt56" "libjpeg-9" "libsqlite3-0" "libwebp-5" "libgcc_s_seh-1")
|
||||
set(TOOLCHAIN_BINDIRS "@CONAN_BIN_DIRS_MXETOOLCHAIN-X86_64-W64-MINGW32@")
|
||||
separate_arguments(TOOLCHAIN_BINDIRS)
|
||||
foreach(lib ${deps_qt5})
|
||||
foreach(bindir ${TOOLCHAIN_BINDIRS})
|
||||
set(lib_full_path "${bindir}/${lib}.dll")
|
||||
if(EXISTS "${lib_full_path}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT EXISTS "${lib_full_path}")
|
||||
set(lib_full_path "@CONAN_BIN_DIRS_QT5-MXE@/${lib}.dll")
|
||||
endif()
|
||||
message(STATUS "Copying ${lib_full_path} to ${TARGET_DIR}")
|
||||
file(COPY ${lib_full_path} DESTINATION ${TARGET_DIR})
|
||||
endforeach(lib ${deps_qt5})
|
||||
@@ -0,0 +1,86 @@
|
||||
macro(import_qt_modules)
|
||||
set(REQUIRED_QT_VERSION "5.9.1")
|
||||
|
||||
set(QTCONFIGROOT ${QTROOT}/lib/cmake/Qt5)
|
||||
|
||||
foreach(COMP ${USED_QT_MODULES})
|
||||
set(mod Qt5${COMP})
|
||||
|
||||
# look for the config files in the QtConfigRoot defined above
|
||||
set(${mod}_DIR ${QTCONFIGROOT}${COMP})
|
||||
|
||||
# look for the actual package
|
||||
find_package(${mod} ${REQUIRED_QT_VERSION} REQUIRED)
|
||||
|
||||
#message("${mod}_INCLUDE_DIRS: include_directories(${${mod}_INCLUDE_DIRS})")
|
||||
include_directories(${${mod}_INCLUDE_DIRS})
|
||||
if (${COMP} STREQUAL "Quick")
|
||||
# We need to include the private headers for QZipWriter. If in the future we can't use that class anymore, we can always resort to the QuaZIP OSS library
|
||||
include_directories(${${mod}_PRIVATE_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
list(APPEND QT5_LIBRARIES ${${mod}_LIBRARIES})
|
||||
list(APPEND QT5_CFLAGS ${${mod}_EXECUTABLE_COMPILE_FLAGS})
|
||||
endforeach(COMP ${USED_QT_MODULES})
|
||||
endmacro(import_qt_modules)
|
||||
|
||||
if(WIN32)
|
||||
# Download automatically, you can also just copy the conan.cmake file
|
||||
# TODO: Create packages of qt5 for Linux and MacOS too, so that we can rely strictly on this branch of code
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
|
||||
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/9cc97acda619b7917f140415241785a864482b11/conan.cmake"
|
||||
"${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
endif()
|
||||
|
||||
include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
|
||||
conan_check()
|
||||
|
||||
if(USE_QTWEBKIT)
|
||||
set(_QT_PACKAGE_OPTIONS "qt5-mxe:webkit=True")
|
||||
endif()
|
||||
conan_cmake_run(REQUIRES qt5-mxe/5.11.2@status-im/stable
|
||||
PROFILE ../node_modules/status-conan/profiles/status-mingw32-x86_64
|
||||
SETTINGS "qt5-mxe:os=Windows" "qt5-mxe:arch=x86_64"
|
||||
OPTIONS ${_QT_PACKAGE_OPTIONS}
|
||||
BUILD never)
|
||||
|
||||
set(QTROOT "${CONAN_QT5-MXE_ROOT}")
|
||||
else(WIN32)
|
||||
set(QTROOT "$ENV{QT_PATH}")
|
||||
endif(WIN32)
|
||||
|
||||
if(NOT EXISTS ${QTROOT}/bin/qt.conf)
|
||||
if(EXISTS ${QTROOT}/gcc_64/bin/qt.conf)
|
||||
set(QTROOT "${QTROOT}/gcc_64")
|
||||
elseif(EXISTS ${QTROOT}/clang_64/bin/qt.conf)
|
||||
set(QTROOT "${QTROOT}/clang_64")
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find qt.conf in ${QTROOT}/bin nor in ${QTROOT}/clang_64/bin nor in ${QTROOT}/gcc_64/bin. Is QTROOT correctly defined?")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(WINARCHSTR ARCHSTR windows-x86_64)
|
||||
endif(WIN32)
|
||||
|
||||
message(STATUS "Qt root directory: ${QTROOT}")
|
||||
|
||||
list(APPEND CMAKE_FIND_ROOT_PATH ${QTROOT})
|
||||
list(APPEND CMAKE_PREFIX_PATH ${QTROOT})
|
||||
include_directories(${QTROOT}/include)
|
||||
|
||||
import_qt_modules()
|
||||
|
||||
if(QT5_CFLAGS)
|
||||
list(REMOVE_DUPLICATES QT5_CFLAGS)
|
||||
if(WIN32)
|
||||
list(REMOVE_ITEM QT5_CFLAGS -fPIC)
|
||||
endif(WIN32)
|
||||
endif(QT5_CFLAGS)
|
||||
|
||||
message(STATUS "Qt version: ${Qt5Core_VERSION_STRING}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QT5_CFLAGS}")
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${QT5_LIBRARIES})
|
||||
@@ -0,0 +1,19 @@
|
||||
# Toolchain file for building for Windows from an Ubuntu Linux system.
|
||||
#
|
||||
# Typical usage:
|
||||
# *) install cross compiler: `sudo apt-get install mingw-w64 g++-mingw-w64`
|
||||
# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-Ubuntu-mingw64.cmake ..
|
||||
|
||||
message(STATUS "Cross-compiling for Windows")
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
if(NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
message(FATAL_ERROR "Can only cross-compile to Windows from Linux")
|
||||
endif()
|
||||
|
||||
set(USE_QTWEBKIT OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/toolchain/")
|
||||
include(conanbuildinfo)
|
||||
#conan_basic_setup()
|
||||
conan_global_flags()
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "appconfig.h"
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const QStringList loggingCategories =
|
||||
{"UIManager",
|
||||
"Flexbox",
|
||||
"WebSocketModule",
|
||||
"Networking",
|
||||
"ViewManager",
|
||||
"RCTNotification",
|
||||
"default",
|
||||
"RCTStatus",
|
||||
"jsserver",
|
||||
"status"};
|
||||
|
||||
const QString SETTINGS_GROUP_NAME = "im/status";
|
||||
const QString AppConfig::LOGGING_ENABLED = "logging_enabled";
|
||||
|
||||
Q_LOGGING_CATEGORY(APPCONFIG, "AppConfig")
|
||||
|
||||
AppConfig AppConfig::appConfig;
|
||||
|
||||
AppConfig::AppConfig()
|
||||
: settings("Status.im", "StatusDesktop") {
|
||||
settings.beginGroup(SETTINGS_GROUP_NAME);
|
||||
|
||||
// Set default values
|
||||
if (settings.value(LOGGING_ENABLED).isNull()) {
|
||||
settings.setValue(LOGGING_ENABLED, false);
|
||||
}
|
||||
|
||||
QStringList keys = settings.allKeys();
|
||||
for (int i = 0; i < keys.size(); ++i) {
|
||||
processFx(keys[i], settings.value(keys[i]));
|
||||
}
|
||||
}
|
||||
|
||||
AppConfig& AppConfig::inst() {
|
||||
return appConfig;
|
||||
}
|
||||
|
||||
QVariant AppConfig::getValue(const QString& name) const {
|
||||
return settings.value(name);
|
||||
}
|
||||
|
||||
void AppConfig::setValue(const QString& name, const QVariant& value) {
|
||||
processFx(name, value);
|
||||
settings.setValue(name, value);
|
||||
}
|
||||
|
||||
// This fn is for processing side-effects of a particular value
|
||||
void AppConfig::processFx(const QString& name, const QVariant& value) const {
|
||||
//qCDebug(APPCONFIG) << "### processFx group" << settings.group() << " " << name << ": " << value;
|
||||
if (name == LOGGING_ENABLED) {
|
||||
bool enabled = value.toBool();
|
||||
//qCDebug(APPCONFIG) << "### processFx" << name << ": " << value << ": " << enabled;
|
||||
QLoggingCategory::setFilterRules(getLoggingFilterRules(enabled));
|
||||
}
|
||||
}
|
||||
|
||||
QString AppConfig::getLoggingFilterRules(bool enabled) const {
|
||||
if (enabled) {
|
||||
return "UIManager=false\nFlexbox=false\nViewManager=false\nNetworking=false\nWebSocketModule=false";
|
||||
}
|
||||
else {
|
||||
QString filterRules;
|
||||
for (int i = 0; i < loggingCategories.size(); ++i) {
|
||||
filterRules += (loggingCategories.at(i) + "=false\n");
|
||||
}
|
||||
return filterRules;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef APPCONFIG_H
|
||||
#define APPCONFIG_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <QSettings>
|
||||
|
||||
// This class is intended to store app configuration
|
||||
// modifiable from JS side
|
||||
// Currently, only logging-related settings are here
|
||||
// that are used by react-native-desktop-config module
|
||||
class AppConfig {
|
||||
public:
|
||||
|
||||
static AppConfig& inst();
|
||||
|
||||
QVariant getValue(const QString& name) const;
|
||||
void setValue(const QString& name, const QVariant& value);
|
||||
|
||||
const static QString LOGGING_ENABLED;
|
||||
private:
|
||||
AppConfig();
|
||||
|
||||
static AppConfig appConfig;
|
||||
QSettings settings;
|
||||
|
||||
QString getLoggingFilterRules(bool enabled) const;
|
||||
void processFx(const QString& name, const QVariant& value) const;
|
||||
};
|
||||
#endif // APPCONFIG_H
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
@rem Copyright (c) 2017-present, Status Research and Development GmbH.
|
||||
@rem All rights reserved.
|
||||
@rem
|
||||
@rem This source code is licensed under the BSD-style license found in the
|
||||
@rem LICENSE file in the root directory of this source tree. An additional grant
|
||||
@rem of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
@echo off
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
set "option="
|
||||
for %%a in (%*) do (
|
||||
if not defined option (
|
||||
set arg=%%a
|
||||
if "!arg:~0,1!" equ "-" set "option=!arg!"
|
||||
) else (
|
||||
set "option!option!=%%a"
|
||||
set "option="
|
||||
)
|
||||
)
|
||||
|
||||
SET option
|
||||
@echo on
|
||||
|
||||
echo "build.bat external modules paths: "%option-e%
|
||||
echo "build.bat JS bundle path: "%option-j%
|
||||
echo "build.bat desktop fonts: "%option-f%
|
||||
echo "build.bat desktop images: "%option-i%
|
||||
echo "build.bat cmake generator: "%option-g%
|
||||
|
||||
@rem Workaround
|
||||
@rem rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile
|
||||
|
||||
@rem Build project
|
||||
echo %CD%
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -G %option-g% -DEXTERNAL_MODULES_DIR=%option-e% -DJS_BUNDLE_PATH=%option-j% -DDESKTOP_FONTS=%option-f% -DDESKTOP_IMAGES=%option-i% . && cmake --build .
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (C) 2016, Canonical Ltd.
|
||||
# All rights reserved.
|
||||
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
# XXX: Don't move this script
|
||||
cd $(dirname $0)
|
||||
|
||||
while (( "$#" )); do
|
||||
if [[ $1 == "-e" ]]; then
|
||||
shift
|
||||
ExternalModulesPaths="$1"
|
||||
fi
|
||||
if [[ $1 == "-j" ]]; then
|
||||
shift
|
||||
JsBundlePath="$1"
|
||||
fi
|
||||
if [[ $1 == "-f" ]]; then
|
||||
shift
|
||||
desktopFonts="$1"
|
||||
fi
|
||||
if [[ $1 == "-i" ]]; then
|
||||
shift
|
||||
desktopImages="$1"
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
echo "build.sh external modules paths: "$ExternalModulesPaths
|
||||
echo "build.sh JS bundle path: "$JsBundlePath
|
||||
echo "build.sh desktop fonts: "$desktopFonts
|
||||
echo "build.sh desktop images: "$desktopImages
|
||||
|
||||
# Workaround
|
||||
rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile
|
||||
|
||||
# Build project
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DEXTERNAL_MODULES_DIR="$ExternalModulesPaths" \
|
||||
-DJS_BUNDLE_PATH="$JsBundlePath" \
|
||||
-DDESKTOP_FONTS="$desktopFonts" \
|
||||
-DDESKTOP_IMAGES="$desktopImages" \
|
||||
-DCMAKE_INSTALL_COMPONENT='' \
|
||||
. && \
|
||||
make
|
||||
@@ -0,0 +1,216 @@
|
||||
{
|
||||
"name": "StatusIm-Desktop",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
"prepare": "patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert": "^1.4.1",
|
||||
"bignumber.js": "git+https://github.com/status-im/bignumber.js.git#v4.0.2-status",
|
||||
"buffer": "^3.6.0",
|
||||
"chance": "^1.1.3",
|
||||
"create-react-class": "^15.6.2",
|
||||
"emojilib": "^2.2.9",
|
||||
"eth-phishing-detect": "^1.1.13",
|
||||
"events": "^1.1.1",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"google-breakpad": "git+https://github.com/status-im/google-breakpad.git#v0.9.0",
|
||||
"hi-base32": "^0.5.0",
|
||||
"i18n-js": "^3.5.0",
|
||||
"identicon.js": "git+https://github.com/status-im/identicon.js.git#v1.2.1-status",
|
||||
"metro": "^0.48.1",
|
||||
"nfc-react-native": "git+https://github.com/status-im/nfc-react-native.git#v0.3.8-status",
|
||||
"qrcode": "^1.4.4",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-native": "git+https://github.com/status-im/react-native-desktop.git#v0.57.8_11",
|
||||
"react-native-background-timer": "^2.0.0",
|
||||
"react-native-camera": "^3.9.0",
|
||||
"react-native-config": "git+https://github.com/status-im/react-native-config.git#v0.11.2-status",
|
||||
"react-native-dialogs": "^0.0.20",
|
||||
"react-native-fetch-polyfill": "^1.1.2",
|
||||
"react-native-fs": "git+https://github.com/status-im/react-native-fs.git#v2.9.7-status",
|
||||
"react-native-gesture-handler": "^1.5.0",
|
||||
"react-native-image-crop-picker": "^0.26.1",
|
||||
"react-native-image-resizer": "^1.1.0",
|
||||
"react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#v.3.0.0-4-status",
|
||||
"react-native-languages": "git+https://github.com/status-im/react-native-languages.git#v0.1.1-status",
|
||||
"react-native-navigation-twopane": "git+https://github.com/status-im/react-native-navigation-twopane.git#v0.0.2-status",
|
||||
"react-native-os": "^1.1.0",
|
||||
"react-native-splash-screen": "^3.0.6",
|
||||
"react-native-webview-bridge": "git+https://github.com/status-im/react-native-webview-bridge.git#0.33.16-status-rn049-desktop",
|
||||
"react-navigation": "^3.11.0",
|
||||
"status-conan": "git+https://github.com/status-im/status-conan.git#v1.0.0",
|
||||
"web3-utils": "^1.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.7.2",
|
||||
"@babel/generator": "^7.7.2",
|
||||
"@babel/helper-builder-react-jsx": "^7.7.0",
|
||||
"@babel/plugin-transform-block-scoping": "7.0.0",
|
||||
"@babel/preset-env": "^7.7.1",
|
||||
"@babel/register": "^7.7.0",
|
||||
"babel-preset-react-native": "^5.0.2",
|
||||
"coveralls": "^3.0.7",
|
||||
"metro-react-native-babel-preset": "^0.57.0",
|
||||
"nyc": "^14.1.1",
|
||||
"patch-package": "^5.1.1",
|
||||
"rn-snoopy": "git+https://github.com/status-im/rn-snoopy.git#v2.0.2-status"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"appdmg": "^0.6.0"
|
||||
},
|
||||
"desktopExternalModules": [
|
||||
"node_modules/react-native-languages/desktop",
|
||||
"node_modules/react-native-config/desktop",
|
||||
"node_modules/react-native-fs/desktop",
|
||||
"node_modules/react-native-webview-bridge/desktop",
|
||||
"node_modules/react-native-keychain/desktop",
|
||||
"modules/react-native-status/desktop",
|
||||
"modules/react-native-desktop-linking/desktop",
|
||||
"modules/react-native-desktop-menu/desktop",
|
||||
"modules/react-native-desktop-config/desktop",
|
||||
"modules/react-native-desktop-shortcuts/desktop",
|
||||
"modules/react-native-desktop-notification/desktop",
|
||||
"modules/react-native-desktop-gesture-handler/desktop",
|
||||
"node_modules/google-breakpad"
|
||||
],
|
||||
"desktopFonts": [
|
||||
"../../../../../resources/fonts/Inter-BlackItalic.otf",
|
||||
"../../../../../resources/fonts/Inter-Black.otf",
|
||||
"../../../../../resources/fonts/Inter-BoldItalic.otf",
|
||||
"../../../../../resources/fonts/Inter-Bold.otf",
|
||||
"../../../../../resources/fonts/Inter-ExtraBoldItalic.otf",
|
||||
"../../../../../resources/fonts/Inter-ExtraBold.otf",
|
||||
"../../../../../resources/fonts/Inter-ExtraLight-BETA.otf",
|
||||
"../../../../../resources/fonts/Inter-ExtraLightItalic-BETA.otf",
|
||||
"../../../../../resources/fonts/Inter-Italic.otf",
|
||||
"../../../../../resources/fonts/Inter-Light-BETA.otf",
|
||||
"../../../../../resources/fonts/Inter-LightItalic-BETA.otf",
|
||||
"../../../../../resources/fonts/Inter-MediumItalic.otf",
|
||||
"../../../../../resources/fonts/Inter-Medium.otf",
|
||||
"../../../../../resources/fonts/Inter-Regular.otf",
|
||||
"../../../../../resources/fonts/Inter-SemiBoldItalic.otf",
|
||||
"../../../../../resources/fonts/Inter-SemiBold.otf",
|
||||
"../../../../../resources/fonts/Inter-Thin-BETA.otf",
|
||||
"../../../../../resources/fonts/Inter-ThinItalic-BETA.otf"
|
||||
],
|
||||
"desktopImages": [
|
||||
"../../../../../desktop/resources/add.png",
|
||||
"../../../../../desktop/resources/address.png",
|
||||
"../../../../../desktop/resources/add_contact.png",
|
||||
"../../../../../desktop/resources/arrow_left.png",
|
||||
"../../../../../desktop/resources/arrow_right.png",
|
||||
"../../../../../desktop/resources/arrow_up.png",
|
||||
"../../../../../desktop/resources/back.png",
|
||||
"../../../../../desktop/resources/backspace.png",
|
||||
"../../../../../desktop/resources/bell.png",
|
||||
"../../../../../desktop/resources/browser.png",
|
||||
"../../../../../desktop/resources/camera.png",
|
||||
"../../../../../desktop/resources/cancel.png",
|
||||
"../../../../../desktop/resources/change.png",
|
||||
"../../../../../desktop/resources/check.png",
|
||||
"../../../../../desktop/resources/close.png",
|
||||
"../../../../../desktop/resources/commands.png",
|
||||
"../../../../../desktop/resources/copy.png",
|
||||
"../../../../../desktop/resources/corner_left_bottom.png",
|
||||
"../../../../../desktop/resources/corner_left_top.png",
|
||||
"../../../../../desktop/resources/corner_right_bottom.png",
|
||||
"../../../../../desktop/resources/corner_right_top.png",
|
||||
"../../../../../desktop/resources/dapp.png",
|
||||
"../../../../../desktop/resources/delete.png",
|
||||
"../../../../../desktop/resources/desktop.png",
|
||||
"../../../../../desktop/resources/download.png",
|
||||
"../../../../../desktop/resources/dropdown.png",
|
||||
"../../../../../desktop/resources/dropdown_up.png",
|
||||
"../../../../../desktop/resources/edit.png",
|
||||
"../../../../../desktop/resources/filter.png",
|
||||
"../../../../../desktop/resources/fingerprint.png",
|
||||
"../../../../../desktop/resources/flash.png",
|
||||
"../../../../../desktop/resources/flash_active.png",
|
||||
"../../../../../desktop/resources/group_chat.png",
|
||||
"../../../../../desktop/resources/help.png",
|
||||
"../../../../../desktop/resources/history.png",
|
||||
"../../../../../desktop/resources/home.png",
|
||||
"../../../../../desktop/resources/home_1.png",
|
||||
"../../../../../desktop/resources/icon_action_back.png",
|
||||
"../../../../../desktop/resources/icon_action_forward.png",
|
||||
"../../../../../desktop/resources/icon_action_fullscreen_collapse.png",
|
||||
"../../../../../desktop/resources/icon_action_fullscreen_expand.png",
|
||||
"../../../../../desktop/resources/icon_arrow_top.png",
|
||||
"../../../../../desktop/resources/icon_avatar.png",
|
||||
"../../../../../desktop/resources/icon_check_on.png",
|
||||
"../../../../../desktop/resources/icon_close_light_gray.png",
|
||||
"../../../../../desktop/resources/icon_forward_gray.png",
|
||||
"../../../../../desktop/resources/icon_lock_gray.png",
|
||||
"../../../../../desktop/resources/icon_lock_white.png",
|
||||
"../../../../../desktop/resources/icon_menu_group.png",
|
||||
"../../../../../desktop/resources/icon_money_white.png",
|
||||
"../../../../../desktop/resources/icon_muted.png",
|
||||
"../../../../../desktop/resources/icon_notifications_on.png",
|
||||
"../../../../../desktop/resources/icon_phone_white.png",
|
||||
"../../../../../desktop/resources/ic_background.png",
|
||||
"../../../../../desktop/resources/ic_foreground.png",
|
||||
"../../../../../desktop/resources/ic_stat_status_notification.png",
|
||||
"../../../../../desktop/resources/info.png",
|
||||
"../../../../../desktop/resources/in_contacts.png",
|
||||
"../../../../../desktop/resources/keycard.png",
|
||||
"../../../../../desktop/resources/keycard_logo.png",
|
||||
"../../../../../desktop/resources/language.png",
|
||||
"../../../../../desktop/resources/launch_logo.png",
|
||||
"../../../../../desktop/resources/link.png",
|
||||
"../../../../../desktop/resources/logo.png",
|
||||
"../../../../../desktop/resources/log_out.png",
|
||||
"../../../../../desktop/resources/mailserver.png",
|
||||
"../../../../../desktop/resources/make_admin.png",
|
||||
"../../../../../desktop/resources/max.png",
|
||||
"../../../../../desktop/resources/message.png",
|
||||
"../../../../../desktop/resources/mobile.png",
|
||||
"../../../../../desktop/resources/more.png",
|
||||
"../../../../../desktop/resources/network.png",
|
||||
"../../../../../desktop/resources/next.png",
|
||||
"../../../../../desktop/resources/notification.png",
|
||||
"../../../../../desktop/resources/one_on_one_chat.png",
|
||||
"../../../../../desktop/resources/password.png",
|
||||
"../../../../../desktop/resources/paste.png",
|
||||
"../../../../../desktop/resources/photo.png",
|
||||
"../../../../../desktop/resources/profile.png",
|
||||
"../../../../../desktop/resources/public_chat.png",
|
||||
"../../../../../desktop/resources/qr.png",
|
||||
"../../../../../desktop/resources/receive.png",
|
||||
"../../../../../desktop/resources/refresh.png",
|
||||
"../../../../../desktop/resources/remove_contact.png",
|
||||
"../../../../../desktop/resources/reply.png",
|
||||
"../../../../../desktop/resources/rotate_camera.png",
|
||||
"../../../../../desktop/resources/search.png",
|
||||
"../../../../../desktop/resources/security.png",
|
||||
"../../../../../desktop/resources/send.png",
|
||||
"../../../../../desktop/resources/settings.png",
|
||||
"../../../../../desktop/resources/settings_advanced.png",
|
||||
"../../../../../desktop/resources/share.png",
|
||||
"../../../../../desktop/resources/stickers.png",
|
||||
"../../../../../desktop/resources/text.png",
|
||||
"../../../../../desktop/resources/tiny_arrow_down.png",
|
||||
"../../../../../desktop/resources/tiny_check.png",
|
||||
"../../../../../desktop/resources/tiny_clear.png",
|
||||
"../../../../../desktop/resources/tiny_edit.png",
|
||||
"../../../../../desktop/resources/tiny_external.png",
|
||||
"../../../../../desktop/resources/tiny_group.png",
|
||||
"../../../../../desktop/resources/tiny_lock.png",
|
||||
"../../../../../desktop/resources/tiny_lock_broken.png",
|
||||
"../../../../../desktop/resources/tiny_new_contact.png",
|
||||
"../../../../../desktop/resources/tiny_pending.png",
|
||||
"../../../../../desktop/resources/tiny_public.png",
|
||||
"../../../../../desktop/resources/tiny_settings.png",
|
||||
"../../../../../desktop/resources/tiny_tribute_to_talk.png",
|
||||
"../../../../../desktop/resources/tribute_to_talk.png",
|
||||
"../../../../../desktop/resources/two_arrows.png",
|
||||
"../../../../../desktop/resources/username.png",
|
||||
"../../../../../desktop/resources/user_profile.png",
|
||||
"../../../../../desktop/resources/user_profile_1.png",
|
||||
"../../../../../desktop/resources/wallet.png",
|
||||
"../../../../../desktop/resources/warning.png"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,545 @@
|
||||
/**
|
||||
* Copyright (C) 2016, Canonical Ltd.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
// #define BUILD_FOR_BUNDLE
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFontDatabase>
|
||||
#include <QApplication>
|
||||
#include <QMutexLocker>
|
||||
#include <QProcess>
|
||||
#include <QQuickView>
|
||||
#include <QStandardPaths>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
|
||||
#include "attachedproperties.h"
|
||||
#include "reactitem.h"
|
||||
#include "rootview.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "exceptionglobalhandler.h"
|
||||
|
||||
#include "appconfig.h"
|
||||
Q_DECLARE_LOGGING_CATEGORY(JSSERVER)
|
||||
Q_DECLARE_LOGGING_CATEGORY(STATUS)
|
||||
Q_LOGGING_CATEGORY(JSSERVER, "jsserver")
|
||||
Q_LOGGING_CATEGORY(STATUS, "status")
|
||||
|
||||
static QStringList consoleOutputStrings;
|
||||
static QMutex consoleOutputMutex;
|
||||
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
bool nodeJsServerStarted = false;
|
||||
QProcess *g_nodeJsServerProcess = nullptr;
|
||||
#define NODEJS_SERVER_NAME "ubuntu-server"
|
||||
#endif
|
||||
|
||||
const int MAIN_WINDOW_WIDTH = 1024;
|
||||
const int MAIN_WINDOW_HEIGHT = 768;
|
||||
const QString CRASH_REPORT_EXECUTABLE = QStringLiteral("reportApp");
|
||||
|
||||
const char *ENABLE_LOG_FILE_ENV_VAR_NAME = "STATUS_LOG_FILE_ENABLED";
|
||||
const char *LOG_FILE_PATH_ENV_VAR_NAME = "STATUS_LOG_PATH";
|
||||
|
||||
// TODO: some way to change while running
|
||||
class ReactNativeProperties : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(
|
||||
bool liveReload READ liveReload WRITE setLiveReload NOTIFY liveReloadChanged)
|
||||
Q_PROPERTY(
|
||||
QUrl codeLocation READ codeLocation WRITE setCodeLocation NOTIFY codeLocationChanged)
|
||||
Q_PROPERTY(
|
||||
QString pluginsPath READ pluginsPath WRITE setPluginsPath NOTIFY pluginsPathChanged)
|
||||
Q_PROPERTY(
|
||||
QString executor READ executor WRITE setExecutor NOTIFY executorChanged)
|
||||
Q_PROPERTY(
|
||||
QVariantMap initialProps READ initialProps WRITE setInitialProps NOTIFY initialPropsChanged)
|
||||
public:
|
||||
ReactNativeProperties(QObject *parent = nullptr) : QObject(parent) {
|
||||
m_codeLocation = m_packagerTemplate.arg(m_packagerHost).arg(m_packagerPort);
|
||||
}
|
||||
bool liveReload() const { return m_liveReload; }
|
||||
void setLiveReload(bool liveReload) {
|
||||
if (m_liveReload == liveReload)
|
||||
return;
|
||||
m_liveReload = liveReload;
|
||||
Q_EMIT liveReloadChanged();
|
||||
}
|
||||
QUrl codeLocation() const { return m_codeLocation; }
|
||||
void setCodeLocation(const QUrl &codeLocation) {
|
||||
if (m_codeLocation == codeLocation)
|
||||
return;
|
||||
m_codeLocation = codeLocation;
|
||||
Q_EMIT codeLocationChanged();
|
||||
}
|
||||
QString pluginsPath() const { return m_pluginsPath; }
|
||||
void setPluginsPath(const QString &pluginsPath) {
|
||||
if (m_pluginsPath == pluginsPath)
|
||||
return;
|
||||
m_pluginsPath = pluginsPath;
|
||||
Q_EMIT pluginsPathChanged();
|
||||
}
|
||||
QString executor() const { return m_executor; }
|
||||
void setExecutor(const QString &executor) {
|
||||
if (m_executor == executor)
|
||||
return;
|
||||
m_executor = executor;
|
||||
Q_EMIT executorChanged();
|
||||
}
|
||||
QVariantMap initialProps() const { return m_initialProps; }
|
||||
void setInitialProps(const QVariantMap &initialProps) {
|
||||
if (m_initialProps == initialProps)
|
||||
return;
|
||||
m_initialProps = initialProps;
|
||||
Q_EMIT initialPropsChanged();
|
||||
}
|
||||
|
||||
QString packagerHost() const { return m_packagerHost; }
|
||||
void setPackagerHost(const QString &packagerHost) {
|
||||
if (m_packagerHost == packagerHost)
|
||||
return;
|
||||
m_packagerHost = packagerHost;
|
||||
setCodeLocation(m_packagerTemplate.arg(m_packagerHost).arg(m_packagerPort));
|
||||
}
|
||||
QString packagerPort() const { return m_packagerPort; }
|
||||
void setPackagerPort(const QString &packagerPort) {
|
||||
if (m_packagerPort == packagerPort)
|
||||
return;
|
||||
m_packagerPort = packagerPort;
|
||||
setCodeLocation(m_packagerTemplate.arg(m_packagerHost).arg(m_packagerPort));
|
||||
}
|
||||
void setLocalSource(const QString &source) {
|
||||
if (m_localSource == source)
|
||||
return;
|
||||
|
||||
// overrides packager*
|
||||
if (source.startsWith("file:")) {
|
||||
setCodeLocation(source);
|
||||
} else {
|
||||
QFileInfo fi(source);
|
||||
if (!fi.exists()) {
|
||||
qCWarning(STATUS) << "Attempt to set non-existent local source file";
|
||||
return;
|
||||
}
|
||||
setCodeLocation(QUrl::fromLocalFile(fi.absoluteFilePath()));
|
||||
setLiveReload(false);
|
||||
}
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void liveReloadChanged();
|
||||
void codeLocationChanged();
|
||||
void pluginsPathChanged();
|
||||
void executorChanged();
|
||||
void initialPropsChanged();
|
||||
|
||||
private:
|
||||
bool m_liveReload = false;
|
||||
QString m_packagerHost = "localhost";
|
||||
QString m_packagerPort = "8081";
|
||||
QString m_localSource;
|
||||
QString m_packagerTemplate =
|
||||
"http://%1:%2/index.desktop.bundle?platform=desktop&dev=true";
|
||||
QUrl m_codeLocation;
|
||||
QString m_pluginsPath;
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
QString m_executor = "RemoteServerConnection";
|
||||
#else
|
||||
QString m_executor = "LocalServerConnection";
|
||||
#endif
|
||||
QVariantMap m_initialProps;
|
||||
};
|
||||
|
||||
void saveMessage(QtMsgType type, const QMessageLogContext &context,
|
||||
const QString &msg);
|
||||
void writeLogsToFile();
|
||||
void writeLogFromJSServer(const QString &msg);
|
||||
void writeSingleLineLogFromJSServer(const QString &msg);
|
||||
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
|
||||
void killZombieJsServer();
|
||||
bool runNodeJsServer();
|
||||
|
||||
#endif
|
||||
|
||||
void loadFontsFromResources() {
|
||||
QDirIterator it(":", QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
QString resourceFile = it.next();
|
||||
if (resourceFile.endsWith(".otf", Qt::CaseInsensitive) ||
|
||||
resourceFile.endsWith(".ttf", Qt::CaseInsensitive)) {
|
||||
qint32 fontId = QFontDatabase::addApplicationFont(resourceFile);
|
||||
if (Q_UNLIKELY(fontId == -1)) {
|
||||
qCDebug(STATUS) << "Unable to install font" << resourceFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void exceptionPostHandledCallback() {
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
if (g_nodeJsServerProcess) {
|
||||
g_nodeJsServerProcess->kill();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool redirectLogIntoFile() {
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
return true;
|
||||
#else
|
||||
return qEnvironmentVariable(ENABLE_LOG_FILE_ENV_VAR_NAME, "") ==
|
||||
QStringLiteral("1");
|
||||
#endif
|
||||
}
|
||||
|
||||
QString getDataStoragePath() {
|
||||
QString statusDataDir = qgetenv("STATUS_DATA_DIR");
|
||||
QString dataStoragePath;
|
||||
if (!statusDataDir.isEmpty()) {
|
||||
dataStoragePath = statusDataDir;
|
||||
} else {
|
||||
dataStoragePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
|
||||
}
|
||||
QDir dir(dataStoragePath);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
return dataStoragePath;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QCoreApplication::setApplicationName("Status");
|
||||
|
||||
// Init AppConfig
|
||||
AppConfig::inst().getValue(AppConfig::LOGGING_ENABLED);
|
||||
|
||||
QString appPath = QCoreApplication::applicationDirPath();
|
||||
QString dataStoragePath = getDataStoragePath();
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
if (qgetenv("STATUS_DATA_DIR").isEmpty()) {
|
||||
killZombieJsServer();
|
||||
}
|
||||
#else
|
||||
dataStoragePath = "";
|
||||
#endif
|
||||
|
||||
ExceptionGlobalHandler exceptionHandler(
|
||||
appPath + QDir::separator() + CRASH_REPORT_EXECUTABLE,
|
||||
exceptionPostHandledCallback, dataStoragePath);
|
||||
|
||||
Q_INIT_RESOURCE(react_resources);
|
||||
|
||||
loadFontsFromResources();
|
||||
if (redirectLogIntoFile()) {
|
||||
qInstallMessageHandler(saveMessage);
|
||||
}
|
||||
|
||||
//qCDebug(STATUS) << "###STATUS_NO_LOGGING";
|
||||
|
||||
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
if (!runNodeJsServer()) {
|
||||
if (g_nodeJsServerProcess->state() == QProcess::NotRunning) {
|
||||
// If we failed to start the Node.js server (happens on Windows if the Node.js server process was previously running), let's do a final attempt
|
||||
delete g_nodeJsServerProcess;
|
||||
if (!runNodeJsServer()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.setWindowIcon(QIcon(":/icon.png"));
|
||||
#endif
|
||||
|
||||
QQuickView view;
|
||||
ReactNativeProperties *rnp = new ReactNativeProperties(&view);
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
QVariantMap initialProps;
|
||||
QString statusNodePort = env.value("STATUS_NODE_PORT");
|
||||
QString statusDataDir = env.value("STATUS_DATA_DIR");
|
||||
if (!statusNodePort.isEmpty()) {
|
||||
initialProps["STATUS_NODE_PORT"] = statusNodePort;
|
||||
}
|
||||
if (!statusDataDir.isEmpty()) {
|
||||
initialProps["STATUS_DATA_DIR"] = statusDataDir;
|
||||
}
|
||||
|
||||
rnp->setInitialProps(initialProps);
|
||||
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
rnp->setCodeLocation("file:" + QGuiApplication::applicationDirPath() +
|
||||
"/assets");
|
||||
#endif
|
||||
|
||||
utilities::registerReactTypes();
|
||||
|
||||
QCommandLineParser p;
|
||||
p.setApplicationDescription("React Native host application");
|
||||
p.addHelpOption();
|
||||
p.addOptions({
|
||||
{{"R", "live-reload"}, "Enable live reload."},
|
||||
{{"H", "host"}, "Set packager host address.", rnp->packagerHost()},
|
||||
{{"P", "port"}, "Set packager port number.", rnp->packagerPort()},
|
||||
{{"L", "local"}, "Set path to the local packaged source", "not set"},
|
||||
{{"M", "plugins-path"}, "Set path to node modules", "./plugins"},
|
||||
{{"E", "executor"}, "Set Javascript executor", rnp->executor()},
|
||||
});
|
||||
p.process(app);
|
||||
rnp->setLiveReload(p.isSet("live-reload"));
|
||||
if (p.isSet("host"))
|
||||
rnp->setPackagerHost(p.value("host"));
|
||||
if (p.isSet("port"))
|
||||
rnp->setPackagerPort(p.value("port"));
|
||||
if (p.isSet("local"))
|
||||
rnp->setLocalSource(p.value("local"));
|
||||
if (p.isSet("plugins-path"))
|
||||
rnp->setPluginsPath(p.value("plugins-path"));
|
||||
if (p.isSet("executor"))
|
||||
rnp->setExecutor(p.value("executor"));
|
||||
|
||||
view.rootContext()->setContextProperty("ReactNativeProperties", rnp);
|
||||
view.setSource(QUrl("qrc:///main.qml"));
|
||||
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
view.resize(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT);
|
||||
view.show();
|
||||
|
||||
QTimer flushLogsToFileTimer;
|
||||
if (redirectLogIntoFile()) {
|
||||
flushLogsToFileTimer.setInterval(500);
|
||||
QObject::connect(&flushLogsToFileTimer, &QTimer::timeout,
|
||||
[=]() { writeLogsToFile(); });
|
||||
flushLogsToFileTimer.start();
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
QString getLogFilePath() {
|
||||
QString logFilePath;
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
logFilePath = getDataStoragePath() + QDir::separator() + "Status.log";
|
||||
#else
|
||||
logFilePath = qEnvironmentVariable(LOG_FILE_PATH_ENV_VAR_NAME, "");
|
||||
if (logFilePath.isEmpty()) {
|
||||
logFilePath = getDataStoragePath() + QDir::separator() + "StatusDev.log";
|
||||
}
|
||||
#endif
|
||||
return logFilePath;
|
||||
}
|
||||
|
||||
void writeLogsToFile() {
|
||||
QMutexLocker locker(&consoleOutputMutex);
|
||||
if(consoleOutputStrings.isEmpty())
|
||||
return;
|
||||
|
||||
QFile logFile(getLogFilePath());
|
||||
if (logFile.open(QIODevice::WriteOnly | QIODevice::Append)) {
|
||||
for (QString message : consoleOutputStrings) {
|
||||
logFile.write(message.toStdString().c_str());
|
||||
}
|
||||
consoleOutputStrings.clear();
|
||||
|
||||
logFile.flush();
|
||||
logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BUILD_FOR_BUNDLE
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
bool IsProcessRunning(const wchar_t *processName) {
|
||||
bool exists = false;
|
||||
PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
|
||||
|
||||
HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (snapshot != NULL) {
|
||||
if (::Process32First(snapshot, &entry)) {
|
||||
do {
|
||||
if (!wcsicmp(entry.szExeFile, processName)) {
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
} while (::Process32Next(snapshot, &entry));
|
||||
}
|
||||
|
||||
::CloseHandle(snapshot);
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void killZombieJsServer() {
|
||||
// Ensure that a zombie Node.js server process is not still running in the background before we spawn a new one
|
||||
QString cmd;
|
||||
#ifdef Q_OS_LINUX
|
||||
cmd = QString("pkill -f %1").arg(NODEJS_SERVER_NAME);
|
||||
#elif defined(Q_OS_MAC)
|
||||
cmd = QString("killall -9 %1").arg(NODEJS_SERVER_NAME);
|
||||
#elif defined(Q_OS_WIN)
|
||||
#define _CAT(A, B) A##B
|
||||
#define _W(A) _CAT(L, #A)
|
||||
WCHAR exeName[_MAX_PATH];
|
||||
wsprintf(exeName, L"%s.exe", _W(NODEJS_SERVER_NAME));
|
||||
if (IsProcessRunning(exeName)) {
|
||||
qCDebug(STATUS) << NODEJS_SERVER_NAME << "is running, killing it";
|
||||
::ShellExecuteW(NULL, NULL, L"tskill", _W(NODEJS_SERVER_NAME), NULL, SW_HIDE);
|
||||
} else {
|
||||
qCDebug(STATUS) << NODEJS_SERVER_NAME << "is not running";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!cmd.isEmpty()) {
|
||||
qCDebug(STATUS) << "Running " << cmd;
|
||||
QByteArray cmdArray = cmd.toLocal8Bit();
|
||||
system(cmdArray.data());
|
||||
}
|
||||
}
|
||||
|
||||
bool runNodeJsServer() {
|
||||
g_nodeJsServerProcess = new QProcess();
|
||||
g_nodeJsServerProcess->setWorkingDirectory(getDataStoragePath());
|
||||
g_nodeJsServerProcess->setProgram(QGuiApplication::applicationDirPath() + QDir::separator() + NODEJS_SERVER_NAME);
|
||||
QString port = qgetenv("REACT_SERVER_PORT");
|
||||
if (!port.isEmpty()) {
|
||||
QStringList arguments = (QStringList() << "--port" << port);
|
||||
g_nodeJsServerProcess->setArguments(arguments);
|
||||
}
|
||||
QObject::connect(g_nodeJsServerProcess, &QProcess::errorOccurred,
|
||||
[=](QProcess::ProcessError) {
|
||||
qCWarning(JSSERVER) << "process name: "
|
||||
<< qUtf8Printable(g_nodeJsServerProcess->program());
|
||||
qCWarning(JSSERVER) << "process error: "
|
||||
<< qUtf8Printable(g_nodeJsServerProcess->errorString());
|
||||
});
|
||||
|
||||
QObject::connect(
|
||||
g_nodeJsServerProcess, &QProcess::readyReadStandardOutput, [=] {
|
||||
writeLogFromJSServer(g_nodeJsServerProcess->readAllStandardOutput().trimmed());
|
||||
});
|
||||
QObject::connect(
|
||||
g_nodeJsServerProcess, &QProcess::readyReadStandardError, [=] {
|
||||
QString output =
|
||||
g_nodeJsServerProcess->readAllStandardError().trimmed();
|
||||
writeLogFromJSServer(output);
|
||||
if (output.contains("Server starting")) {
|
||||
nodeJsServerStarted = true;
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(QGuiApplication::instance(), &QCoreApplication::aboutToQuit,
|
||||
[=]() {
|
||||
qCDebug(STATUS) << "Kill node.js server process";
|
||||
g_nodeJsServerProcess->kill();
|
||||
});
|
||||
|
||||
qCDebug(STATUS) << "starting node.js server process...";
|
||||
g_nodeJsServerProcess->start();
|
||||
qCDebug(STATUS) << "wait for started...";
|
||||
|
||||
if (g_nodeJsServerProcess->waitForReadyRead(10000)) {
|
||||
// We know that the process started, now wait until it communicates that it has started
|
||||
while (!nodeJsServerStarted) {
|
||||
QGuiApplication::processEvents();
|
||||
}
|
||||
qCDebug(STATUS) << "waiting finished";
|
||||
|
||||
return true;
|
||||
} else {
|
||||
qCDebug(STATUS) << "failed to start process";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void writeLogFromJSServer(const QString &msg) {
|
||||
if (msg.contains("\\n")) {
|
||||
QStringList lines = msg.split("\\n");
|
||||
foreach (const QString &line, lines) {
|
||||
writeSingleLineLogFromJSServer(line);
|
||||
}
|
||||
} else {
|
||||
writeSingleLineLogFromJSServer(msg);
|
||||
}
|
||||
}
|
||||
|
||||
QString extractJSServerMessage(const QString& msg, int prefixLength) {
|
||||
return msg.mid(prefixLength);
|
||||
}
|
||||
|
||||
void writeSingleLineLogFromJSServer(const QString &msg) {
|
||||
if (msg.startsWith("TRACE "))
|
||||
qCDebug(JSSERVER) << qUtf8Printable(extractJSServerMessage(msg, 6));
|
||||
else if (msg.startsWith("DEBUG "))
|
||||
qCDebug(JSSERVER) << qUtf8Printable(extractJSServerMessage(msg, 6));
|
||||
else if (msg.startsWith("INFO "))
|
||||
qCInfo(JSSERVER) << qUtf8Printable(extractJSServerMessage(msg, 5));
|
||||
else if (msg.startsWith("WARN "))
|
||||
qCWarning(JSSERVER) << qUtf8Printable(extractJSServerMessage(msg, 5));
|
||||
else if (msg.startsWith("ERROR "))
|
||||
qCWarning(JSSERVER) << qUtf8Printable(extractJSServerMessage(msg, 6));
|
||||
else if (msg.startsWith("FATAL "))
|
||||
qCCritical(JSSERVER) << qUtf8Printable(extractJSServerMessage(msg, 6));
|
||||
else
|
||||
qCDebug(JSSERVER) << qUtf8Printable(msg);
|
||||
}
|
||||
|
||||
void appendConsoleString(const QString &msg) {
|
||||
QMutexLocker locker(&consoleOutputMutex);
|
||||
consoleOutputStrings << msg;
|
||||
}
|
||||
|
||||
void saveMessage(QtMsgType type, const QMessageLogContext &context,
|
||||
const QString &msg) {
|
||||
|
||||
Q_UNUSED(context);
|
||||
QByteArray localMsg = msg.toLocal8Bit();
|
||||
QString message = localMsg + "\n";
|
||||
QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
|
||||
QString typeStr;
|
||||
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
typeStr = "D";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
typeStr = "I";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
typeStr = "W";
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
typeStr = "C";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
typeStr = "F";
|
||||
}
|
||||
appendConsoleString(QString("%1 - %2 - [%3] - %4").arg(timestamp, typeStr, context.category, message));
|
||||
if (type == QtFatalMsg) {
|
||||
writeLogsToFile();
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#include "main.moc"
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Copyright (c) 2017-present, Status Research and Development GmbH.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under the BSD-style license found in the
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(APP_NAME "reportApp")
|
||||
|
||||
set(MAIN_CPP_SOURCE reportpublisher.cpp
|
||||
main.cpp)
|
||||
|
||||
add_executable(
|
||||
${APP_NAME}
|
||||
${MAIN_CPP_SOURCE}
|
||||
main.qrc
|
||||
)
|
||||
|
||||
set(USED_QT_MODULES Core Qml Quick WebSockets Widgets Svg)
|
||||
|
||||
qt5_use_modules(${APP_NAME} ${USED_QT_MODULES})
|
||||
|
||||
set(REACT_NATIVE_DESKTOP_EXTERNAL_PROJECT_DEPS ${REACT_NATIVE_DESKTOP_EXTERNAL_PROJECT_DEPS} reportApp PARENT_SCOPE)
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Status Research and Development GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlContext>
|
||||
#include <QQuickView>
|
||||
|
||||
#include "reportpublisher.h"
|
||||
|
||||
const int MAIN_WINDOW_WIDTH = 1024;
|
||||
const int MAIN_WINDOW_HEIGHT = 768;
|
||||
const int INPUT_ARGUMENTS_COUNT = 6;
|
||||
|
||||
const int MINIDUMP_FILE_PATH_ARG_INDEX = 1;
|
||||
const int CRASHED_EXECUTABLE_PATH_ARG_INDEX = 2;
|
||||
const int LOGS_PATH_INDEX = 5;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
if (argc != INPUT_ARGUMENTS_COUNT) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
app.setApplicationName("Crash Report");
|
||||
|
||||
ReportPublisher reportPublisher(argv[MINIDUMP_FILE_PATH_ARG_INDEX],
|
||||
argv[CRASHED_EXECUTABLE_PATH_ARG_INDEX],
|
||||
argv[LOGS_PATH_INDEX]);
|
||||
|
||||
QQuickView view;
|
||||
view.rootContext()->setContextProperty("reportPublisher", &reportPublisher);
|
||||
view.setSource(QUrl("qrc:///main.qml"));
|
||||
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
view.resize(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT);
|
||||
view.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Status Research and Development GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: 384
|
||||
height: 640
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: "Oh, no! Status application just crashed!"
|
||||
font.bold: true
|
||||
font.pointSize: 25
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 20
|
||||
text: "Please report us <b>crash.dmp</b> and <b>Status</b> executable files to allow us fix the issue!"
|
||||
font.bold: true
|
||||
font.pointSize: 20
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 40
|
||||
spacing: 25
|
||||
|
||||
Button {
|
||||
Layout.minimumWidth: 150
|
||||
text: "Report (highly appreciated)"
|
||||
onClicked: reportPublisher.submit()
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Restart and Quit"
|
||||
onClicked: reportPublisher.restartAndQuit()
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Just Quit"
|
||||
onClicked: reportPublisher.quit()
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 100
|
||||
|
||||
TextEdit {
|
||||
readOnly: true
|
||||
Layout.maximumWidth: 500
|
||||
wrapMode: TextEdit.Wrap
|
||||
selectByMouse: true
|
||||
font.pointSize: 12
|
||||
textFormat: TextEdit.RichText
|
||||
text: "<div>Please upload both <b>crash.dmp</b> and <b>Status</b> executable files from the report directory:<br>" + reportPublisher.resolveDataStoragePath() + "</div>"
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "View"
|
||||
onClicked: reportPublisher.showDirectory()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>main.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Status Research and Development GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "reportpublisher.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QUrl>
|
||||
|
||||
const QString REPORT_SUBMIT_URL =
|
||||
QStringLiteral("https://goo.gl/forms/0705ZN0EMW3xLDpI2");
|
||||
|
||||
ReportPublisher::ReportPublisher(QString minidumpFilePath,
|
||||
QString crashedExecutablePath,
|
||||
QString logsPath, QObject *parent)
|
||||
: QObject(parent), m_minidumpFilePath(minidumpFilePath),
|
||||
m_logsPath(logsPath), m_crashedExecutablePath(crashedExecutablePath) {}
|
||||
|
||||
void ReportPublisher::submit() {
|
||||
QDesktopServices::openUrl(QUrl(REPORT_SUBMIT_URL));
|
||||
showDirectory();
|
||||
}
|
||||
|
||||
void ReportPublisher::restartAndQuit() {
|
||||
QString appPath = m_crashedExecutablePath;
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
|
||||
QFileInfo crashedExecutableFileInfo(m_crashedExecutablePath);
|
||||
QString fullPath = crashedExecutableFileInfo.dir().absolutePath();
|
||||
#ifdef Q_OS_MACOS
|
||||
const QString bundleExtension = QStringLiteral(".app");
|
||||
const QString cmdTemplate = QStringLiteral("open \"%1\"");
|
||||
#else
|
||||
const QString bundleExtension = QStringLiteral(".AppImage");
|
||||
const QString cmdTemplate = QStringLiteral("\"%1\"");
|
||||
#endif
|
||||
if (fullPath.contains(bundleExtension)) {
|
||||
appPath = fullPath.left(fullPath.indexOf(bundleExtension) +
|
||||
bundleExtension.size());
|
||||
}
|
||||
QString cmd = QString(cmdTemplate).arg(appPath);
|
||||
#else
|
||||
QString cmd = QString("\"%1\"").arg(appPath);;
|
||||
#endif
|
||||
|
||||
QProcess::startDetached(cmd);
|
||||
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
void ReportPublisher::quit() { qApp->quit(); }
|
||||
|
||||
void ReportPublisher::showDirectory() {
|
||||
QString dataStoragePath = resolveDataStoragePath();
|
||||
if (!m_logFilesPrepared) {
|
||||
m_logFilesPrepared = prepareReportFiles(dataStoragePath);
|
||||
}
|
||||
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(dataStoragePath));
|
||||
}
|
||||
|
||||
bool ReportPublisher::prepareReportFiles(QString reportDirPath) {
|
||||
QFileInfo minidumpFileInfo(m_minidumpFilePath);
|
||||
QFileInfo crashedExecutableFileInfo(m_crashedExecutablePath);
|
||||
if (!minidumpFileInfo.exists() || !crashedExecutableFileInfo.exists())
|
||||
return false;
|
||||
|
||||
return QFile::copy(m_minidumpFilePath,
|
||||
reportDirPath + QDir::separator() + "crash.dmp") &&
|
||||
QFile::copy(m_crashedExecutablePath,
|
||||
reportDirPath + QDir::separator() +
|
||||
crashedExecutableFileInfo.fileName()) &&
|
||||
prepareLogFiles(reportDirPath);
|
||||
}
|
||||
|
||||
bool ReportPublisher::prepareLogFiles(QString reportDirPath) {
|
||||
if (reportDirPath.isEmpty())
|
||||
return true;
|
||||
|
||||
QDirIterator filesIterator(m_logsPath, QStringList() << "*.log", QDir::Files);
|
||||
while (filesIterator.hasNext()) {
|
||||
QFileInfo logFile(filesIterator.next());
|
||||
QFile::copy(logFile.absoluteFilePath(),
|
||||
reportDirPath + QDir::separator() + logFile.fileName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ReportPublisher::resolveDataStoragePath() {
|
||||
QFileInfo minidumpFileInfo(m_minidumpFilePath);
|
||||
QString dataStoragePath =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
|
||||
QDir::separator() + minidumpFileInfo.baseName();
|
||||
QDir dir(dataStoragePath);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
return dir.path();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Status Research and Development GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef REPORTPUBLISHER
|
||||
#define REPORTPUBLISHER
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class ReportPublisher : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ReportPublisher(QString minidumpFilePath, QString crashedExecutablePath,
|
||||
QString logsPath, QObject *parent = 0);
|
||||
|
||||
Q_INVOKABLE void submit();
|
||||
Q_INVOKABLE void restartAndQuit();
|
||||
Q_INVOKABLE void quit();
|
||||
Q_INVOKABLE void showDirectory();
|
||||
Q_INVOKABLE QString resolveDataStoragePath();
|
||||
|
||||
private:
|
||||
bool prepareReportFiles(QString reportDirPath);
|
||||
bool prepareLogFiles(QString reportDirPath);
|
||||
|
||||
QString m_minidumpFilePath;
|
||||
QString m_crashedExecutablePath;
|
||||
QString m_logsPath;
|
||||
bool m_logFilesPrepared = false;
|
||||
};
|
||||
|
||||
#endif // REPORTPUBLISHER
|
||||
|
After Width: | Height: | Size: 132 B |
|
After Width: | Height: | Size: 317 B |
|
After Width: | Height: | Size: 142 B |
|
After Width: | Height: | Size: 155 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 167 B |