Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff6cb2292d | ||
|
|
25727bc281 | ||
|
|
00d63edf93 | ||
|
|
67ceb74c6e | ||
|
|
4aa90f2b9b | ||
|
|
51ce235948 | ||
|
|
cf63839a86 | ||
|
|
4904e923a5 | ||
|
|
427d9f05a1 | ||
|
|
de4e73a256 | ||
|
|
c9308af4d8 | ||
|
|
4f120d99f7 | ||
|
|
cc70a7e8da | ||
|
|
aebe68fa1a | ||
|
|
d68b757589 | ||
|
|
28a2bca012 | ||
|
|
23af624305 | ||
|
|
035e07f7be | ||
|
|
0a9919c991 | ||
|
|
c94977c8d3 | ||
|
|
ae411a432f | ||
|
|
5307fdfbce | ||
|
|
7046543533 | ||
|
|
c9e6f0aff7 | ||
|
|
7a89b2852a | ||
|
|
a5a00e0a2c | ||
|
|
e11385e350 | ||
|
|
1b43e4c16b | ||
|
|
5c8a8e83ac | ||
|
|
64580f0ad1 | ||
|
|
435c6a7943 | ||
|
|
a1a64ce5f4 | ||
|
|
75c5a13d7b | ||
|
|
6424c59c8b | ||
|
|
a9c580e82c | ||
|
|
453c1bf824 | ||
|
|
ea3735d938 | ||
|
|
45dae49fc0 | ||
|
|
e813d1e4e4 | ||
|
|
fee6864d56 | ||
|
|
962d0fb6cd | ||
|
|
c41727c1b3 | ||
|
|
966b6e5a33 | ||
|
|
461b6cdb74 | ||
|
|
8b9a245f54 | ||
|
|
8b4bc0290a | ||
|
|
0cc7ec92bd | ||
|
|
55a955d8dd | ||
|
|
19fdced2bc | ||
|
|
47eb863a3c | ||
|
|
5b1e0b3bdf | ||
|
|
901f091929 | ||
|
|
c2d129d04e | ||
|
|
a914334fed | ||
|
|
749faaeb1b | ||
|
|
5ddd605328 | ||
|
|
9df455088e | ||
|
|
14d1a6cfb2 | ||
|
|
e7a213fe95 | ||
|
|
5eea4ba218 | ||
|
|
9b6e7cad6d | ||
|
|
efab1d30ed | ||
|
|
151b6a3cbf | ||
|
|
71ab9c9d9d | ||
|
|
45b296a2c5 | ||
|
|
f1e83158d9 | ||
|
|
ff9cd359e9 | ||
|
|
e5dbac877e | ||
|
|
c47aca0ddb | ||
|
|
b344322475 | ||
|
|
430a8fb27c | ||
|
|
3d1a1c5be9 | ||
|
|
fd0a328106 | ||
|
|
9243daa405 | ||
|
|
f75cb14588 | ||
|
|
12bcd79c2c | ||
|
|
9e5cc74ea9 | ||
|
|
49fd306f25 | ||
|
|
fc1bc48fdc | ||
|
|
c5ec451692 | ||
|
|
97a953cc64 | ||
|
|
dcca501b0a | ||
|
|
2f53c7f914 | ||
|
|
2122c5518f | ||
|
|
5fab3268bd | ||
|
|
fb86b4d367 | ||
|
|
5a955cd4d2 | ||
|
|
a7c2ecda42 | ||
|
|
a090a059ec | ||
|
|
68f0a02cbc | ||
|
|
a447bed4ac | ||
|
|
efc2fa9cf2 | ||
|
|
3760d2a2e5 | ||
|
|
c9cdd48849 | ||
|
|
cda7564bbe | ||
|
|
81070f07b0 | ||
|
|
dd7b3c21ae | ||
|
|
0306f1cfbd | ||
|
|
5809cba0df | ||
|
|
85d0022b26 | ||
|
|
86d85df5d3 | ||
|
|
b6e0bb0a0e | ||
|
|
2272fafc05 | ||
|
|
1e44b433c5 | ||
|
|
2f446a73bb | ||
|
|
53883e4be1 | ||
|
|
fadda87ac2 | ||
|
|
9496bfa2a8 | ||
|
|
cd02175144 | ||
|
|
ed8b5b265b | ||
|
|
ebf2600fdc | ||
|
|
d24f4690b8 | ||
|
|
d2478bbd34 | ||
|
|
4a7c03b1cc | ||
|
|
8aff7f487d | ||
|
|
a2b2f55996 | ||
|
|
009ea990bc | ||
|
|
d823a2082a | ||
|
|
61d465a343 | ||
|
|
947b1c2b2e | ||
|
|
2f412d95ee | ||
|
|
eb5fe57e90 | ||
|
|
10fab4e77c | ||
|
|
619e176087 | ||
|
|
b8861c6c14 | ||
|
|
3cf282e75a | ||
|
|
4f95e0bcf4 | ||
|
|
c4a7849c9d | ||
|
|
4e567cf782 | ||
|
|
826b7df982 | ||
|
|
cc520a1f27 | ||
|
|
c2e195979c | ||
|
|
9594bb49e2 | ||
|
|
51c80a8f8e | ||
|
|
8b3c7f29b2 | ||
|
|
9b1150df29 | ||
|
|
de53581ef4 | ||
|
|
efa420def4 | ||
|
|
5f2b29ee52 | ||
|
|
696ebbf67e | ||
|
|
cfe25b8b45 | ||
|
|
6d3ef2282f | ||
|
|
5301d421f2 | ||
|
|
4d0fd4389e | ||
|
|
f5488e1f61 | ||
|
|
0e4c7a23bf | ||
|
|
7b7f567361 | ||
|
|
f645d3fbb5 | ||
|
|
a79a72fccb | ||
|
|
c9486dc634 | ||
|
|
d64ba1b540 | ||
|
|
87ce82e10a | ||
|
|
6a9eef1c2a | ||
|
|
8ac20b442e | ||
|
|
f9af0825ce | ||
|
|
001264bd1a | ||
|
|
de8d109ba1 | ||
|
|
3ad9cfa269 | ||
|
|
8abea59196 | ||
|
|
89535ea8fc | ||
|
|
cb78293db7 | ||
|
|
988a7f6b0c | ||
|
|
490c8f8776 | ||
|
|
8c23975ad7 | ||
|
|
a76a4f6878 | ||
|
|
21ef5a68b8 | ||
|
|
c9d1adbc27 | ||
|
|
bca946aa78 | ||
|
|
1c81d6e190 | ||
|
|
8d95515480 | ||
|
|
6e3784d671 | ||
|
|
17e5fc4dd4 | ||
|
|
999bb9940e | ||
|
|
9f2e2f9d3e | ||
|
|
ff1022f337 | ||
|
|
f18e7d746b | ||
|
|
9a713148c7 | ||
|
|
e5f7a94ee2 | ||
|
|
59184b12d0 | ||
|
|
807c8377d4 | ||
|
|
46bd2b2e4c | ||
|
|
eb1cc65a3d | ||
|
|
7485093398 | ||
|
|
90bae33689 | ||
|
|
b8c7e44326 | ||
|
|
81c4d16f9f | ||
|
|
40c12241e0 | ||
|
|
8ffbf61b79 | ||
|
|
7ff412722d | ||
|
|
505ef626cc | ||
|
|
a2af83f034 | ||
|
|
705b80ef8f | ||
|
|
3d52d1cb9c | ||
|
|
965dce053d | ||
|
|
3f6051c22b | ||
|
|
b30d002efb | ||
|
|
4734a4ee04 | ||
|
|
d281c560dc | ||
|
|
e6c859dd2d | ||
|
|
553f2c0e01 | ||
|
|
dc0d0b59cb | ||
|
|
13c7f06317 | ||
|
|
1ea49a80fc | ||
|
|
c1eb98691c | ||
|
|
ff41394d9e | ||
|
|
0a7dc8fdd2 | ||
|
|
b2a70c8331 | ||
|
|
481092dd25 | ||
|
|
671e5f4540 | ||
|
|
39ea685adc | ||
|
|
8a612a3807 | ||
|
|
3d4ee8fe6a | ||
|
|
06025ce26f | ||
|
|
25fd297573 | ||
|
|
7c5decbbfc | ||
|
|
dcfac1c4e2 | ||
|
|
f9c15be1d4 | ||
|
|
27a001b0f0 | ||
|
|
b1ec418133 | ||
|
|
76f9703afe | ||
|
|
6ad84f4232 | ||
|
|
ef49699222 | ||
|
|
e0bafb842e | ||
|
|
6e9292c1e1 | ||
|
|
c1245d7b1d | ||
|
|
785f829554 | ||
|
|
47732e7b5b | ||
|
|
b2feca723c | ||
|
|
cc3ae6c693 | ||
|
|
b41df2f2fc | ||
|
|
58afae07ba | ||
|
|
6ff878c836 | ||
|
|
128f44f58b | ||
|
|
9fb513cea0 | ||
|
|
a64eb79065 | ||
|
|
9dfb908678 | ||
|
|
028543aa31 | ||
|
|
60af04ff06 | ||
|
|
5203fc6fd8 | ||
|
|
238b559981 | ||
|
|
33abdf559a | ||
|
|
14242a7877 | ||
|
|
81d2c35f4d | ||
|
|
a8c39370d5 | ||
|
|
ea02f8e3cf | ||
|
|
5a64745fce | ||
|
|
30545f77d2 | ||
|
|
19f92413de | ||
|
|
c91fe5fa82 |
@@ -22,3 +22,5 @@ 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
|
||||
@@ -5,6 +5,7 @@ ETHEREUM_DEV_CLUSTER=1
|
||||
EXTENSIONS=0
|
||||
FLEET=eth.prod
|
||||
GROUP_CHATS_ENABLED=1
|
||||
HARDWALLET_ENABLED=1
|
||||
LOG_LEVEL_STATUS_GO=info
|
||||
LOG_LEVEL=debug
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=0
|
||||
@@ -20,3 +21,6 @@ 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
|
||||
@@ -4,7 +4,7 @@ ERC20_CONTRACT_WARNINGS=0
|
||||
ETHEREUM_DEV_CLUSTER=0
|
||||
EXTENSIONS=0
|
||||
FLEET=eth.prod
|
||||
GROUP_CHATS_ENABLED=0
|
||||
GROUP_CHATS_ENABLED=1
|
||||
LOG_LEVEL_STATUS_GO=
|
||||
LOG_LEVEL=info
|
||||
MAILSERVER_CONFIRMATIONS_ENABLED=1
|
||||
|
||||
@@ -11,7 +11,7 @@ These are just guidelines, not rules. Use your best judgment, and feel free to p
|
||||
* [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://get.status.im/chat/public/status-core-dev)
|
||||
* [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/build_status)
|
||||
* [Find issues to work on](https://github.com/status-im/)
|
||||
|
||||
@@ -183,3 +183,5 @@ status-modules/resources
|
||||
/fiddle/node_modules/
|
||||
/fiddle/target/
|
||||
/fiddle/resources/public/images/
|
||||
|
||||
trace.edn
|
||||
@@ -16,7 +16,7 @@ RESET := $(shell tput -Txterm sgr0)
|
||||
HELP_FUN = \
|
||||
%help; \
|
||||
while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \
|
||||
print "Usage: make [target]\n\n"; \
|
||||
print "Usage: make [target]\n\nSee STARTING_GUIDE.md for more info.\n\n"; \
|
||||
for (sort keys %help) { \
|
||||
print "${WHITE}$$_:${RESET}\n"; \
|
||||
for (@{$$help{$$_}}) { \
|
||||
@@ -47,6 +47,12 @@ ifdef TARGET_OS
|
||||
export TARGET ?= $(TARGET_OS)
|
||||
endif
|
||||
|
||||
# Useful for checking if we are on NixOS
|
||||
OS_NAME := $(shell [ -f /etc/os-release ] && awk -F= '/^NAME/{print $2}' /etc/os-release)
|
||||
|
||||
# Useful for Andoird release builds
|
||||
TMP_BUILD_NUMBER := $(shell ./scripts/version/gen_build_no.sh | cut -c1-10)
|
||||
|
||||
# MacOS root is read-only, read nix/README.md for details
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
@@ -80,11 +86,15 @@ nix-clean: ##@nix Remove all status-react build artifacts from /nix/store
|
||||
|
||||
nix-purge: SHELL := /bin/sh
|
||||
nix-purge: ##@nix Completely remove the complete Nix setup
|
||||
ifeq ($(OS_NAME), NixOS)
|
||||
$(error $(RED)You should not purge Nix files on NixOS!$(RESET))
|
||||
else
|
||||
sudo rm -rf $(_NIX_ROOT)/* ~/.nix-profile ~/.nix-defexpr ~/.nix-channels ~/.cache/nix ~/.status .nix-gcroots
|
||||
endif
|
||||
|
||||
nix-add-gcroots: export TARGET := default
|
||||
nix-add-gcroots: ##@nix Add Nix GC roots to avoid status-react expressions being garbage collected
|
||||
scripts/add-nix-gcroots.sh
|
||||
nix/scripts/gcroots.sh
|
||||
|
||||
nix-update-gradle: ##@nix Update maven nix expressions based on current gradle setup
|
||||
nix/mobile/android/maven-and-npm-deps/maven/generate-nix.sh
|
||||
@@ -145,19 +155,24 @@ update-fleets: ##@prepare Download up-to-date JSON file with current fleets stat
|
||||
| jq --indent 4 --sort-keys . \
|
||||
> resources/config/fleets.json
|
||||
|
||||
keystore: export TARGET := keytool
|
||||
keystore: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
|
||||
keystore: ##@prepare Generate a Keystore for signing Android APKs
|
||||
@./scripts/generate-keystore.sh
|
||||
|
||||
#----------------
|
||||
# Release builds
|
||||
#----------------
|
||||
release: release-android release-ios ##@build build release for Android and iOS
|
||||
|
||||
release-android: export TARGET ?= android
|
||||
release-android: export TARGET := android
|
||||
release-android: export BUILD_ENV ?= prod
|
||||
release-android: export BUILD_TYPE ?= nightly
|
||||
release-android: export BUILD_NUMBER ?= 9999
|
||||
release-android: export STORE_FILE ?= $(HOME)/.gradle/status-im.keystore
|
||||
release-android: export BUILD_NUMBER ?= $(TMP_BUILD_NUMBER)
|
||||
release-android: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
|
||||
release-android: export ANDROID_ABI_SPLIT ?= false
|
||||
release-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
|
||||
release-android: ##@build build release for Android
|
||||
release-android: keystore ##@build build release for Android
|
||||
scripts/release-android.sh
|
||||
|
||||
release-ios: export TARGET ?= ios
|
||||
@@ -215,7 +230,7 @@ jsbundle-desktop: ##@jsbundle Compile JavaScript and Clojure into index.desktop.
|
||||
node prepare-modules.js
|
||||
|
||||
#--------------
|
||||
# REPL
|
||||
# Clojure REPL
|
||||
# -------------
|
||||
|
||||
_watch-%: ##@watch Start development for device
|
||||
@@ -224,22 +239,18 @@ _watch-%: ##@watch Start development for device
|
||||
clj -R:dev build.clj watch --platform $(SYSTEM) --$(SYSTEM)-device $(DEVICE)
|
||||
|
||||
watch-ios-real: export TARGET := ios
|
||||
watch-ios-real: _watch-ios-real ##@watch Start development for iOS real device
|
||||
|
||||
watch-ios-real: _watch-ios-real
|
||||
watch-ios-simulator: export TARGET := ios
|
||||
watch-ios-simulator: _watch-ios-simulator ##@watch Start development for iOS simulator
|
||||
|
||||
watch-ios-simulator: _watch-ios-simulator
|
||||
watch-android-real: export TARGET := android
|
||||
watch-android-real: _watch-android-real ##@watch Start development for Android real device
|
||||
|
||||
watch-android-real: _watch-android-real
|
||||
watch-android-avd: export TARGET := android
|
||||
watch-android-avd: _watch-android-avd ##@watch Start development for Android AVD
|
||||
|
||||
watch-android-avd: _watch-android-avd
|
||||
watch-android-genymotion: export TARGET ?= android
|
||||
watch-android-genymotion: _watch-android-genymotion ##@watch Start development for Android Genymotion
|
||||
watch-android-genymotion: _watch-android-genymotion
|
||||
|
||||
watch-desktop: export TARGET ?= $(HOST_OS)
|
||||
watch-desktop: ##@watch Start development for Desktop
|
||||
watch-desktop:
|
||||
clj -R:dev build.clj watch --platform desktop
|
||||
|
||||
desktop-server: export TARGET ?= $(HOST_OS)
|
||||
@@ -247,15 +258,15 @@ desktop-server:
|
||||
node ubuntu-server.js
|
||||
|
||||
#--------------
|
||||
# Run
|
||||
# -------------
|
||||
# Run React-Native app
|
||||
#--------------
|
||||
_run-%:
|
||||
$(eval SYSTEM := $(word 2, $(subst -, , $@)))
|
||||
npx react-native run-$(SYSTEM)
|
||||
|
||||
# TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix
|
||||
run-android: export TARGET := android
|
||||
run-android: ##@run Run Android build
|
||||
run-android: ##@run Build Android APK and start it on the device
|
||||
npx react-native run-android --appIdSuffix debug
|
||||
|
||||
run-desktop: export TARGET ?= $(HOST_OS)
|
||||
@@ -263,7 +274,7 @@ run-desktop: _run-desktop ##@run Run Desktop build
|
||||
|
||||
SIMULATOR=
|
||||
run-ios: export TARGET := ios
|
||||
run-ios: ##@run Run iOS build
|
||||
run-ios: ##@run Build iOS app and start it in a simulator/device
|
||||
ifneq ("$(SIMULATOR)", "")
|
||||
npx react-native run-ios --simulator="$(SIMULATOR)"
|
||||
else
|
||||
@@ -311,7 +322,7 @@ react-native-ios: export _NIX_PURE ?= true
|
||||
react-native-ios: ##@other Start react native packager for Android client
|
||||
@scripts/start-react-native.sh
|
||||
|
||||
geth-connect: export TARGET := adb
|
||||
geth-connect: export TARGET := android-env
|
||||
geth-connect: ##@other Connect to Geth on the device
|
||||
adb forward tcp:8545 tcp:8545 && \
|
||||
build/bin/geth attach http://localhost:8545
|
||||
@@ -320,22 +331,22 @@ android-clean: ##@prepare Clean Gradle state
|
||||
git clean -dxf -f ./android/app/build
|
||||
[ -d android/.gradle ] && cd android && ./gradlew clean
|
||||
|
||||
android-ports: export TARGET := adb
|
||||
android-ports: export TARGET := android-env
|
||||
android-ports: ##@other Add proxies to Android Device/Simulator
|
||||
adb reverse tcp:8081 tcp:8081 && \
|
||||
adb reverse tcp:3449 tcp:3449 && \
|
||||
adb reverse tcp:4567 tcp:4567 && \
|
||||
adb forward tcp:5561 tcp:5561
|
||||
|
||||
android-devices: export TARGET := adb
|
||||
android-devices: export TARGET := android-env
|
||||
android-devices: ##@other Invoke adb devices
|
||||
adb devices
|
||||
|
||||
android-logcat: export TARGET := adb
|
||||
android-logcat: export TARGET := android-env
|
||||
android-logcat: ##@other Read status-react logs from Android phone using adb
|
||||
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
|
||||
|
||||
android-install: export TARGET := adb
|
||||
android-install: export TARGET := android-env
|
||||
android-install: export BUILD_TYPE ?= release
|
||||
android-install:
|
||||
adb install result/app-$(BUILD_TYPE).apk
|
||||
@@ -362,13 +373,19 @@ _startdev-%:
|
||||
|
||||
startdev-android-avd: export TARGET = android
|
||||
startdev-android-avd: _startdev-android-avd
|
||||
startdev-android-avd: ##@startdev Compile Clojure for Android AVD
|
||||
startdev-android-genymotion: export TARGET = android
|
||||
startdev-android-genymotion: _startdev-android-genymotion
|
||||
startdev-android-genymotion: ##@startdev Compile Clojure for Genymotion
|
||||
startdev-android-real: export TARGET = android
|
||||
startdev-android-real: _startdev-android-real
|
||||
startdev-desktop: export TARGET ?= $(HOST_OS)
|
||||
startdev-desktop: _startdev-desktop
|
||||
startdev-android-real: ##@startdev Compile Clojure for Android real device
|
||||
startdev-ios-real: export TARGET = ios
|
||||
startdev-ios-real: _startdev-ios-real
|
||||
startdev-ios-real: ##@startdev Compile Clojure for iOS device
|
||||
startdev-ios-simulator: export TARGET = ios
|
||||
startdev-ios-simulator: _startdev-ios-simulator
|
||||
startdev-ios-simulator: ##@startdev Compile Clojure for iOS simulator
|
||||
|
||||
startdev-desktop: export TARGET ?= $(HOST_OS)
|
||||
startdev-desktop: _startdev-desktop
|
||||
|
||||
@@ -17,7 +17,7 @@ If this interests you, **help us make Status a reality** - anyone can contribute
|
||||
|
||||
## How to Contribute?
|
||||
|
||||
Go straight to the [docs](https://status.im/docs) or [join our chat](http://get.status.im/chat/public/status) and choose what interests you:
|
||||
Go straight to the [docs](https://status.im/docs) or [join our chat](https://join.status.im/chat/public/status) and choose what interests you:
|
||||
|
||||
- **Developer**
|
||||
Developers are the heart of software and to keep Status beating we need all the help we can get! If you're looking to code in ClojureScript or Golang then Status is the project for you! We use React Native and there is even some Java/Objective-C too!
|
||||
@@ -30,16 +30,16 @@ Metcalfe's law states that the value of a network is proportional to the square
|
||||
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.
|
||||
|
||||
- **Blog Writing**
|
||||
Content is King, keeping our blog up to date and informing the community of news helps keep everyone on the same page. [Jump into our chat](http://get.status.im/chat/public/status) and discuss with the team how you can contribute!
|
||||
Content is King, keeping our blog up to date and informing the community of news helps keep everyone on the same page. [Jump into our chat](https://join.status.im/chat/public/status) and discuss with the team how you can contribute!
|
||||
|
||||
- **Testers**
|
||||
It's bug hunting season! Status is currently in Alpha and there is sure to be a bunch of learning, [build status from scratch](https://status.im/build_status/) or if an android user check out our [nightly builds](https://status.im/nightly). You can shake your phone to submit bug reports, or start browsing our [Github Issues](http://github.com/status-im/status-react/issues). Every bug you find brings Status closer to stable, usable software for everyone to enjoy!
|
||||
It's bug hunting season! Status is currently in Alpha and there is sure to be a bunch of learning, [build status from scratch](https://status.im/build_status/) or if an android user check out our [nightly builds](https://status.im/nightly). You can shake your phone to submit bug reports, or start browsing our [Github Issues](https://github.com/status-im/status-react/issues). Every bug you find brings Status closer to stable, usable software for everyone to enjoy!
|
||||
|
||||
- **Security**
|
||||
Status is a visual interface to make permanent changes on the Blockchain, it handles crypto-tokens that have real value and allows 3rd party code execution. Security is paramount to its success. You are given permission to break Status as hard as you can, as long as you share your findings with the community!
|
||||
|
||||
- **Evangelism**
|
||||
Help us spread the word! Tell a friend *right now*, in fact tell **everyone** - yell from a mountain if you have to, every person counts! If you've got a great story to tell or have some interesting way you've spread the word about Status let us know about it in our [chat](https://get.status.im/chat/public/status)
|
||||
Help us spread the word! Tell a friend *right now*, in fact tell **everyone** - yell from a mountain if you have to, every person counts! If you've got a great story to tell or have some interesting way you've spread the word about Status let us know about it in our [chat](https://join.status.im/chat/public/status)
|
||||
|
||||
## Status API
|
||||
View our [API Docs](https://status.im/developer_tools/status_web_api.html) and learn how to integrate your DApp into Status. You can read more about how to add your DApp to Status [here](https://status.im/developer_tools/add_your_dapp.html).
|
||||
@@ -57,7 +57,7 @@ Without the dedication of these outstanding individuals, Status would not exist.
|
||||
|
||||
## Contact us
|
||||
|
||||
Feel free to email us at [support@status.im](mailto:support@status.im) or better yet, [join our chat](http://get.status.im/chat/public/status).
|
||||
Feel free to email us at [support@status.im](mailto:support@status.im) or better yet, [join our chat](https://join.status.im/chat/public/status).
|
||||
|
||||
## License
|
||||
|
||||
@@ -67,4 +67,4 @@ Licensed under the [Mozilla Public License v2.0](https://github.com/status-im/st
|
||||
|
||||
[](https://www.browserstack.com/automate/public-build/SFBWQ3k5R2tnT2t6UGsxU1h1U0g3VFlCNnoxVTRHYWNoTDhsb1laaTJZWT0tLUZMUm5sSVFBSU9qSWM1RUJvK1I3Z3c9PQ==--ad15ae7992b432b33743749d40318952415bd98f)
|
||||
|
||||
[](https://coveralls.io/github/status-im/status-react)
|
||||
[](https://coveralls.io/github/status-im/status-react)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Description
|
||||
|
||||
This document provides information on how to start developing Status App.
|
||||
|
||||
# Getting Started
|
||||
|
||||
To start developing start a shell for platform you are interested in.
|
||||
```
|
||||
make shell TARGET=android
|
||||
```
|
||||
This step will take a while the first time as it will download all dependencies.
|
||||
|
||||
To build the app, your can simply run on of the following:
|
||||
```
|
||||
make release-android
|
||||
make release-ios
|
||||
```
|
||||
For more `make` targets run `make help`.
|
||||
|
||||
# Development
|
||||
|
||||
There are three steps necessary to start development, in this case for Android:
|
||||
|
||||
1. `make startdev-android-real` - Compiles Clojure into JavaScript for real device
|
||||
2. `make react-native-android` - Watches JavaScript code and updates the App
|
||||
3. `make run-android` - Builds the Android app and starts it on the device
|
||||
|
||||
The first two will continue watching for changes and keep re-building the app.
|
||||
The last one will exit once the app is up and ready.
|
||||
|
||||
# Manual Steps
|
||||
|
||||
There are a few manual steps you might want to do in order to start contributing.
|
||||
|
||||
## Genymotion Virtualization
|
||||
|
||||
Optionally set up Genymotion if you don't want to use Android Virtual Device:
|
||||
|
||||
https://www.genymotion.com
|
||||
|
||||
## Android Development Environment
|
||||
|
||||
You can also setup Android Development Environment + Simulator:
|
||||
|
||||
https://facebook.github.io/react-native/docs/getting-started.html
|
||||
|
||||
## Configure GitHub Account
|
||||
|
||||
The optimal way of pushing to GitHubis using SSH instead of user/pass auth.
|
||||
|
||||
It's recommented that you [add your public SSH key to your GitHub account](https://help.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account).
|
||||
|
||||
## Configure GPG Keys for signing commits
|
||||
|
||||
In order to increase security we require all commits in `status-react` repo to be signed with a GPG key.
|
||||
|
||||
Steps:
|
||||
1. [Generate a new GPG key](https://help.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key)
|
||||
2. [Setup Git to use your GPG key](https://help.github.com/en/github/authenticating-to-github/telling-git-about-your-signing-key)
|
||||
3. [Setup Git to sign commits](https://help.github.com/en/github/authenticating-to-github/signing-commits)
|
||||
4. [Setup GitHub to validate commits](https://help.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account)
|
||||
@@ -219,10 +219,10 @@ android {
|
||||
}
|
||||
release {
|
||||
/* environment variables take precedence over gradle.properties file */
|
||||
storeFile file(getEnvOrConfig('STATUS_RELEASE_STORE_FILE').replaceAll("~", System.properties['user.home']))
|
||||
storePassword getEnvOrConfig('STATUS_RELEASE_STORE_PASSWORD')
|
||||
keyAlias getEnvOrConfig('STATUS_RELEASE_KEY_ALIAS')
|
||||
keyPassword getEnvOrConfig('STATUS_RELEASE_KEY_PASSWORD')
|
||||
storeFile file(getEnvOrConfig('KEYSTORE_PATH').replaceAll("~", System.properties['user.home']))
|
||||
storePassword getEnvOrConfig('KEYSTORE_PASSWORD')
|
||||
keyAlias getEnvOrConfig('KEYSTORE_ALIAS')
|
||||
keyPassword getEnvOrConfig('KEYSTORE_KEY_PASSWORD')
|
||||
}
|
||||
}
|
||||
splits {
|
||||
@@ -244,7 +244,6 @@ android {
|
||||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
// see https://facebook.github.io/react-native/docs/signed-apk-android.
|
||||
signingConfig signingConfigs.debug
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
signingConfig signingConfigs.release
|
||||
@@ -268,8 +267,7 @@ android {
|
||||
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
|
||||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
|
||||
output.versionCodeOverride = versionCodes.get(abi) + defaultConfig.versionCode
|
||||
}
|
||||
|
||||
}
|
||||
@@ -298,6 +296,10 @@ dependencies {
|
||||
implementation jscFlavor
|
||||
}
|
||||
|
||||
// react-native-screens
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
|
||||
|
||||
implementation 'androidx.multidex:multidex:2.0.1' // only needed if minSdkVersion is less than 21 (https://developer.android.com/studio/build/multidex)
|
||||
implementation project(':react-native-dialogs')
|
||||
// Force using exact RN version instead of relying on gradle dependency resolution
|
||||
@@ -305,29 +307,40 @@ dependencies {
|
||||
// NOTE: Uncomment if building RN from a fork
|
||||
//compile ("com.facebook.react:react-native:0.55.4") { force = true } // From node_modules
|
||||
implementation project(':react-native-status')
|
||||
implementation project(':react-native-webview-bridge')
|
||||
implementation project(':react-native-status-keycard')
|
||||
implementation 'com.github.status-im:function:0.0.1'
|
||||
implementation 'com.facebook.fresco:fresco:2.0.0'
|
||||
implementation 'com.facebook.fresco:animated-gif:2.0.0'
|
||||
}
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
// puts all compile dependencies into folder libs for BUCK to use
|
||||
|
||||
task hemroidBuild(type: Exec) {
|
||||
def getLocalNDKDir = { ->
|
||||
def rootDir = project.rootDir
|
||||
def localProperties = new File(rootDir, "local.properties")
|
||||
|
||||
def ndkDir = System.env.ANDROID_NDK
|
||||
if (localProperties.exists()) {
|
||||
Properties properties = new Properties()
|
||||
localProperties.withInputStream { instr ->
|
||||
properties.load(instr)
|
||||
}
|
||||
ndkDir = properties.getProperty('ndk.dir')
|
||||
if (!localProperties.exists()) {
|
||||
return null
|
||||
}
|
||||
executable "$ndkDir/ndk-build"
|
||||
Properties properties = new Properties()
|
||||
localProperties.withInputStream { instr ->
|
||||
properties.load(instr)
|
||||
}
|
||||
return properties.getProperty('ndk.dir')
|
||||
}
|
||||
|
||||
// Run this once to be able to run the application with BUCK
|
||||
// puts all compile dependencies into folder libs for BUCK to use
|
||||
task hemroidBuild(type: Exec) {
|
||||
def localNdkDir = getLocalNDKDir()
|
||||
def ndkDir = System.env.ANDROID_NDK
|
||||
if (localNdkDir != null) {
|
||||
ndkDir = localNdkDir
|
||||
}
|
||||
|
||||
def execPath = "$ndkDir/ndk-build"
|
||||
def exec = new File(execPath)
|
||||
if (!exec.exists()) {
|
||||
throw new GradleException("No ndk-build binary found!")
|
||||
}
|
||||
executable execPath
|
||||
}
|
||||
|
||||
preBuild.dependsOn hemroidBuild
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
|
||||
<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"/>
|
||||
@@ -39,7 +41,7 @@
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||
android:resizeableActivity="false"
|
||||
android:launchMode="singleTask">
|
||||
<intent-filter>
|
||||
@@ -57,8 +59,8 @@
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="http" android:host="get.status.im" />
|
||||
<data android:scheme="https" android:host="get.status.im" />
|
||||
<data android:scheme="http" android:host="join.status.im" />
|
||||
<data android:scheme="https" android:host="join.status.im" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@@ -108,6 +108,17 @@ public class MainActivity extends ReactFragmentActivity
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
|
||||
case Configuration.UI_MODE_NIGHT_YES:
|
||||
setTheme(R.style.DarkTheme);
|
||||
|
||||
break;
|
||||
case Configuration.UI_MODE_NIGHT_NO:
|
||||
setTheme(R.style.LightTheme);
|
||||
break;
|
||||
default:
|
||||
setTheme(R.style.LightTheme);
|
||||
}
|
||||
// Make sure we get an Alert for every uncaught exceptions
|
||||
registerUncaughtExceptionHandler(MainActivity.this);
|
||||
|
||||
@@ -117,7 +128,8 @@ public class MainActivity extends ReactFragmentActivity
|
||||
|
||||
setSecureFlag();
|
||||
SplashScreen.show(this, true);
|
||||
super.onCreate(savedInstanceState);
|
||||
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
|
||||
super.onCreate(null);
|
||||
|
||||
if (!shouldShowRootedNotification()) {
|
||||
configureStatus();
|
||||
@@ -229,10 +241,6 @@ public class MainActivity extends ReactFragmentActivity
|
||||
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
mPermissionListener = null;
|
||||
}
|
||||
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
// Permission has been granted. Start camera preview Activity.
|
||||
com.github.alinz.reactnativewebviewbridge.WebViewBridgeManager.grantAccess(requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.github.alinz.reactnativewebviewbridge.WebViewBridgePackage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -33,7 +32,6 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
||||
packages.add(statusPackage);
|
||||
packages.add(new ReactNativeDialogsPackage());
|
||||
packages.add(new RNStatusKeycardPackage());
|
||||
packages.add(new WebViewBridgePackage(BuildConfig.DEBUG_WEBVIEW == "1"));
|
||||
return packages;
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 202 B |
|
After Width: | Height: | Size: 694 B |
|
After Width: | Height: | Size: 202 B |
|
After Width: | Height: | Size: 598 B |
|
After Width: | Height: | Size: 940 B |
|
Before Width: | Height: | Size: 163 B After Width: | Height: | Size: 319 B |
|
After Width: | Height: | Size: 518 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 286 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 380 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 886 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 439 B |
@@ -3,7 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background">
|
||||
android:background="?attr/backgroundColor">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<resources>
|
||||
<color name="primary">#4360df</color>
|
||||
<color name="primary_dark">#FFFFFF</color>
|
||||
<color name="accent">#5c6bc0</color>
|
||||
<color name="background">#FFFFFF</color>
|
||||
</resources>
|
||||
@@ -1,13 +1,20 @@
|
||||
<resources>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primary_dark</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
|
||||
<item name="colorControlNormal">@color/primary</item>
|
||||
<item name="colorControlActivated">@color/primary</item>
|
||||
<item name="android:windowBackground">@color/background</item>
|
||||
<item name="android:textColor">#000000</item>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="colorPrimary">#4360df</item>
|
||||
<item name="colorPrimaryDark">?attr/backgroundColor</item>
|
||||
<item name="colorControlActivated">#4360df</item>
|
||||
<item name="android:windowBackground">?attr/backgroundColor</item>
|
||||
<item name="android:textColor">?attr/textColor</item>
|
||||
<item name="android:forceDarkAllowed">true</item>
|
||||
</style>
|
||||
|
||||
<style name="LightTheme" parent="AppTheme">
|
||||
<item name="textColor">#000000</item>
|
||||
<item name="backgroundColor">#ffffff</item>
|
||||
</style>
|
||||
|
||||
<style name="DarkTheme" parent="AppTheme">
|
||||
<item name="textColor">#ffffff</item>
|
||||
<item name="backgroundColor">#000000</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<attr name="backgroundColor" format="color"/>
|
||||
<attr name="textColor" format="color"/>
|
||||
</resources>
|
||||
@@ -21,6 +21,7 @@
|
||||
# $keytool -genkey -v -keystore ./status-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias status
|
||||
|
||||
# Version requirements used throughout the Gradle scripts
|
||||
kotlinVersion=1.3.11
|
||||
minSdkVersion=23
|
||||
compileSdkVersion=29
|
||||
targetSdkVersion=29
|
||||
@@ -31,10 +32,10 @@ gradlePluginVersion=3.4.1
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
STATUS_RELEASE_STORE_FILE=~/.gradle/status-im.keystore
|
||||
STATUS_RELEASE_STORE_PASSWORD=password
|
||||
STATUS_RELEASE_KEY_ALIAS=status
|
||||
STATUS_RELEASE_KEY_PASSWORD=password
|
||||
KEYSTORE_PATH=~/.gradle/status-im.keystore
|
||||
KEYSTORE_PASSWORD=password
|
||||
KEYSTORE_ALIAS=status
|
||||
KEYSTORE_KEY_PASSWORD=password
|
||||
|
||||
# By default we build a mostly universal APK
|
||||
ANDROID_ABI_SPLIT=false
|
||||
|
||||
@@ -16,5 +16,3 @@ include ':react-native-status'
|
||||
project(':react-native-status').projectDir = new File(rootProject.projectDir, '../modules/react-native-status/android')
|
||||
include ':react-native-status-keycard'
|
||||
project(':react-native-status-keycard').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-status-keycard/android')
|
||||
include ':react-native-webview-bridge'
|
||||
project(':react-native-webview-bridge').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview-bridge/android')
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -29,8 +31,6 @@ pipeline {
|
||||
BUILD_ENV = 'prod'
|
||||
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
|
||||
FASTLANE_DISABLE_COLORS = 1
|
||||
/* since we are mounting it we need to specify location */
|
||||
STATUS_RELEASE_STORE_FILE = '/home/jenkins/status-im.keystore'
|
||||
/* We use EXECUTOR_NUMBER to avoid multiple instances clashing */
|
||||
LEIN_HOME = "/var/tmp/lein-${EXECUTOR_NUMBER}"
|
||||
/* coverage report identification */
|
||||
@@ -42,14 +42,11 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
/* Necessary to load methods */
|
||||
android = load 'ci/android.groovy'
|
||||
cmn = load 'ci/common.groovy'
|
||||
btype = cmn.utils.getBuildType()
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
cmn.ci.abortPreviousRunningBuilds()
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
cmn.prep(btype)
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +55,7 @@ pipeline {
|
||||
/* Build implicit dependencies if needed (we run `lein deps :tree` but it's not really required, for this purpose)
|
||||
Implicit dependencies include building a patched node_modules, fetching maven dependencies, and anything else required.
|
||||
We do this before the parallel steps so we have a known starting situation. */
|
||||
script { cmn.nix.shell('lein deps :tree', attr: 'shells.lein') }
|
||||
script { nix.shell('lein deps :tree', attr: 'shells.lein') }
|
||||
}
|
||||
}
|
||||
stage('Parallel Assemble') {
|
||||
@@ -66,23 +63,25 @@ pipeline {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
nix.shell('lein cljfmt check', attr: 'shells.lein')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
script { nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
}
|
||||
}
|
||||
} }
|
||||
stage('Build') { stages {
|
||||
stage('JSBundle') {
|
||||
steps {
|
||||
script {
|
||||
cmn.nix.shell('make jsbundle-android', pure: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Bundle') {
|
||||
steps {
|
||||
script { apks = android.bundle() }
|
||||
@@ -101,7 +100,7 @@ pipeline {
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script {
|
||||
def urls = apks.collect { cmn.uploadArtifact(it) }
|
||||
def urls = apks.collect { s3.uploadArtifact(it) }
|
||||
/* return only the universal APK */
|
||||
if (urls.size() > 1) {
|
||||
env.PKG_URL = urls.find { it.contains('universal') }
|
||||
@@ -129,8 +128,8 @@ pipeline {
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { load('ci/github.groovy').notifyPR(true) } }
|
||||
failure { script { load('ci/github.groovy').notifyPR(false) } }
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
always { sh 'make _fix-node-perms' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'master' }
|
||||
agent { label 'linux' }
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
@@ -18,36 +20,33 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps { script {
|
||||
println "Current JOB: ${env.JOB_NAME}"
|
||||
/* load common lib */
|
||||
cmn = load('ci/common.groovy')
|
||||
gh = load('ci/github.groovy')
|
||||
/* just for a shorter access */
|
||||
btype = cmn.utils.getBuildType()
|
||||
btype = utils.getBuildType()
|
||||
} }
|
||||
}
|
||||
stage('Build') {
|
||||
parallel {
|
||||
stage('iOS') { steps { script {
|
||||
ios = cmn.ci.Build('status-react/combined/mobile-ios')
|
||||
ios = jenkins.Build('status-react/combined/mobile-ios')
|
||||
} } }
|
||||
stage('Android') { steps { script {
|
||||
apk = cmn.ci.Build('status-react/combined/mobile-android')
|
||||
apk = jenkins.Build('status-react/combined/mobile-android')
|
||||
} } }
|
||||
stage('Android e2e') { steps { script {
|
||||
apke2e = cmn.ci.Build('status-react/combined/mobile-android-e2e')
|
||||
apke2e = jenkins.Build('status-react/combined/mobile-android-e2e')
|
||||
} } }
|
||||
}
|
||||
}
|
||||
stage('Archive') {
|
||||
steps { script {
|
||||
sh('rm -f pkg/*')
|
||||
cmn.ci.copyArts(ios)
|
||||
//cmn.ci.copyArts(iose2e)
|
||||
cmn.ci.copyArts(apk)
|
||||
cmn.ci.copyArts(apke2e)
|
||||
jenkins.copyArts(ios)
|
||||
//jenkins.copyArts(iose2e)
|
||||
jenkins.copyArts(apk)
|
||||
jenkins.copyArts(apke2e)
|
||||
dir('pkg') {
|
||||
/* generate sha256 checksums for upload */
|
||||
sh "sha256sum * | tee ${cmn.utils.pkgFilename(btype, 'sha256')}"
|
||||
sh "sha256sum * | tee ${utils.pkgFilename(btype, 'sha256')}"
|
||||
archiveArtifacts('*')
|
||||
}
|
||||
} }
|
||||
@@ -57,37 +56,37 @@ pipeline {
|
||||
/* object for easier URLs handling */
|
||||
urls = [
|
||||
/* mobile */
|
||||
Apk: cmn.pkgUrl(apk), Apke2e: cmn.pkgUrl(apke2e),
|
||||
iOS: cmn.pkgUrl(ios), /*iOSe2e: cmn.pkgUrl(iose2e),*/
|
||||
Diawi: cmn.utils.getEnv(ios, 'DIAWI_URL'),
|
||||
Apk: utils.pkgUrl(apk), Apke2e: utils.pkgUrl(apke2e),
|
||||
iOS: utils.pkgUrl(ios), /*iOSe2e: utils.pkgUrl(iose2e),*/
|
||||
Diawi: utils.utils.getEnv(ios, 'DIAWI_URL'),
|
||||
/* upload the sha256 checksums file too */
|
||||
SHA: cmn.uploadArtifact(cmn.utils.pkgFind('sha256')),
|
||||
SHA: s3.uploadArtifact(utils.pkgFind('sha256')),
|
||||
]
|
||||
/* add URLs to the build description */
|
||||
cmn.ci.setBuildDesc(urls)
|
||||
jenkins.setBuildDesc(urls)
|
||||
/* Create JSON file with newest build URLs */
|
||||
switch (btype) {
|
||||
/* legacy naming, should have named it nightly.json */
|
||||
case 'nightly': cmn.updateBucketJSON(urls, 'latest.json'); break
|
||||
case 'release': cmn.updateBucketJSON(urls, 'release.json'); break
|
||||
case 'nightly': s3.updateBucketJSON(urls, 'latest.json'); break
|
||||
}
|
||||
} }
|
||||
}
|
||||
stage('Publish') {
|
||||
steps { script {
|
||||
switch (btype) {
|
||||
//case 'nightly': build('misc/status.im'); break
|
||||
case 'release': gh.publishReleaseMobile(); break
|
||||
case 'nightly': build(job: 'misc/status.im', wait: false); break
|
||||
case 'release': github.publishReleaseMobile(); break
|
||||
}
|
||||
} }
|
||||
}
|
||||
stage('Run e2e') {
|
||||
when { expression { btype == 'nightly' } }
|
||||
steps { script {
|
||||
e2eApk = cmn.utils.getEnv(apke2e, 'SAUCE_URL')
|
||||
e2eApk = utils.getEnv(apke2e, 'SAUCE_URL')
|
||||
build(
|
||||
job: 'end-to-end-tests/status-app-nightly', wait: false,
|
||||
parameters: [string(name: 'APK_NAME', value: e2eApk)]
|
||||
job: 'end-to-end-tests/status-app-nightly',
|
||||
parameters: [string(name: 'APK_NAME', value: e2eApk)],
|
||||
wait: false
|
||||
)
|
||||
} }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos' }
|
||||
|
||||
@@ -26,10 +28,9 @@ pipeline {
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps { script {
|
||||
nix = load('ci/nix.groovy')
|
||||
nix.shell(
|
||||
'bundle install --gemfile=fastlane/Gemfile',
|
||||
attr: 'shells.fastlane'
|
||||
attr: 'shells.fastlane',
|
||||
)
|
||||
} }
|
||||
}
|
||||
@@ -44,7 +45,7 @@ pipeline {
|
||||
]) {
|
||||
nix.shell(
|
||||
'bundle exec --gemfile=fastlane/Gemfile fastlane ios clean',
|
||||
keep: ['FASTLANE_APPLE_ID', 'FASTLANE_PASSWORD']
|
||||
keepEnv: ['FASTLANE_APPLE_ID', 'FASTLANE_PASSWORD'],
|
||||
attr: 'shells.fastlane',
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos-xcode-11.3.1' }
|
||||
agent { label 'macos-xcode-11.4.1' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
@@ -39,14 +41,11 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
/* Necessary to load methods */
|
||||
ios = load 'ci/ios.groovy'
|
||||
cmn = load 'ci/common.groovy'
|
||||
btype = cmn.utils.getBuildType()
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
cmn.ci.abortPreviousRunningBuilds()
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
cmn.prep(btype)
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,19 +54,28 @@ pipeline {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
nix.shell('lein cljfmt check', attr: 'shells.lein')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
script { nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
}
|
||||
}
|
||||
} }
|
||||
stage('Build') { stages {
|
||||
stage('JSBundle') {
|
||||
steps {
|
||||
script { cmn.nix.shell('make jsbundle-ios') }
|
||||
script { nix.shell('make jsbundle-ios') }
|
||||
}
|
||||
}
|
||||
stage('Bundle') {
|
||||
@@ -88,7 +96,7 @@ pipeline {
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script {
|
||||
env.PKG_URL = cmn.uploadArtifact(api)
|
||||
env.PKG_URL = s3.uploadArtifact(api)
|
||||
/* e2e builds get tested in SauceLabs */
|
||||
if (btype == 'e2e') {
|
||||
env.SAUCE_URL = ios.uploadToSauceLabs()
|
||||
@@ -108,8 +116,8 @@ pipeline {
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { load('ci/github.groovy').notifyPR(true) } }
|
||||
failure { script { load('ci/github.groovy').notifyPR(false) } }
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
always { sh 'make _fix-node-perms' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -42,14 +44,11 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
/* Necessary to load methods */
|
||||
desktop = load 'ci/desktop.groovy'
|
||||
cmn = load 'ci/common.groovy'
|
||||
btype = cmn.utils.getBuildType()
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
cmn.ci.abortPreviousRunningBuilds()
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
cmn.prep(btype)
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,12 +57,21 @@ pipeline {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
nix.shell('lein cljfmt check', attr: 'shells.lein')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
script { nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
}
|
||||
}
|
||||
} }
|
||||
@@ -95,7 +103,7 @@ pipeline {
|
||||
}
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script { env.PKG_URL = cmn.uploadArtifact(app) }
|
||||
script { env.PKG_URL = s3.uploadArtifact(app) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,7 +116,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { load('ci/github.groovy').notifyPR(true) } }
|
||||
failure { script { load('ci/github.groovy').notifyPR(false) } }
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'macos-xcode-11.3.1' }
|
||||
agent { label 'macos-xcode-11.4.1' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
@@ -40,14 +42,11 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
/* Necessary to load methods */
|
||||
desktop = load 'ci/desktop.groovy'
|
||||
cmn = load 'ci/common.groovy'
|
||||
btype = cmn.utils.getBuildType()
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
cmn.ci.abortPreviousRunningBuilds()
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
cmn.prep(btype)
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,12 +55,21 @@ pipeline {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
nix.shell('lein cljfmt check', attr: 'shells.lein')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
script { nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
}
|
||||
}
|
||||
} }
|
||||
@@ -93,7 +101,7 @@ pipeline {
|
||||
}
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script { env.PKG_URL = cmn.uploadArtifact(dmg) }
|
||||
script { env.PKG_URL = s3.uploadArtifact(dmg) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,7 +114,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { load('ci/github.groovy').notifyPR(true) } }
|
||||
failure { script { load('ci/github.groovy').notifyPR(false) } }
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label params.AGENT_LABEL }
|
||||
|
||||
@@ -25,11 +27,6 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps { script {
|
||||
nix = load('ci/nix.groovy')
|
||||
} }
|
||||
}
|
||||
stage('Setup') {
|
||||
steps { script {
|
||||
nix.shell('nix-env -i openssh', pure: false)
|
||||
@@ -46,6 +43,7 @@ pipeline {
|
||||
platforms.each { os ->
|
||||
nix.build(
|
||||
attr: "targets.status-go.${os}.buildInputs",
|
||||
sandbox: false,
|
||||
link: false
|
||||
)
|
||||
}
|
||||
@@ -57,6 +55,7 @@ pipeline {
|
||||
* (e.g. maven and node repos) */
|
||||
nix.build(
|
||||
attr: 'targets.mobile.android.jsbundle',
|
||||
sandbox: false,
|
||||
pure: false,
|
||||
link: false
|
||||
)
|
||||
@@ -67,6 +66,7 @@ pipeline {
|
||||
/* build/fetch things required to build jsbundle and android */
|
||||
nix.build(
|
||||
attr: 'targets.mobile.android.buildInputs',
|
||||
sandbox: false,
|
||||
pure: false,
|
||||
link: false
|
||||
)
|
||||
@@ -77,6 +77,7 @@ pipeline {
|
||||
/* build/fetch things required to instantiate shell.nix for TARGET=all */
|
||||
nix.build(
|
||||
attr: 'shells.default.buildInputs',
|
||||
sandbox: false,
|
||||
link: false
|
||||
)
|
||||
} }
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
library 'status-react-jenkins@master'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
||||
@@ -45,14 +47,11 @@ pipeline {
|
||||
stage('Prep') {
|
||||
steps {
|
||||
script {
|
||||
/* Necessary to load methods */
|
||||
desktop = load 'ci/desktop.groovy'
|
||||
cmn = load 'ci/common.groovy'
|
||||
btype = cmn.utils.getBuildType()
|
||||
btype = utils.getBuildType()
|
||||
print "Running ${btype} build!"
|
||||
cmn.ci.abortPreviousRunningBuilds()
|
||||
jenkins.abortPreviousRunningBuilds()
|
||||
/* Cleanup and Prep */
|
||||
cmn.prep(btype)
|
||||
commonPrep(btype)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,12 +60,21 @@ pipeline {
|
||||
stage('Checks') { stages {
|
||||
stage('Lint') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein cljfmt check', attr: 'shells.lein') }
|
||||
script {
|
||||
/* We want the build result to be uploaded */
|
||||
catchError(
|
||||
message: 'Linting check failed!',
|
||||
buildResult: 'FAILURE',
|
||||
stageResult: 'FAILURE'
|
||||
) {
|
||||
nix.shell('lein cljfmt check', attr: 'shells.lein')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Tests') {
|
||||
steps {
|
||||
script { cmn.nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
script { nix.shell('lein test-cljs', attr: 'shells.lein') }
|
||||
}
|
||||
}
|
||||
} }
|
||||
@@ -98,7 +106,7 @@ pipeline {
|
||||
}
|
||||
stage('Upload') {
|
||||
steps {
|
||||
script { env.PKG_URL = cmn.uploadArtifact(app) }
|
||||
script { env.PKG_URL = s3.uploadArtifact(app) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +119,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
post {
|
||||
success { script { load('ci/github.groovy').notifyPR(true) } }
|
||||
failure { script { load('ci/github.groovy').notifyPR(false) } }
|
||||
success { script { github.notifyPR(true) } }
|
||||
failure { script { github.notifyPR(false) } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Description
|
||||
|
||||
This folder contains files defininf [Jenkins pipelines](https://jenkins.io/doc/book/pipeline/) that run on https://ci.status.im/.
|
||||
|
||||
# Libraries
|
||||
|
||||
All `Jenkinsfile`s contain the following line:
|
||||
```groovy
|
||||
library 'status-react-jenkins@master'
|
||||
```
|
||||
|
||||
Which loads the used methods - like `nix.shell()` - from a separate private repo:
|
||||
|
||||
https://github.com/status-im/status-react-jenkins
|
||||
|
||||
This is done to improve security of our CI setup.
|
||||
@@ -1,172 +0,0 @@
|
||||
nix = load 'ci/nix.groovy'
|
||||
utils = load 'ci/utils.groovy'
|
||||
|
||||
def bundle() {
|
||||
/* we use the method because parameter build type does not take e2e into account */
|
||||
def btype = utils.getBuildType()
|
||||
/* Disable Gradle Daemon https://stackoverflow.com/questions/38710327/jenkins-builds-fail-using-the-gradle-daemon */
|
||||
def gradleOpt = "-PbuildUrl='${currentBuild.absoluteUrl}' --console plain "
|
||||
/* we don't need x86 for any builds except e2e */
|
||||
env.ANDROID_ABI_INCLUDE="armeabi-v7a;arm64-v8a"
|
||||
env.ANDROID_ABI_SPLIT="false"
|
||||
|
||||
/* some builds tyes require different architectures */
|
||||
switch (btype) {
|
||||
case 'e2e':
|
||||
env.ANDROID_ABI_INCLUDE="x86" /* e2e builds are used with simulators */
|
||||
break
|
||||
case 'release':
|
||||
env.ANDROID_ABI_SPLIT="true"
|
||||
gradleOpt += "-PreleaseVersion='${utils.getVersion()}'"
|
||||
break
|
||||
}
|
||||
|
||||
/* credentials necessary to open the keystore and sign the APK */
|
||||
withCredentials([
|
||||
string(
|
||||
credentialsId: 'android-keystore-pass',
|
||||
variable: 'STATUS_RELEASE_STORE_PASSWORD'
|
||||
),
|
||||
usernamePassword(
|
||||
credentialsId: 'android-keystore-key-pass',
|
||||
usernameVariable: 'STATUS_RELEASE_KEY_ALIAS',
|
||||
passwordVariable: 'STATUS_RELEASE_KEY_PASSWORD'
|
||||
)
|
||||
]) {
|
||||
/* Nix target which produces the final APKs */
|
||||
nix.build(
|
||||
attr: 'targets.mobile.android.release',
|
||||
conf: [
|
||||
'status-im.ci': '1',
|
||||
'status-im.build-type': btype,
|
||||
'status-im.status-react.gradle-opts': gradleOpt,
|
||||
'status-im.status-react.build-number': utils.readBuildNumber(),
|
||||
],
|
||||
safeEnv: [
|
||||
'STATUS_RELEASE_KEY_ALIAS',
|
||||
'STATUS_RELEASE_STORE_PASSWORD',
|
||||
'STATUS_RELEASE_KEY_PASSWORD',
|
||||
],
|
||||
keep: [
|
||||
'ANDROID_ABI_SPLIT',
|
||||
'ANDROID_ABI_INCLUDE',
|
||||
'STATUS_RELEASE_STORE_FILE',
|
||||
],
|
||||
sbox: [
|
||||
env.STATUS_RELEASE_STORE_FILE,
|
||||
],
|
||||
link: false
|
||||
)
|
||||
}
|
||||
/* necessary for Fastlane */
|
||||
def apks = renameAPKs()
|
||||
/* for use with Fastlane */
|
||||
env.APK_PATHS = apks.join(";")
|
||||
return apks
|
||||
}
|
||||
|
||||
def extractArchFromAPK(name) {
|
||||
def pattern = /app-(.+)-[^-]+.apk/
|
||||
/* extract architecture from filename */
|
||||
def matches = (name =~ pattern)
|
||||
if (matches.size() > 0) {
|
||||
return matches[0][1]
|
||||
}
|
||||
if (utils.isE2EBuild()) {
|
||||
return 'x86'
|
||||
}
|
||||
/* non-release builds make universal APKs */
|
||||
return 'universal'
|
||||
}
|
||||
|
||||
/**
|
||||
* We need more informative filenames for all builds.
|
||||
* For more details on the format see utils.pkgFilename().
|
||||
**/
|
||||
def renameAPKs() {
|
||||
/* find all APK files */
|
||||
def apkGlob = 'result/*.apk'
|
||||
def found = findFiles(glob: apkGlob)
|
||||
if (found.size() == 0) {
|
||||
throw "APKs not found via glob: ${apkGlob}"
|
||||
}
|
||||
def renamed = []
|
||||
/* rename each for upload & archiving */
|
||||
for (apk in found) {
|
||||
def arch = extractArchFromAPK(apk)
|
||||
def pkg = utils.pkgFilename(env.BUILD_TYPE, 'apk', arch)
|
||||
def newApk = "result/${pkg}"
|
||||
renamed += newApk
|
||||
sh "cp ${apk.path} ${newApk}"
|
||||
}
|
||||
return renamed
|
||||
}
|
||||
|
||||
def uploadToPlayStore(type = 'nightly') {
|
||||
withCredentials([
|
||||
string(credentialsId: "SUPPLY_JSON_KEY_DATA", variable: 'GOOGLE_PLAY_JSON_KEY'),
|
||||
]) {
|
||||
nix.shell(
|
||||
"fastlane android ${type}",
|
||||
keep: ['FASTLANE_DISABLE_COLORS', 'APK_PATHS', 'GOOGLE_PLAY_JSON_KEY'],
|
||||
attr: 'shells.fastlane',
|
||||
pure: false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def uploadToSauceLabs() {
|
||||
def changeId = utils.changeId()
|
||||
if (changeId != null) {
|
||||
env.SAUCE_LABS_NAME = "${changeId}.apk"
|
||||
} else {
|
||||
def pkg = utils.pkgFilename(env.BUILD_TYPE, 'apk', 'x86')
|
||||
env.SAUCE_LABS_NAME = "${pkg}"
|
||||
}
|
||||
withCredentials([
|
||||
usernamePassword(
|
||||
credentialsId: 'sauce-labs-api',
|
||||
usernameVariable: 'SAUCE_USERNAME',
|
||||
passwordVariable: 'SAUCE_ACCESS_KEY'
|
||||
),
|
||||
]) {
|
||||
nix.shell(
|
||||
'fastlane android saucelabs',
|
||||
keep: [
|
||||
'FASTLANE_DISABLE_COLORS', 'APK_PATHS',
|
||||
'SAUCE_ACCESS_KEY', 'SAUCE_USERNAME', 'SAUCE_LABS_NAME'
|
||||
],
|
||||
attr: 'shells.fastlane',
|
||||
pure: false
|
||||
)
|
||||
}
|
||||
return env.SAUCE_LABS_NAME
|
||||
}
|
||||
|
||||
def uploadToDiawi() {
|
||||
withCredentials([
|
||||
string(credentialsId: 'diawi-token', variable: 'DIAWI_TOKEN'),
|
||||
]) {
|
||||
nix.shell(
|
||||
'fastlane android upload_diawi',
|
||||
keep: ['FASTLANE_DISABLE_COLORS', 'APK_PATHS', 'DIAWI_TOKEN'],
|
||||
attr: 'shells.fastlane',
|
||||
pure: false
|
||||
)
|
||||
}
|
||||
diawiUrl = readFile "${env.WORKSPACE}/fastlane/diawi.out"
|
||||
return diawiUrl
|
||||
}
|
||||
|
||||
def coverage() {
|
||||
withCredentials([
|
||||
string(credentialsId: 'coveralls-status-react-token', variable: 'COVERALLS_REPO_TOKEN'),
|
||||
]) {
|
||||
nix.shell(
|
||||
'make coverage',
|
||||
keep: ['COVERALLS_REPO_TOKEN', 'COVERALLS_SERVICE_NAME', 'COVERALLS_SERVICE_JOB_ID']
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,100 +0,0 @@
|
||||
import groovy.json.JsonBuilder
|
||||
|
||||
/* Libraries -----------------------------------------------------------------*/
|
||||
|
||||
ci = load 'ci/jenkins.groovy'
|
||||
nix = load 'ci/nix.groovy'
|
||||
utils = load 'ci/utils.groovy'
|
||||
|
||||
/* Small Helpers -------------------------------------------------------------*/
|
||||
|
||||
def pkgUrl(build) {
|
||||
return utils.getEnv(build, 'PKG_URL')
|
||||
}
|
||||
|
||||
def updateBucketJSON(urls, fileName) {
|
||||
/* latest.json has slightly different key names */
|
||||
def content = [
|
||||
DIAWI: urls.Diawi,
|
||||
APK: urls.Apk, IOS: urls.iOS,
|
||||
APP: urls.App, MAC: urls.Mac,
|
||||
WIN: urls.Win, SHA: urls.SHA
|
||||
]
|
||||
def filePath = "${pwd()}/pkg/${fileName}"
|
||||
/* it might not exist */
|
||||
sh 'mkdir -p pkg'
|
||||
def contentJson = new JsonBuilder(content).toPrettyString()
|
||||
println "${fileName}:\n${contentJson}"
|
||||
new File(filePath).write(contentJson)
|
||||
return uploadArtifact(filePath)
|
||||
}
|
||||
|
||||
def prep(type = 'nightly') {
|
||||
/* build/downloads all nix deps in advance */
|
||||
nix.prepEnv()
|
||||
/* rebase unless this is a release build */
|
||||
utils.doGitRebase()
|
||||
/* ensure that we start from a known state */
|
||||
sh 'make clean'
|
||||
/* Disable git hooks in CI, it's not useful, takes time and creates weird errors at times
|
||||
(e.g. bin/sh: 2: /etc/ssl/certs/ca-certificates.crt: Permission denied) */
|
||||
sh 'make disable-githooks'
|
||||
|
||||
/* pick right .env and update from params */
|
||||
utils.updateEnv(type)
|
||||
|
||||
if (['android', 'ios'].contains(env.TARGET)) {
|
||||
/* Run at start to void mismatched numbers */
|
||||
utils.genBuildNumber()
|
||||
}
|
||||
|
||||
nix.shell('watchman watch-del-all', attr: 'shells.watchman')
|
||||
|
||||
if (env.TARGET == 'ios') {
|
||||
/* install ruby dependencies */
|
||||
nix.shell(
|
||||
'bundle install --gemfile=fastlane/Gemfile --quiet',
|
||||
attr: 'shells.fastlane')
|
||||
}
|
||||
|
||||
if (['macos', 'linux', 'windows'].contains(env.TARGET)) {
|
||||
/* node deps, pods, and status-go download */
|
||||
nix.shell('scripts/prepare-for-desktop-platform.sh', pure: false)
|
||||
}
|
||||
/* run script in the nix shell so that node_modules gets instantiated before attempting the copies */
|
||||
nix.shell('scripts/copy-translations.sh chmod', attr: "shells.${env.TARGET}")
|
||||
}
|
||||
|
||||
def uploadArtifact(path) {
|
||||
/* defaults for upload */
|
||||
def domain = 'ams3.digitaloceanspaces.com'
|
||||
def bucket = 'status-im'
|
||||
/* There's so many PR builds we need a separate bucket */
|
||||
if (utils.isPRBuild()) {
|
||||
bucket = 'status-im-prs'
|
||||
}
|
||||
/* WARNING: s3cmd can't guess APK MIME content-type */
|
||||
def customOpts = ''
|
||||
if (path.endsWith('apk')) {
|
||||
customOpts += "--mime-type='application/vnd.android.package-archive'"
|
||||
}
|
||||
/* We also need credentials for the upload */
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'digital-ocean-access-keys',
|
||||
usernameVariable: 'DO_ACCESS_KEY',
|
||||
passwordVariable: 'DO_SECRET_KEY'
|
||||
)]) {
|
||||
sh("""
|
||||
s3cmd ${customOpts} \\
|
||||
--acl-public \\
|
||||
--host="${domain}" \\
|
||||
--host-bucket="%(bucket)s.${domain}" \\
|
||||
--access_key=${DO_ACCESS_KEY} \\
|
||||
--secret_key=${DO_SECRET_KEY} \\
|
||||
put ${path} s3://${bucket}/
|
||||
""")
|
||||
}
|
||||
return "https://${bucket}.${domain}/${utils.getFilename(path)}"
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,109 +0,0 @@
|
||||
nix = load 'ci/nix.groovy'
|
||||
utils = load 'ci/utils.groovy'
|
||||
|
||||
packageFolder = './StatusImPackage'
|
||||
|
||||
def buildJSBundle() {
|
||||
nix.shell(
|
||||
'''
|
||||
make jsbundle-desktop && \
|
||||
./scripts/build-desktop.sh buildJSBundle
|
||||
''',
|
||||
keep: ['VERBOSE_LEVEL']
|
||||
)
|
||||
}
|
||||
|
||||
def uploadArtifact(filename) {
|
||||
def domain = 'ams3.digitaloceanspaces.com'
|
||||
def bucket = 'status-im-desktop'
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'digital-ocean-access-keys',
|
||||
usernameVariable: 'DO_ACCESS_KEY',
|
||||
passwordVariable: 'DO_SECRET_KEY'
|
||||
)]) {
|
||||
sh """
|
||||
s3cmd \\
|
||||
--acl-public \\
|
||||
--host='${domain}' \\
|
||||
--host-bucket='%(bucket)s.${domain}' \\
|
||||
--access_key=${DO_ACCESS_KEY} \\
|
||||
--secret_key=${DO_SECRET_KEY} \\
|
||||
put ${filename} s3://${bucket}/
|
||||
"""
|
||||
|
||||
}
|
||||
def url = "https://${bucket}.${domain}/${filename}"
|
||||
return url
|
||||
}
|
||||
|
||||
/* MAIN --------------------------------------------------*/
|
||||
|
||||
def compile() {
|
||||
/* disable logs for desktop builds when releasing */
|
||||
if (params.BUILD_TYPE == 'release') {
|
||||
env.STATUS_NO_LOGGING = 1
|
||||
}
|
||||
/* since QT is in a custom path we need to add it to PATH */
|
||||
if (env.QT_PATH) {
|
||||
env.PATH = "${env.QT_PATH}:${env.PATH}"
|
||||
}
|
||||
nix.shell(
|
||||
'./scripts/build-desktop.sh compile',
|
||||
keep: ['VERBOSE_LEVEL']
|
||||
)
|
||||
}
|
||||
|
||||
def bundleWindows(type = 'nightly') {
|
||||
def pkg
|
||||
|
||||
nix.shell(
|
||||
'./scripts/build-desktop.sh bundle',
|
||||
keep: ['VERBOSE_LEVEL']
|
||||
)
|
||||
dir(packageFolder) {
|
||||
pkg = utils.pkgFilename(type, 'exe')
|
||||
sh "mv ../Status-x86_64-setup.exe ${pkg}"
|
||||
}
|
||||
return "${packageFolder}/${pkg}".drop(2)
|
||||
}
|
||||
|
||||
def bundleLinux(type = 'nightly') {
|
||||
def pkg
|
||||
nix.shell(
|
||||
'./scripts/build-desktop.sh bundle',
|
||||
keep: ['VERBOSE_LEVEL']
|
||||
)
|
||||
dir(packageFolder) {
|
||||
pkg = utils.pkgFilename(type, 'AppImage')
|
||||
sh "mv ../Status-x86_64.AppImage ${pkg}"
|
||||
}
|
||||
return "${packageFolder}/${pkg}".drop(2)
|
||||
}
|
||||
|
||||
def bundleMacOS(type = 'nightly') {
|
||||
def pkg = utils.pkgFilename(type, 'dmg')
|
||||
nix.shell(
|
||||
'./scripts/build-desktop.sh bundle',
|
||||
keep: ['VERBOSE_LEVEL']
|
||||
)
|
||||
dir(packageFolder) {
|
||||
withCredentials([
|
||||
string(credentialsId: 'desktop-gpg-outer-pass', variable: 'GPG_PASS_OUTER'),
|
||||
string(credentialsId: 'desktop-gpg-inner-pass', variable: 'GPG_PASS_INNER'),
|
||||
string(credentialsId: 'desktop-keychain-pass', variable: 'KEYCHAIN_PASS')
|
||||
]) {
|
||||
nix.shell(
|
||||
"""
|
||||
../scripts/sign-macos-pkg.sh Status.app ../deployment/macos/macos-developer-id.keychain-db.gpg && \
|
||||
../node_modules/appdmg/bin/appdmg.js ../deployment/macos/status-dmg.json ${pkg} && \
|
||||
../scripts/sign-macos-pkg.sh ${pkg} ../deployment/macos/macos-developer-id.keychain-db.gpg
|
||||
""",
|
||||
pure: false,
|
||||
keep: ['GPG_PASS_OUTER', 'GPG_PASS_INNER', 'KEYCHAIN_PASS']
|
||||
)
|
||||
}
|
||||
}
|
||||
return "${packageFolder}/${pkg}".drop(2)
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,62 +0,0 @@
|
||||
import groovy.json.JsonBuilder
|
||||
|
||||
utils = load 'ci/utils.groovy'
|
||||
|
||||
/**
|
||||
* Methods for interacting with ghcmgr API.
|
||||
* For more details see:
|
||||
* https://github.com/status-im/github-comment-manager
|
||||
**/
|
||||
|
||||
def buildObj(success) {
|
||||
def pkg_url = env.PKG_URL
|
||||
/* a bare ipa file is not installable on iOS */
|
||||
if (env.TARGET == 'ios' && env.DIAWI_URL != "") {
|
||||
pkg_url = env.DIAWI_URL
|
||||
}
|
||||
/* assemble build object valid for ghcmgr */
|
||||
return [
|
||||
id: env.BUILD_DISPLAY_NAME,
|
||||
commit: GIT_COMMIT.take(8),
|
||||
success: success != null ? success : true,
|
||||
platform: env.TARGET + (utils.isE2EBuild() ? '-e2e' : ''),
|
||||
duration: utils.buildDuration(),
|
||||
url: currentBuild.absoluteUrl,
|
||||
pkg_url: pkg_url,
|
||||
]
|
||||
}
|
||||
|
||||
def postBuild(success) {
|
||||
/**
|
||||
* This is our own service for avoiding comment spam.
|
||||
* https://github.com/status-im/github-comment-manager
|
||||
**/
|
||||
def ghcmgrurl = 'https://ghcmgr.status.im'
|
||||
def body = buildObj(success)
|
||||
def json = new JsonBuilder(body).toPrettyString()
|
||||
def stdout = null
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'ghcmgr-auth',
|
||||
usernameVariable: 'GHCMGR_USER',
|
||||
passwordVariable: 'GHCMGR_PASS'
|
||||
)]) {
|
||||
stdout = sh(
|
||||
returnStdout: true,
|
||||
script: """
|
||||
curl --silent \
|
||||
-XPOST --data '${json}' \
|
||||
-u '${GHCMGR_USER}:${GHCMGR_PASS}' \
|
||||
-w '\nHTTP_CODE:%{http_code}' \
|
||||
-H "content-type: application/json" \
|
||||
'${ghcmgrurl}/builds/status-react/${utils.changeId()}'
|
||||
"""
|
||||
)
|
||||
}
|
||||
/* We're not using --fail because it suppresses server response */
|
||||
if (!stdout.contains('HTTP_CODE:201')) {
|
||||
println("STDOUT:\n${stdout}")
|
||||
error("Notifying GHCMGR failed")
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,205 +0,0 @@
|
||||
import groovy.json.JsonBuilder
|
||||
|
||||
/* I'm using utils from ghcmgr to avoid another load */
|
||||
ghcmgr = load 'ci/ghcmgr.groovy'
|
||||
|
||||
/**
|
||||
* Methods for interacting with GitHub API and related tools.
|
||||
**/
|
||||
|
||||
/* Comments -------------------------------------------------------*/
|
||||
|
||||
def notify(message) {
|
||||
def githubIssuesUrl = 'https://api.github.com/repos/status-im/status-react/issues'
|
||||
def changeId = ghcmgr.utils.changeId()
|
||||
if (changeId == null) { return }
|
||||
def msgObj = [body: message]
|
||||
def msgJson = new JsonBuilder(msgObj).toPrettyString()
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'status-im-auto',
|
||||
usernameVariable: 'GH_USER',
|
||||
passwordVariable: 'GH_PASS'
|
||||
)]) {
|
||||
sh """
|
||||
curl --silent \
|
||||
-u '${GH_USER}:${GH_PASS}' \
|
||||
--data '${msgJson}' \
|
||||
-H "Content-Type: application/json" \
|
||||
"${githubIssuesUrl}/${changeId}/comments"
|
||||
""".trim()
|
||||
}
|
||||
}
|
||||
|
||||
def notifyFull(urls) {
|
||||
def msg = "#### :white_check_mark: "
|
||||
msg += "[${env.JOB_NAME}${currentBuild.displayName}](${currentBuild.absoluteUrl}) "
|
||||
msg += "CI BUILD SUCCESSFUL in ${ghcmgr.utils.buildDuration()} (${GIT_COMMIT.take(8)})\n"
|
||||
msg += '| | | | | |\n'
|
||||
msg += '|-|-|-|-|-|\n'
|
||||
msg += "| [Android](${urls.Apk}) ([e2e](${urls.Apke2e})) "
|
||||
msg += "| [iOS](${urls.iOS}) ([e2e](${urls.iOSe2e})) |"
|
||||
if (urls.Mac != null) {
|
||||
msg += " [MacOS](${urls.Mac}) | [AppImage](${urls.App}) | [Windows](${urls.Win}) |"
|
||||
} else {
|
||||
msg += " ~~MacOS~~ | ~~AppImage~~ | ~~Windows~~~ |"
|
||||
}
|
||||
notify(msg)
|
||||
}
|
||||
|
||||
def notifyPRFailure() {
|
||||
def d = ":small_orange_diamond:"
|
||||
def msg = "#### :x: "
|
||||
msg += "[${env.JOB_NAME}${currentBuild.displayName}](${currentBuild.absoluteUrl}) ${d} "
|
||||
msg += "${ghcmgr.utils.buildDuration()} ${d} ${GIT_COMMIT.take(8)} ${d} "
|
||||
msg += "[:page_facing_up: build log](${currentBuild.absoluteUrl}/consoleText)"
|
||||
//msg += "Failed in stage: ${env.STAGE_NAME}\n"
|
||||
//msg += "```${currentBuild.rawBuild.getLog(5)}```"
|
||||
notify(msg)
|
||||
}
|
||||
|
||||
def notifyPRSuccess() {
|
||||
def d = ":small_blue_diamond:"
|
||||
def msg = "#### :heavy_check_mark: "
|
||||
def type = ghcmgr.utils.isE2EBuild() ? ' e2e' : ''
|
||||
msg += "[${env.JOB_NAME}${currentBuild.displayName}](${currentBuild.absoluteUrl}) ${d} "
|
||||
msg += "${ghcmgr.utils.buildDuration()} ${d} ${GIT_COMMIT.take(8)} ${d} "
|
||||
msg += "[:package: ${env.TARGET}${type} package](${env.PKG_URL})"
|
||||
notify(msg)
|
||||
}
|
||||
|
||||
/* Releases -------------------------------------------------------*/
|
||||
|
||||
def getPrevRelease() {
|
||||
return sh(returnStdout: true,
|
||||
script: "git for-each-ref --format '%(refname)' --sort=committerdate refs/remotes/origin/release"
|
||||
).trim().split('\\r?\\n').last()
|
||||
}
|
||||
|
||||
def getDiffUrl(prev, current) {
|
||||
prev = prev.replaceAll(/.*origin\//, '')
|
||||
return "https://github.com/status-im/status-react/compare/${prev}...${current}"
|
||||
}
|
||||
|
||||
def getReleaseChanges() {
|
||||
def prevRelease = getPrevRelease()
|
||||
def curRelease = ghcmgr.utils.branchName()
|
||||
def changes = ''
|
||||
try {
|
||||
changes = sh(returnStdout: true,
|
||||
script: """
|
||||
git log \
|
||||
--cherry-pick \
|
||||
--right-only \
|
||||
--no-merges \
|
||||
--format='%h %s' \
|
||||
${prevRelease}..HEAD
|
||||
"""
|
||||
).trim()
|
||||
} catch (Exception ex) {
|
||||
println 'ERROR: Failed to retrieve changes.'
|
||||
println ex.message
|
||||
return ':warning: __Please fill me in!__'
|
||||
}
|
||||
/* remove single quotes to not confuse formatting */
|
||||
changes = changes.replace('\'', '')
|
||||
return changes + '\nDiff:' + getDiffUrl(prevRelease, curRelease)
|
||||
}
|
||||
|
||||
def releaseExists(Map args) {
|
||||
def output = sh(
|
||||
returnStdout: true,
|
||||
script: """
|
||||
github-release info --json \
|
||||
-u '${args.user}' \
|
||||
-r '${args.repo}' \
|
||||
| jq '.Releases[].tag_name'
|
||||
"""
|
||||
)
|
||||
return output.contains(args.version)
|
||||
}
|
||||
|
||||
def releaseDelete(Map args) {
|
||||
if (!releaseExists(args)) {
|
||||
return
|
||||
}
|
||||
sh """
|
||||
github-release delete \
|
||||
-u '${args.user}' \
|
||||
-r '${args.repo}' \
|
||||
-t '${args.version}' \
|
||||
"""
|
||||
}
|
||||
|
||||
def releaseUpload(Map args) {
|
||||
args.files.each {
|
||||
sh """
|
||||
github-release upload \
|
||||
-u '${args.user}' \
|
||||
-r '${args.repo}' \
|
||||
-t '${args.version}' \
|
||||
-n ${it} \
|
||||
-f ${it}
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
def releasePublish(Map args) {
|
||||
sh """
|
||||
github-release release \
|
||||
-u '${args.user}' \
|
||||
-r '${args.repo}' \
|
||||
-n '${args.version}' \
|
||||
-t '${args.version}' \
|
||||
-c '${args.branch}' \
|
||||
-d '${args.desc}' \
|
||||
${args.draft ? '--draft' : ''}
|
||||
"""
|
||||
}
|
||||
|
||||
def publishRelease(Map args) {
|
||||
def config = [
|
||||
draft: true,
|
||||
user: 'status-im',
|
||||
repo: 'status-react',
|
||||
files: args.files,
|
||||
version: args.version,
|
||||
branch: ghcmgr.utils.branchName(),
|
||||
desc: getReleaseChanges(),
|
||||
]
|
||||
/* we release only for mobile right now */
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'status-im-auto',
|
||||
usernameVariable: 'GITHUB_USER',
|
||||
passwordVariable: 'GITHUB_TOKEN'
|
||||
)]) {
|
||||
releaseDelete(config) /* so we can re-release it */
|
||||
releasePublish(config)
|
||||
releaseUpload(config)
|
||||
}
|
||||
}
|
||||
|
||||
def publishReleaseMobile(path='pkg') {
|
||||
def found = findFiles(glob: "${path}/*")
|
||||
if (found.size() == 0) {
|
||||
sh "ls ${path}"
|
||||
error("No file to release in ${path}")
|
||||
}
|
||||
publishRelease(
|
||||
version: ghcmgr.utils.getVersion(),
|
||||
files: found.collect { it.path },
|
||||
)
|
||||
}
|
||||
|
||||
def notifyPR(success) {
|
||||
if (ghcmgr.utils.changeId() == null) { return }
|
||||
try {
|
||||
ghcmgr.postBuild(success)
|
||||
} catch (ex) { /* fallback to posting directly to GitHub */
|
||||
println "Failed to use GHCMGR: ${ex}"
|
||||
switch (success) {
|
||||
case true: notifyPRSuccess(); break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,102 +0,0 @@
|
||||
nix = load('ci/nix.groovy')
|
||||
utils = load('ci/utils.groovy')
|
||||
|
||||
def plutil(name, value) {
|
||||
return """
|
||||
plutil -replace ${name} -string ${value} ios/StatusIm/Info.plist;
|
||||
"""
|
||||
}
|
||||
|
||||
def bundle() {
|
||||
def btype = utils.getBuildType()
|
||||
def target
|
||||
switch (btype) {
|
||||
case 'release': target = 'release'; break;
|
||||
case 'testflight': target = 'release'; break;
|
||||
case 'e2e': target = 'e2e'; break;
|
||||
default: target = 'nightly';
|
||||
}
|
||||
/* configure build metadata */
|
||||
nix.shell(plutil('CFBundleShortVersionString', utils.getVersion()), attr: 'shells.ios')
|
||||
nix.shell(plutil('CFBundleVersion', utils.genBuildNumber()), attr: 'shells.ios')
|
||||
nix.shell(plutil('CFBundleBuildUrl', currentBuild.absoluteUrl), attr: 'shells.ios')
|
||||
/* the dir might not exist */
|
||||
sh 'mkdir -p status-e2e'
|
||||
/* build the actual app */
|
||||
withCredentials([
|
||||
string(credentialsId: "slave-pass-${env.NODE_NAME}", variable: 'KEYCHAIN_PASSWORD'),
|
||||
string(credentialsId: 'fastlane-match-password', variable: 'MATCH_PASSWORD'),
|
||||
usernamePassword(
|
||||
credentialsId: 'fastlane-match-apple-id',
|
||||
usernameVariable: 'FASTLANE_APPLE_ID',
|
||||
passwordVariable: 'FASTLANE_PASSWORD'
|
||||
),
|
||||
]) {
|
||||
nix.shell(
|
||||
"bundle exec --gemfile=fastlane/Gemfile fastlane ios ${target}",
|
||||
keep: [
|
||||
'FASTLANE_DISABLE_COLORS',
|
||||
'FASTLANE_PASSWORD', 'KEYCHAIN_PASSWORD',
|
||||
'MATCH_PASSWORD', 'FASTLANE_APPLE_ID',
|
||||
],
|
||||
attr: 'shells.ios'
|
||||
)
|
||||
}
|
||||
/* rename built file for uploads and archivization */
|
||||
def pkg = ''
|
||||
if (btype == 'release') {
|
||||
pkg = utils.pkgFilename('release', 'ipa')
|
||||
sh "cp status_appstore/StatusIm.ipa ${pkg}"
|
||||
} else if (btype == 'e2e') {
|
||||
pkg = utils.pkgFilename('e2e', 'app.zip')
|
||||
sh "cp status-e2e/StatusIm.app.zip ${pkg}"
|
||||
} else if (btype != 'testflight') {
|
||||
pkg = utils.pkgFilename(btype, 'ipa')
|
||||
sh "cp status-adhoc/StatusIm.ipa ${pkg}"
|
||||
}
|
||||
/* necessary for Diawi upload */
|
||||
env.DIAWI_IPA = pkg
|
||||
return pkg
|
||||
}
|
||||
|
||||
def uploadToDiawi() {
|
||||
withCredentials([
|
||||
string(credentialsId: 'diawi-token', variable: 'DIAWI_TOKEN'),
|
||||
]) {
|
||||
/* This can silently fail with 'File is not processed.' */
|
||||
nix.shell(
|
||||
'bundle exec --verbose --gemfile=fastlane/Gemfile fastlane ios upload_diawi',
|
||||
keep: ['FASTLANE_DISABLE_COLORS', 'DIAWI_TOKEN'],
|
||||
attr: 'shells.fastlane'
|
||||
)
|
||||
}
|
||||
diawiUrl = readFile "${env.WORKSPACE}/fastlane/diawi.out"
|
||||
/* Save the URL in the build description */
|
||||
currentBuild.description = "<a href=\"${diawiUrl}\">Diawi Link</a>"
|
||||
return diawiUrl
|
||||
}
|
||||
|
||||
def uploadToSauceLabs() {
|
||||
def changeId = utils.getParentRunEnv('CHANGE_ID')
|
||||
if (changeId != null) {
|
||||
env.SAUCE_LABS_NAME = "${changeId}.app.zip"
|
||||
} else {
|
||||
env.SAUCE_LABS_NAME = "im.status.ethereum-e2e-${utils.gitCommit()}.app.zip"
|
||||
}
|
||||
withCredentials([
|
||||
usernamePassword(
|
||||
credentialsId: 'sauce-labs-api',
|
||||
usernameVariable: 'SAUCE_USERNAME',
|
||||
passwordVariable: 'SAUCE_ACCESS_KEY'
|
||||
),
|
||||
]) {
|
||||
nix.shell(
|
||||
'bundle exec --gemfile=fastlane/Gemfile fastlane ios saucelabs',
|
||||
keep: ['FASTLANE_DISABLE_COLORS', 'SAUCE_ACCESS_KEY', 'SAUCE_USERNAME'],
|
||||
attr: 'shells.fastlane'
|
||||
)
|
||||
}
|
||||
return env.SAUCE_LABS_NAME
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,92 +0,0 @@
|
||||
import jenkins.model.CauseOfInterruption.UserInterruption
|
||||
import hudson.model.Result
|
||||
import hudson.model.Run
|
||||
|
||||
utils = load 'ci/utils.groovy'
|
||||
|
||||
@NonCPS
|
||||
def abortPreviousRunningBuilds() {
|
||||
/* Aborting makes sense only for PR builds, since devs start so many of them */
|
||||
if (!env.JOB_NAME.contains('status-react/prs')) {
|
||||
println ">> Not aborting any previous jobs. Not a PR build."
|
||||
return
|
||||
}
|
||||
Run previousBuild = currentBuild.rawBuild.getPreviousBuildInProgress()
|
||||
|
||||
while (previousBuild != null) {
|
||||
if (previousBuild.isInProgress()) {
|
||||
def executor = previousBuild.getExecutor()
|
||||
if (executor != null) {
|
||||
println ">> Aborting older build #${previousBuild.number}"
|
||||
executor.interrupt(Result.ABORTED, new UserInterruption(
|
||||
"newer build #${currentBuild.number}"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
previousBuild = previousBuild.getPreviousBuildInProgress()
|
||||
}
|
||||
}
|
||||
|
||||
def strParam(key, value) {
|
||||
/* just a helper for making string params */
|
||||
return [
|
||||
name: key,
|
||||
value: value,
|
||||
$class: 'StringParameterValue',
|
||||
]
|
||||
}
|
||||
|
||||
def Build(name = null) {
|
||||
/**
|
||||
* Generate parameters to pass from current params
|
||||
* This allows utils.updateEnv() to work in sub-jobs
|
||||
**/
|
||||
parameters = params.keySet().collectEntries { key ->
|
||||
[(key): strParam(key, params.get(key))]
|
||||
}
|
||||
/* default to current build type */
|
||||
parameters['BUILD_TYPE'] = strParam('BUILD_TYPE', utils.getBuildType())
|
||||
/* need to drop origin/ to match definitions of child jobs */
|
||||
parameters['BRANCH'] = strParam('BRANCH', utils.branchName())
|
||||
/* necessary for updating GitHub PRs */
|
||||
parameters['CHANGE_ID'] = strParam('CHANGE_ID', env.CHANGE_ID)
|
||||
/* always pass the BRANCH and BUILD_TYPE params with current branch */
|
||||
def b = build(
|
||||
job: name,
|
||||
/* this allows us to analize the job even after failure */
|
||||
propagate: false,
|
||||
parameters: parameters.values()
|
||||
)
|
||||
/* BlueOcean seems to not show child-build links */
|
||||
println "Build: ${b.getAbsoluteUrl()} (${b.result})"
|
||||
if (b.result != 'SUCCESS') {
|
||||
error("Build Failed")
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
def copyArts(build) {
|
||||
/**
|
||||
* The build argument is of class RunWrapper.
|
||||
* https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
|
||||
**/
|
||||
copyArtifacts(
|
||||
projectName: build.fullProjectName,
|
||||
target: 'pkg',
|
||||
flatten: true,
|
||||
selector: specific("${build.number}")
|
||||
)
|
||||
}
|
||||
|
||||
def setBuildDesc(Map links) {
|
||||
def desc = 'Links: \n'
|
||||
links.each { type, url ->
|
||||
if (url != null) {
|
||||
desc += "<a href=\"${url}\">${type}</a> \n"
|
||||
}
|
||||
}
|
||||
currentBuild.description = desc
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -1,166 +0,0 @@
|
||||
/**
|
||||
* Arguments:
|
||||
* - pure - Use --pure mode with Nix for more deterministic behaviour
|
||||
* - keep - List of env variables to keep even in pure mode
|
||||
* - args - Map of arguments to provide to --argstr
|
||||
**/
|
||||
def shell(Map opts = [:], String cmd) {
|
||||
def defaults = [
|
||||
pure: true,
|
||||
args: ['target': env.TARGET ? env.TARGET : 'default'],
|
||||
keep: ['LOCALE_ARCHIVE_2_27'],
|
||||
]
|
||||
/* merge defaults with received opts */
|
||||
opts = defaults + opts
|
||||
/* previous merge overwrites the array */
|
||||
opts.keep = (opts.keep + defaults.keep).unique()
|
||||
/* not all targets can use a pure build */
|
||||
if (env.TARGET in ['windows', 'ios']) {
|
||||
opts.pure = false
|
||||
}
|
||||
sh("""
|
||||
set +x
|
||||
. ~/.nix-profile/etc/profile.d/nix.sh
|
||||
set -x
|
||||
nix-shell --run \'${cmd}\' ${_getNixCommandArgs(opts, true)}
|
||||
""")
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
* - pure - Use --pure mode with Nix for more deterministic behaviour
|
||||
* - link - Bu default build creates a `result` directory, you can turn that off
|
||||
* - keep - List of env variables to pass through to Nix build
|
||||
* - conf - Map of config values to provide to --arg config
|
||||
* - args - Map of arguments to provide to --argstr
|
||||
* - attr - Name of attribute to use with --attr flag
|
||||
* - sbox - List of host file paths to pass to the Nix expression
|
||||
* - safeEnv - Name of env variables to pass securely through to Nix build (they won't get captured in Nix derivation file)
|
||||
**/
|
||||
def build(Map opts = [:]) {
|
||||
def defaults = [
|
||||
pure: true,
|
||||
link: true,
|
||||
args: ['target': env.TARGET],
|
||||
keep: [],
|
||||
conf: [:],
|
||||
attr: null,
|
||||
sbox: [],
|
||||
safeEnv: [],
|
||||
]
|
||||
/* merge defaults with received opts */
|
||||
opts = defaults + opts
|
||||
/* Previous merge overwrites the array */
|
||||
opts.args = defaults.args + opts.args
|
||||
opts.keep = (opts.keep + defaults.keep).unique()
|
||||
|
||||
def nixPath = sh(
|
||||
returnStdout: true,
|
||||
script: """
|
||||
set +x
|
||||
. ~/.nix-profile/etc/profile.d/nix.sh
|
||||
set -x
|
||||
nix-build ${_getNixCommandArgs(opts, false)}
|
||||
"""
|
||||
).trim()
|
||||
/* if not linking, copy results, but only if there's just one path */
|
||||
if (!opts.link && nixPath && !nixPath.contains('\n')) {
|
||||
copyResults(nixPath)
|
||||
}
|
||||
return nixPath
|
||||
}
|
||||
|
||||
private def copyResults(path) {
|
||||
def resultsPath = "${env.WORKSPACE}/result"
|
||||
sh "rm -fr ${resultsPath}"
|
||||
sh "mkdir -p ${resultsPath}"
|
||||
sh "cp -fr ${path}/* ${resultsPath}/"
|
||||
sh "chmod -R 755 ${resultsPath}"
|
||||
}
|
||||
|
||||
private makeNixBuildEnvFile(Map opts = [:]) {
|
||||
File envFile = File.createTempFile("nix-env", ".tmp")
|
||||
if (!opts.safeEnv.isEmpty()) {
|
||||
// Export the environment variables we want to keep into a temporary script we can pass to Nix and source it from the build script
|
||||
def exportCommandList = opts.safeEnv.collect { envVarName -> """
|
||||
echo \"export ${envVarName}=\\\"\$(printenv ${envVarName})\\\"\" >> ${envFile.absolutePath}
|
||||
""" }
|
||||
def exportCommands = exportCommandList.join("")
|
||||
sh """
|
||||
${exportCommands}
|
||||
chmod u+x ${envFile.absolutePath}
|
||||
"""
|
||||
|
||||
opts.args = opts.args + [ 'secrets-file': envFile.absolutePath ]
|
||||
opts.sbox = opts.sbox + envFile.absolutePath
|
||||
}
|
||||
|
||||
return envFile
|
||||
}
|
||||
|
||||
private def _getNixCommandArgs(Map opts = [:], boolean isShell) {
|
||||
def keepFlags = []
|
||||
def entryPoint = "\'${env.WORKSPACE}/shell.nix\'"
|
||||
if (!isShell || opts.attr != null) {
|
||||
entryPoint = "\'${env.WORKSPACE}/default.nix\'"
|
||||
}
|
||||
def extraSandboxPathsFlag = ''
|
||||
|
||||
if (isShell) {
|
||||
keepFlags = opts.keep.collect { var -> "--keep ${var} " }
|
||||
} else {
|
||||
def envVarsList = opts.keep.collect { var -> "${var}=\"${env[var]}\";" }
|
||||
keepFlags = ["--arg env \'{${envVarsList.join("")}}\'"]
|
||||
|
||||
/* Export the environment variables we want to keep into
|
||||
* a Nix attribute set we can pass to Nix and source it from the build script */
|
||||
def envFile = makeNixBuildEnvFile(opts)
|
||||
envFile.deleteOnExit()
|
||||
}
|
||||
|
||||
def configFlag = ''
|
||||
def argsFlags = opts.args.collect { key,val -> "--argstr ${key} \'${val}\'" }
|
||||
def attrFlag = ''
|
||||
if (opts.attr != null) {
|
||||
attrFlag = "--attr '${opts.attr}'"
|
||||
}
|
||||
if (opts.conf != null && opts.conf != [:]) {
|
||||
def configFlags = opts.conf.collect { key,val -> "${key}=\"${val}\";" }
|
||||
configFlag = "--arg config \'{${configFlags.join('')}}\'"
|
||||
}
|
||||
if (opts.sbox != null && !opts.sbox.isEmpty()) {
|
||||
extraSandboxPathsFlag = "--option extra-sandbox-paths \"${opts.sbox.join(' ')}\""
|
||||
}
|
||||
|
||||
return [
|
||||
opts.pure ? "--pure" : "",
|
||||
opts.link ? "" : "--no-out-link",
|
||||
configFlag,
|
||||
keepFlags.join(" "),
|
||||
argsFlags.join(" "),
|
||||
extraSandboxPathsFlag,
|
||||
attrFlag,
|
||||
entryPoint,
|
||||
].join(" ")
|
||||
}
|
||||
|
||||
def prepEnv() {
|
||||
if (env.TARGET in ['linux', 'windows', 'android']) {
|
||||
def glibcLocales = sh(
|
||||
returnStdout: true,
|
||||
script: """
|
||||
. ~/.nix-profile/etc/profile.d/nix.sh && \\
|
||||
nix-build --no-out-link '<nixpkgs>' -A glibcLocales
|
||||
"""
|
||||
).trim()
|
||||
/**
|
||||
* This is a hack to fix missing locale errors.
|
||||
* See:
|
||||
* - https://github.com/NixOS/nixpkgs/issues/38991
|
||||
* - https://qiita.com/kimagure/items/4449ceb0bda5c10ca50f
|
||||
**/
|
||||
env.LOCALE_ARCHIVE_2_27 = "${glibcLocales}/lib/locale/locale-archive"
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -40,6 +40,10 @@ pipeline {
|
||||
usernameVariable: 'SAUCE_USERNAME',
|
||||
passwordVariable: 'SAUCE_ACCESS_KEY'
|
||||
),
|
||||
string(
|
||||
credentialsId: 'etherscan-api-key',
|
||||
variable: 'ETHERSCAN_API_KEY'
|
||||
),
|
||||
]) {
|
||||
dir('test/appium/tests') {
|
||||
sh """
|
||||
|
||||
@@ -61,9 +61,10 @@ pipeline {
|
||||
}
|
||||
|
||||
withCredentials([
|
||||
string(
|
||||
credentialsId: 'GIT_HUB_TOKEN',
|
||||
variable: 'GIT_HUB_TOKEN'
|
||||
usernamePassword(
|
||||
credentialsId: 'status-im-auto-token',
|
||||
usernameVariable: 'GIT_HUB_USER', /* ignored */
|
||||
passwordVariable: 'GIT_HUB_TOKEN'
|
||||
),
|
||||
usernamePassword(
|
||||
credentialsId: 'test-rail-api',
|
||||
@@ -75,6 +76,10 @@ pipeline {
|
||||
usernameVariable: 'SAUCE_USERNAME',
|
||||
passwordVariable: 'SAUCE_ACCESS_KEY'
|
||||
),
|
||||
string(
|
||||
credentialsId: 'etherscan-api-key',
|
||||
variable: 'ETHERSCAN_API_KEY'
|
||||
),
|
||||
]) {
|
||||
dir('test/appium/tests') {
|
||||
sh """
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
def getVersion() {
|
||||
def path = "${env.WORKSPACE}/VERSION"
|
||||
return readFile(path).trim()
|
||||
}
|
||||
|
||||
def branchName() {
|
||||
return env.GIT_BRANCH.replaceAll(/.*origin\//, '')
|
||||
}
|
||||
|
||||
def parentOrCurrentBuild() {
|
||||
def c = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
|
||||
if (c == null) { return currentBuild }
|
||||
return c.getUpstreamRun()
|
||||
}
|
||||
|
||||
def timestamp() {
|
||||
/* we use parent if available to make timestmaps consistent */
|
||||
def now = new Date(parentOrCurrentBuild().timeInMillis)
|
||||
return now.format('yyMMdd-HHmmss', TimeZone.getTimeZone('UTC'))
|
||||
}
|
||||
|
||||
def gitCommit() {
|
||||
return GIT_COMMIT.take(6)
|
||||
}
|
||||
|
||||
def pkgFilename(type, ext, arch=null) {
|
||||
/* the grep removes the null arch */
|
||||
return [
|
||||
"StatusIm", timestamp(), gitCommit(), type, arch,
|
||||
].grep().join('-') + ".${ext}"
|
||||
}
|
||||
|
||||
def doGitRebase() {
|
||||
if (!isPRBuild()) {
|
||||
println 'Skipping rebase due for non-PR build...'
|
||||
return
|
||||
}
|
||||
def rebaseBranch = 'develop'
|
||||
if (env.CHANGE_TARGET) { /* This is available for PR builds */
|
||||
rebaseBranch = env.CHANGE_TARGET
|
||||
}
|
||||
sh 'git status'
|
||||
sh "git fetch --force origin ${rebaseBranch}:${rebaseBranch}"
|
||||
try {
|
||||
sh "git rebase ${rebaseBranch}"
|
||||
} catch (e) {
|
||||
sh 'git rebase --abort'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
def genBuildNumber() {
|
||||
def number = sh(
|
||||
returnStdout: true,
|
||||
script: "${env.WORKSPACE}/scripts/version/gen_build_no.sh"
|
||||
).trim()
|
||||
println "Build Number: ${number}"
|
||||
return number
|
||||
}
|
||||
|
||||
def readBuildNumber() {
|
||||
def number = sh(
|
||||
returnStdout: true,
|
||||
script: "${env.WORKSPACE}/scripts/version/build_no.sh"
|
||||
).trim().toInteger()
|
||||
return number
|
||||
}
|
||||
|
||||
def getDirPath(path) {
|
||||
return path.tokenize('/')[0..-2].join('/')
|
||||
}
|
||||
|
||||
def getFilename(path) {
|
||||
return path.tokenize('/')[-1]
|
||||
}
|
||||
|
||||
def getEnv(build, envvar) {
|
||||
return build.getBuildVariables().get(envvar)
|
||||
}
|
||||
|
||||
def buildDuration() {
|
||||
def duration = currentBuild.durationString
|
||||
return '~' + duration.take(duration.lastIndexOf(' and counting'))
|
||||
}
|
||||
|
||||
def pkgFind(glob) {
|
||||
def fullGlob = "pkg/*${glob}"
|
||||
def found = findFiles(glob: fullGlob)
|
||||
if (found.size() == 0) {
|
||||
sh 'ls -l pkg/'
|
||||
error("File not found via glob: ${fullGlob} ${found.size()}")
|
||||
}
|
||||
return found[0].path
|
||||
}
|
||||
|
||||
def isPRBuild() {
|
||||
return env.JOB_NAME.startsWith('status-react/prs')
|
||||
}
|
||||
|
||||
def isE2EBuild() {
|
||||
return env.JOB_NAME.contains('e2e')
|
||||
}
|
||||
|
||||
def getBuildType() {
|
||||
def jobName = env.JOB_NAME
|
||||
if (isE2EBuild()) {
|
||||
return 'e2e'
|
||||
}
|
||||
if (isPRBuild()) {
|
||||
return 'pr'
|
||||
}
|
||||
if (jobName.startsWith('status-react/nightly')) {
|
||||
return 'nightly'
|
||||
}
|
||||
if (jobName.startsWith('status-react/release')) {
|
||||
return 'release'
|
||||
}
|
||||
return params.BUILD_TYPE
|
||||
}
|
||||
|
||||
def getParentRunEnv(name) {
|
||||
def c = currentBuild.rawBuild.getCause(hudson.model.Cause$UpstreamCause)
|
||||
if (c == null) { return null }
|
||||
return c.getUpstreamRun().getEnvironment()[name]
|
||||
}
|
||||
|
||||
def changeId() {
|
||||
/* CHANGE_ID can be provided via the build parameters or from parent */
|
||||
def changeId = env.CHANGE_ID
|
||||
changeId = params.CHANGE_ID ? params.CHANGE_ID : changeId
|
||||
changeId = getParentRunEnv('CHANGE_ID') ? getParentRunEnv('CHANGE_ID') : changeId
|
||||
if (!changeId) {
|
||||
println('This build is not related to a PR, CHANGE_ID missing.')
|
||||
println('GitHub notification impossible, skipping...')
|
||||
return null
|
||||
}
|
||||
return changeId
|
||||
}
|
||||
|
||||
def updateEnv(type) {
|
||||
def envFile = "${env.WORKSPACE}/.env.jenkins"
|
||||
/* select .env based on type of build */
|
||||
if (['nightly', 'release', 'e2e'].contains(type)) {
|
||||
envFile = "${env.WORKSPACE}/.env.${type}"
|
||||
}
|
||||
sh "ln -sf ${envFile} .env"
|
||||
/* show contents for debugging purposes */
|
||||
sh "cat ${envFile}"
|
||||
}
|
||||
|
||||
return this
|
||||
@@ -18,7 +18,7 @@
|
||||
"react-native-image-resizer"
|
||||
"react-native-image-crop-picker"
|
||||
"react-native-svg"
|
||||
"react-native-webview-bridge"
|
||||
"react-native-webview"
|
||||
"react-native-touch-id"
|
||||
"web3-utils"
|
||||
"chance"
|
||||
@@ -34,14 +34,21 @@
|
||||
"react-native/Libraries/vendor/emitter/EventEmitter"
|
||||
"react-native-background-timer"
|
||||
"react-native-fetch-polyfill"
|
||||
"react-navigation"
|
||||
"react-native-navigation-twopane"
|
||||
"@react-navigation/native"
|
||||
"@react-navigation/stack"
|
||||
"@react-navigation/bottom-tabs"
|
||||
;; "react-native-navigation-twopane"
|
||||
"hi-base32"
|
||||
"functional-red-black-tree"
|
||||
"react-native-mail"
|
||||
"react-native-shake"
|
||||
"@react-native-community/netinfo"
|
||||
"react-native-safe-area-context"]
|
||||
"react-native-gesture-handler"
|
||||
"react-native-reanimated"
|
||||
"react-native-redash"
|
||||
"react-native-haptic-feedback"
|
||||
"react-native-safe-area-context"
|
||||
"react-native-dark-mode"]
|
||||
;; Desktop modules
|
||||
:desktop-modules ["buffer"
|
||||
"bignumber.js"
|
||||
@@ -74,9 +81,8 @@
|
||||
"react-native-desktop-notification"
|
||||
"react-native-desktop-gesture-handler"
|
||||
"web3-utils"
|
||||
"react-navigation"
|
||||
"functional-red-black-tree"
|
||||
"react-native-navigation-twopane"
|
||||
;; "react-native-navigation-twopane"
|
||||
"hi-base32"]
|
||||
|
||||
;; Resoures
|
||||
|
||||
@@ -1,35 +1,47 @@
|
||||
(ns status-im.react-native.resources)
|
||||
(ns status-im.react-native.resources
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def ui
|
||||
{:empty-chats-header (js/require "./resources/images/ui/empty-chats-header.png")
|
||||
:welcome (js/require "./resources/images/ui/welcome.jpg")
|
||||
:intro1 (js/require "./resources/images/ui/intro1.jpg")
|
||||
:intro2 (js/require "./resources/images/ui/intro2.jpg")
|
||||
:intro3 (js/require "./resources/images/ui/intro3.jpg")
|
||||
:sample-key (js/require "./resources/images/ui/sample-key.jpg")
|
||||
:lock (js/require "./resources/images/ui/lock.png")
|
||||
:tribute-to-talk (js/require "./resources/images/ui/tribute-to-talk.png")
|
||||
:hardwallet-card (js/require "./resources/images/ui/hardwallet-card.png")
|
||||
:keycard-lock (js/require "./resources/images/ui/keycard-lock.png")
|
||||
:keycard (js/require "./resources/images/ui/keycard.png")
|
||||
:keycard-logo (js/require "./resources/images/ui/keycard-logo.png")
|
||||
:keycard-logo-blue (js/require "./resources/images/ui/keycard-logo-blue.png")
|
||||
:keycard-logo-gray (js/require "./resources/images/ui/keycard-logo-gray.png")
|
||||
:keycard-key (js/require "./resources/images/ui/keycard-key.png")
|
||||
:keycard-empty (js/require "./resources/images/ui/keycard-empty.png")
|
||||
:keycard-phone (js/require "./resources/images/ui/keycard-phone.png")
|
||||
:keycard-connection (js/require "./resources/images/ui/keycard-connection.png")
|
||||
:keycard-nfc-on (js/require "./resources/images/ui/keycard-nfc-on.png")
|
||||
:keycard-wrong (js/require "./resources/images/ui/keycard-wrong.png")
|
||||
:not-keycard (js/require "./resources/images/ui/not-keycard.png")
|
||||
:status-logo (js/require "./resources/images/ui/status-logo.png")
|
||||
:hold-card-animation (js/require "./resources/images/ui/hold-card-animation.gif")
|
||||
:warning-sign (js/require "./resources/images/ui/warning-sign.png")
|
||||
:phone-nfc-on (js/require "./resources/images/ui/phone-nfc-on.png")
|
||||
:phone-nfc-off (js/require "./resources/images/ui/phone-nfc-off.png")
|
||||
:dapp-store (js/require "./resources/images/ui/dapp-store.png")
|
||||
:ens-header (js/require "./resources/images/ui/ens-header.png")
|
||||
:new-chat-header (js/require "./resources/images/ui/new-chat-header.png")})
|
||||
{:empty-chats-header (js/require "./resources/images/ui/empty-chats-header.png")
|
||||
:welcome (js/require "./resources/images/ui/welcome.jpg")
|
||||
:welcome-dark (js/require "./resources/images/ui/welcome-dark.jpg")
|
||||
:chat (js/require "./resources/images/ui/chat.jpg")
|
||||
:wallet (js/require "./resources/images/ui/wallet.jpg")
|
||||
:browser (js/require "./resources/images/ui/browser.jpg")
|
||||
:chat-dark (js/require "./resources/images/ui/chat-dark.jpg")
|
||||
:wallet-dark (js/require "./resources/images/ui/wallet-dark.jpg")
|
||||
:browser-dark (js/require "./resources/images/ui/browser-dark.jpg")
|
||||
:keys (js/require "./resources/images/ui/keys.jpg")
|
||||
:keys-dark (js/require "./resources/images/ui/keys-dark.jpg")
|
||||
:lock (js/require "./resources/images/ui/lock.png")
|
||||
:tribute-to-talk (js/require "./resources/images/ui/tribute-to-talk.png")
|
||||
:hardwallet-card (js/require "./resources/images/ui/hardwallet-card.png")
|
||||
:keycard-lock (js/require "./resources/images/ui/keycard-lock.png")
|
||||
:keycard (js/require "./resources/images/ui/keycard.png")
|
||||
:keycard-logo (js/require "./resources/images/ui/keycard-logo.png")
|
||||
:keycard-logo-blue (js/require "./resources/images/ui/keycard-logo-blue.png")
|
||||
:keycard-logo-gray (js/require "./resources/images/ui/keycard-logo-gray.png")
|
||||
:keycard-key (js/require "./resources/images/ui/keycard-key.png")
|
||||
:keycard-empty (js/require "./resources/images/ui/keycard-empty.png")
|
||||
:keycard-phone (js/require "./resources/images/ui/keycard-phone.png")
|
||||
:keycard-connection (js/require "./resources/images/ui/keycard-connection.png")
|
||||
:keycard-wrong (js/require "./resources/images/ui/keycard-wrong.png")
|
||||
:not-keycard (js/require "./resources/images/ui/not-keycard.png")
|
||||
:status-logo (js/require "./resources/images/ui/status-logo.png")
|
||||
:warning-sign (js/require "./resources/images/ui/warning-sign.png")
|
||||
:phone-nfc-on (js/require "./resources/images/ui/phone-nfc-on.png")
|
||||
:phone-nfc-off (js/require "./resources/images/ui/phone-nfc-off.png")
|
||||
:dapp-store (js/require "./resources/images/ui/dapp-store.png")
|
||||
:ens-header (js/require "./resources/images/ui/ens-header.png")
|
||||
:ens-header-dark (js/require "./resources/images/ui/ens-header-dark.png")
|
||||
:new-chat-header (js/require "./resources/images/ui/new-chat-header.png")
|
||||
:onboarding-phone (js/require "./resources/images/ui/onboarding-phone.png")
|
||||
:theme-dark (js/require "./resources/images/ui/theme-dark.png")
|
||||
:theme-light (js/require "./resources/images/ui/theme-light.png")
|
||||
:theme-system (js/require "./resources/images/ui/theme-system.png")})
|
||||
|
||||
(defn get-theme-image [k]
|
||||
(get ui (when (colors/dark?) (keyword (str (name k) "-dark"))) (get ui k)))
|
||||
|
||||
(def loaded-images (atom {}))
|
||||
|
||||
|
||||
@@ -70,6 +70,11 @@
|
||||
(defn activity-indicator [props]
|
||||
[activity-indicator-class props])
|
||||
|
||||
(defn small-loading-indicator [color]
|
||||
[activity-indicator {:color (if color color :colors/gray)
|
||||
:ios {:size :small}
|
||||
:android {:size :16}}])
|
||||
|
||||
(def modal (get-class "Modal"))
|
||||
|
||||
(def pan-responder (.-PanResponder js-dependencies/react-native))
|
||||
@@ -171,7 +176,8 @@
|
||||
[text {:style style} (i18n/label key)])
|
||||
|
||||
(defn icon
|
||||
([n] (icon n styles/icon-default))
|
||||
([n] (icon n {:width 24
|
||||
:height 24}))
|
||||
([n style]
|
||||
[image {:source {:uri (keyword (str "icon_" (name n)))}
|
||||
:resizeMode "contain"
|
||||
@@ -246,10 +252,9 @@
|
||||
;; KeyboardAvoidingView
|
||||
|
||||
(defn keyboard-avoiding-view [props & children]
|
||||
(let [view-element (if platform/ios?
|
||||
[keyboard-avoiding-view-class (merge {:behavior :padding} props)]
|
||||
[view props])]
|
||||
(vec (concat view-element children))))
|
||||
(into [keyboard-avoiding-view-class
|
||||
(merge (when platform/ios? {:behavior :padding}) props)]
|
||||
children))
|
||||
|
||||
(defn scroll-view [props & children]
|
||||
(vec (conj children props scroll-view-class)))
|
||||
@@ -271,52 +276,10 @@
|
||||
[activity-indicator {:animating true}]])
|
||||
comp)))
|
||||
|
||||
(defn navigation-wrapper
|
||||
"Wraps component so that it will be shown only when current-screen is one of views"
|
||||
[{:keys [component views current-view hide?]
|
||||
:or {hide? false}}]
|
||||
(let [current-view? (if (set? views)
|
||||
(views current-view)
|
||||
(= views current-view))
|
||||
|
||||
style (if current-view?
|
||||
{:flex 1
|
||||
:zIndex 0}
|
||||
{:opacity 0
|
||||
:flex 0
|
||||
:zIndex -1})
|
||||
|
||||
component' (if (fn? component) [component] component)]
|
||||
|
||||
(when (or (not hide?) (and hide? current-view?))
|
||||
(if hide?
|
||||
component'
|
||||
[view style (if (fn? component) [component] component)]))))
|
||||
|
||||
(defn with-empty-preview [comp]
|
||||
[with-activity-indicator
|
||||
{:preview [view {}]}
|
||||
comp])
|
||||
|
||||
(def safe-area-provider (adapt-class (object/get js-dependencies/safe-area-context "SafeAreaProvider")))
|
||||
(def safe-area-consumer (adapt-class (object/get js-dependencies/safe-area-context "SafeAreaConsumer")))
|
||||
|
||||
(defn create-main-screen-view [current-view]
|
||||
(fn [props & children]
|
||||
(apply
|
||||
vector
|
||||
(adapt-class (object/get js-dependencies/safe-area-context "SafeAreaView"))
|
||||
(cond-> props
|
||||
(= current-view :qr-scanner)
|
||||
(assoc :background-color :black))
|
||||
children)))
|
||||
(def safe-area-view (adapt-class (object/get js-dependencies/safe-area-context "SafeAreaView")))
|
||||
|
||||
(defn main-screen-modal-view [current-view & components]
|
||||
[(create-main-screen-view current-view)
|
||||
styles/flex
|
||||
[(if (= current-view :chat-modal)
|
||||
view
|
||||
keyboard-avoiding-view)
|
||||
(merge {:flex 1 :flex-direction :column}
|
||||
(when platform/android?
|
||||
{:background-color :white}))
|
||||
(apply vector view styles/flex components)]])
|
||||
|
||||
(def touchable-without-feedback-gesture (adapt-class (object/get js-dependencies/react-native-gesture-handler "TouchableWithoutFeedback")))
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
:sha "b0d3b0f016f217c6a397a54e5eba9486471fb172"
|
||||
:deps/manifest :deps}
|
||||
com.andrewmcveigh/cljs-time {:mvn/version "0.5.2"}
|
||||
binaryage/oops {:mvn/version "0.7.0"}
|
||||
status-im/timbre {:mvn/version "4.10.0-2-status"}
|
||||
com.taoensso/encore {:mvn/version "2.94.0"}
|
||||
hickory {:mvn/version "0.7.1"}
|
||||
cljs-bean {:mvn/version "1.3.0"}
|
||||
mvxcvi/alphabase {:mvn/version "1.0.0"}
|
||||
rasom/cljs-react-navigation {:mvn/version "0.1.4"}}
|
||||
mvxcvi/alphabase {:mvn/version "1.0.0"}}
|
||||
|
||||
:aliases
|
||||
{:dev {:extra-deps
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
;; translations
|
||||
(def translations-by-locale
|
||||
(->> (i18n/translations [:en :es_419 :fa :ko :ms :pl :ru :zh :zh_Hans_CN])
|
||||
(->> (i18n/translations [:ar :en :es :es_419 :fil :fr :it :ko :ru :in :id :tr :zh :zh_Hant :zh_TW])
|
||||
(map (fn [[k t]]
|
||||
(let [k' (-> (name k)
|
||||
(string/replace "_" "-")
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
(ns env.config)
|
||||
|
||||
(def figwheel-urls {:android "ws://localhost:3449/figwheel-ws",
|
||||
:ios "ws://192.168.0.9:3449/figwheel-ws",
|
||||
:desktop "ws://localhost:3449/figwheel-ws"}
|
||||
)
|
||||
@@ -218,6 +218,7 @@ var TopLevel = {
|
||||
"injectJavaScript" : function () {},
|
||||
"installApplet" : function () {},
|
||||
"installAppletAndInitCard" : function () {},
|
||||
"installCashApplet" : function () {},
|
||||
"Int8Array" : function () {},
|
||||
"integer" : function () {},
|
||||
"interpolate" : function () {},
|
||||
@@ -489,8 +490,10 @@ var TopLevel = {
|
||||
"showActionSheetWithOptions" : function () {},
|
||||
"showPicker" : function () {},
|
||||
"sign" : function () {},
|
||||
"signWithPath" : function () {},
|
||||
"signGroupMembership" : function () {},
|
||||
"signMessage" : function () {},
|
||||
"signPinless" : function () {},
|
||||
"signTypedData" : function () {},
|
||||
"slice" : function () {},
|
||||
"SplashScreen" : function () {},
|
||||
@@ -551,6 +554,7 @@ var TopLevel = {
|
||||
"Uri" : function () {},
|
||||
"url" : function () {},
|
||||
"Value" : function () {},
|
||||
"ValueXY": function() {},
|
||||
"value" : function () {},
|
||||
"verify" : function () {},
|
||||
"verifyPin" : function () {},
|
||||
@@ -558,10 +562,10 @@ var TopLevel = {
|
||||
"version" : function () {},
|
||||
"vibrate" : function () {},
|
||||
"View" : function () {},
|
||||
"viewableItems": function() {},
|
||||
"FlatList" : function () {},
|
||||
"warn" : function () {},
|
||||
"WebView" : function () {},
|
||||
"WebViewBridgeModule" : function () {},
|
||||
"width" : function () {},
|
||||
"window" : function () {},
|
||||
"writeCopyTo" : function () {},
|
||||
@@ -618,5 +622,6 @@ var TopLevel = {
|
||||
"multiAccountLoadAccount" : function () {},
|
||||
"multiAccountStoreAccount" : function () {},
|
||||
"multiAccountImportMnemonic" : function () {},
|
||||
"multiAccountImportPrivateKey" : function () {},
|
||||
"validateMnemonic" : function () {}
|
||||
}
|
||||
|
||||
@@ -222,9 +222,9 @@ platform :ios do
|
||||
lane :clean do
|
||||
clean_testflight_testers(
|
||||
username: ENV['FASTLANE_APPLE_ID'],
|
||||
days_of_inactivity: 30,
|
||||
oldest_build_allowed: 2_019_032_709
|
||||
days_of_inactivity: 30
|
||||
)
|
||||
# In the future we can try using 'oldest_build_allowed'
|
||||
end
|
||||
|
||||
desc '`fastlane ios upload-diawi` - upload .ipa to diawi'
|
||||
|
||||
@@ -19,4 +19,4 @@ Wir wünschen uns eine Welt, in der die Menschen mehr Kontrolle über den Wert h
|
||||
|
||||
|
||||
<b>Machen Sie mit</b>
|
||||
Als Open-Source-Projekt sind das Downloaden und Testen von Status die beste Möglichkeit, an der Entwicklung beteiligt zu sein. Mithilfe des neuen Vertreters des Ethereum-Paradigmas wollen wir den Übergang zu einem offeneren Internet- und Finanzsystem erleichtern. Mit den hochgesteckten Zielen, unser kollektives Menschenrecht auf Privatsphäre zu bewahren, das Zensur-Risiko zu entschärfen und wirtschaftlichen Handel auf transparente, offene Art und Weise zu fördern, bildet Status eine Gemeinschaft, in der jeder willkommen ist, der beitreten und seinen Beitrag leisten möchte. Wir würden uns sehr freuen, von Ihnen zu hören. Besuchen Sie uns auf https://get.status.im/chat/public/status
|
||||
Als Open-Source-Projekt sind das Downloaden und Testen von Status die beste Möglichkeit, an der Entwicklung beteiligt zu sein. Mithilfe des neuen Vertreters des Ethereum-Paradigmas wollen wir den Übergang zu einem offeneren Internet- und Finanzsystem erleichtern. Mit den hochgesteckten Zielen, unser kollektives Menschenrecht auf Privatsphäre zu bewahren, das Zensur-Risiko zu entschärfen und wirtschaftlichen Handel auf transparente, offene Art und Weise zu fördern, bildet Status eine Gemeinschaft, in der jeder willkommen ist, der beitreten und seinen Beitrag leisten möchte. Wir würden uns sehr freuen, von Ihnen zu hören. Besuchen Sie uns auf https://join.status.im/chat/public/status
|
||||
|
||||
@@ -19,4 +19,4 @@ We want to see a world in which people have more control over the value they cre
|
||||
|
||||
|
||||
<b>Get Involved</b>
|
||||
As an open source project, the single best way to get involved with development is to download and test Status. Our mission is to facilitate the transition to a more open internet and financial system through the new paradigm Ethereum represent. With the high level goals of preserving our collective right as humans to privacy, mitigating the risk of censorship, and promoting economic trade in a transparent, open manner, Status is building a community where anyone is welcome to join and contribute to the cause. We’d love to hear from you. Join us at: https://get.status.im/chat/public/status
|
||||
As an open source project, the single best way to get involved with development is to download and test Status. Our mission is to facilitate the transition to a more open internet and financial system through the new paradigm Ethereum represent. With the high level goals of preserving our collective right as humans to privacy, mitigating the risk of censorship, and promoting economic trade in a transparent, open manner, Status is building a community where anyone is welcome to join and contribute to the cause. We’d love to hear from you. Join us at: https://join.status.im/chat/public/status
|
||||
@@ -29,4 +29,4 @@
|
||||
|
||||
|
||||
به عنوان یک پروژهی کدباز، بهترین راه مشارکت در توسعهی اپلیکیشن این است که آن را دانلود و تست کنید. هدف ما تسهیل عبور به یک اینترنت و سیستم مالی بازتر به وسیلهی پارادایمی که اتریوم فراهم میکند است. با هدفهای سطح بالای حفظ حق عمومی انسانی برای حریم خصوصی، کم کردن ریسک سانسور، و گسترش تبادل اقتصادی به شیوهی باز و شفاف، استاتوس در حال ساخت جامعهای است که در آن همه به ورود و مشارکت دعوت میشوند.
|
||||
https://get.status.im/chat/public/status
|
||||
https://join.status.im/chat/public/status
|
||||
@@ -19,4 +19,4 @@ Nous voulons voir un monde dans lequel les gens ont plus de contrôle sur la val
|
||||
|
||||
|
||||
<b>Impliquez-vous</b>
|
||||
En tant que projet open source, la meilleure façon de participer au développement est de télécharger et de tester Status. Notre mission est de faciliter la transition vers un Internet et un système financier plus ouverts à travers le nouveau paradigme que représente Ethereum. Avec les objectifs de haut niveau de la préservation de notre droit collectif en tant qu'êtres humains à la vie privée, atténuant le risque de censure et encourageant le commerce économique de manière transparente et ouverte, Status construit une communauté que tout le monde est invité à rejoindre et où chacun peut contribuer à la cause. Nous aimerions recevoir de vos nouvelles. Rejoignez-nous sur : https://get.status.im/chat/public/status
|
||||
En tant que projet open source, la meilleure façon de participer au développement est de télécharger et de tester Status. Notre mission est de faciliter la transition vers un Internet et un système financier plus ouverts à travers le nouveau paradigme que représente Ethereum. Avec les objectifs de haut niveau de la préservation de notre droit collectif en tant qu'êtres humains à la vie privée, atténuant le risque de censure et encourageant le commerce économique de manière transparente et ouverte, Status construit une communauté que tout le monde est invité à rejoindre et où chacun peut contribuer à la cause. Nous aimerions recevoir de vos nouvelles. Rejoignez-nous sur : https://join.status.im/chat/public/status
|
||||
@@ -19,4 +19,4 @@
|
||||
|
||||
|
||||
<b>参加しよう</b>
|
||||
オープンソースプロジェクトの開発に関わる最良の方法は、Statusをダウンロードしてテストをすることです。当社は、イーサリアムがもたらす新たな可能性をもとに、よりオープンなインターネット世界と金融システムへの移行を推し進めています。個人情報の保護、検閲リスクの軽減、より透明性のあるオープンな方法に基づく取引の推進など高次元の目標の下、Statusでは誰でも参加でき、目的に沿った活動がとれるコミュニティの構築を進めています。皆様のご意見をぜひお聞かせください。ご連絡はこちら: https://get.status.im/chat/public/status
|
||||
オープンソースプロジェクトの開発に関わる最良の方法は、Statusをダウンロードしてテストをすることです。当社は、イーサリアムがもたらす新たな可能性をもとに、よりオープンなインターネット世界と金融システムへの移行を推し進めています。個人情報の保護、検閲リスクの軽減、より透明性のあるオープンな方法に基づく取引の推進など高次元の目標の下、Statusでは誰でも参加でき、目的に沿った活動がとれるコミュニティの構築を進めています。皆様のご意見をぜひお聞かせください。ご連絡はこちら: https://join.status.im/chat/public/status
|
||||
@@ -20,4 +20,4 @@
|
||||
|
||||
|
||||
<b>참여하기</b>
|
||||
어플리케이션을 다운로드 받아 테스트하며, 스테이터스 오픈소스 프로젝트에 참여하실 수 있습니다. 우리의 비전은 이더리움이 제시하는 새로운 인터넷 패러다임을 통해 인터넷과 금융 시스템이 조금 더 개방적으로 변모할 수 있도록 하는 것입니다. 스테이터스의 궁극적 목표는 사람들의 소중한 프라이버시를 지키고 검열로부터 보호하며, 더욱 투명하고 개방된 방식의 거래를 촉진하는 것입니다. 이를 위해 스테이터스는 누구든지 참여해 혁신적인 변화를 이끌어가는 커뮤니티를 구축하고 있습니다. 여러분의 연락을 기다리고 있습니다. https://get.status.im/chat/public/status 에 참여하세요!
|
||||
어플리케이션을 다운로드 받아 테스트하며, 스테이터스 오픈소스 프로젝트에 참여하실 수 있습니다. 우리의 비전은 이더리움이 제시하는 새로운 인터넷 패러다임을 통해 인터넷과 금융 시스템이 조금 더 개방적으로 변모할 수 있도록 하는 것입니다. 스테이터스의 궁극적 목표는 사람들의 소중한 프라이버시를 지키고 검열로부터 보호하며, 더욱 투명하고 개방된 방식의 거래를 촉진하는 것입니다. 이를 위해 스테이터스는 누구든지 참여해 혁신적인 변화를 이끌어가는 커뮤니티를 구축하고 있습니다. 여러분의 연락을 기다리고 있습니다. https://join.status.im/chat/public/status 에 참여하세요!
|
||||
|
||||
@@ -19,4 +19,4 @@ Quer conhecer um mundo no qual as pessoas têm mais controle sobre o valor que c
|
||||
|
||||
|
||||
<b>Envolva-se</b>
|
||||
Como um projeto de código aberto, a melhor maneira de se envolver com o desenvolvimento é baixar e testar o Status. Nossa missão é facilitar a transição para uma internet e um sistema financeiro mais abertos, por meio do novo paradigma que o Ethereum representa. Com os objetivos de alto nível de preservar nossos direitos coletivos como seres humanos à privacidade, mitigar o risco de censura e promover comercialização economicamente viável de maneira aberta e transparente o Status está construindo uma comunidade na qual todos são bem-vindos para se juntarem e contribuírem com a causa. Adoraríamos falar com você. Junte-se a nós em: https://get.status.im/chat/public/status
|
||||
Como um projeto de código aberto, a melhor maneira de se envolver com o desenvolvimento é baixar e testar o Status. Nossa missão é facilitar a transição para uma internet e um sistema financeiro mais abertos, por meio do novo paradigma que o Ethereum representa. Com os objetivos de alto nível de preservar nossos direitos coletivos como seres humanos à privacidade, mitigar o risco de censura e promover comercialização economicamente viável de maneira aberta e transparente o Status está construindo uma comunidade na qual todos são bem-vindos para se juntarem e contribuírem com a causa. Adoraríamos falar com você. Junte-se a nós em: https://join.status.im/chat/public/status
|
||||
@@ -19,4 +19,4 @@ Queres conhecer um mundo no qual as pessoas têm mais controle sobre o valor que
|
||||
|
||||
|
||||
<b>Envolve-te</b>
|
||||
Sendo um projeto Open Source, a melhor maneira de se envolver com o desenvolvimento é fazer download e testar o cliente Status. A nossa missão é facilitar a transição para uma Internet e um sistema financeiro mais abertos, através do novo paradigma que o Ethereum representa. Partindo de uma a filosofia de preservar nossos direitos coletivos como seres humanos à privacidade, mitigar o risco de censura e promover comercialização economicamente viável de maneira aberta e transparente, a Status está a construir uma comunidade na qual todos são bem-vindos para se juntarem e contribuírem para a causa. Adoraríamos falar contigo. Junta-te a nós em: https://get.status.im/chat/public/status
|
||||
Sendo um projeto Open Source, a melhor maneira de se envolver com o desenvolvimento é fazer download e testar o cliente Status. A nossa missão é facilitar a transição para uma Internet e um sistema financeiro mais abertos, através do novo paradigma que o Ethereum representa. Partindo de uma a filosofia de preservar nossos direitos coletivos como seres humanos à privacidade, mitigar o risco de censura e promover comercialização economicamente viável de maneira aberta e transparente, a Status está a construir uma comunidade na qual todos são bem-vindos para se juntarem e contribuírem para a causa. Adoraríamos falar contigo. Junta-te a nós em: https://join.status.im/chat/public/status
|
||||
@@ -19,4 +19,4 @@ Status - программа с открытым исходным кодом на
|
||||
|
||||
|
||||
<b>Присоединяйтесь к нам</b>
|
||||
Самый лучший способ принять участие в разработке нашей платформы — это загрузить и протестировать Status. Наша миссия состоит в том, чтобы облегчить переход к более открытому интернету и финансовой системе на основе новой парадигмы, которую представляет Ethereum. Ставя перед собой высокую цель сохранения права людей на частную жизнь, снижения риска цензуры, а также содействия экономической торговле в прозрачной, открытой манере, Status строит сообщество, где любой желающий может присоединиться и внести свой вклад в общее дело. Мы хотели бы услышать ваш голос. Присоединяйтесь к нам: https://get.status.im/chat/public/status
|
||||
Самый лучший способ принять участие в разработке нашей платформы — это загрузить и протестировать Status. Наша миссия состоит в том, чтобы облегчить переход к более открытому интернету и финансовой системе на основе новой парадигмы, которую представляет Ethereum. Ставя перед собой высокую цель сохранения права людей на частную жизнь, снижения риска цензуры, а также содействия экономической торговле в прозрачной, открытой манере, Status строит сообщество, где любой желающий может присоединиться и внести свой вклад в общее дело. Мы хотели бы услышать ваш голос. Присоединяйтесь к нам: https://join.status.im/chat/public/status
|
||||
@@ -19,4 +19,4 @@ Status 是一个开源的、基于以太坊的应用程序,能够让您聊天
|
||||
|
||||
|
||||
<b>参与其中</b>
|
||||
作为一个开源项目,最好的参与开发的途径就是下载并测试Status。我们的使命是通过以太坊所代表的新范式,实现向更加开放的网络和金融系统的转变。我们的最高目标就是将隐私作为人类的集体权利,降低审查的风险,并以一种透明的、开放的态度来推进经济贸易。Status 正在建设的社区欢迎任何人加入并为此事业做出贡献。我们非常愿意得到你们的反馈。请通过https://get.status.im/chat/public/status 加入我们。
|
||||
作为一个开源项目,最好的参与开发的途径就是下载并测试Status。我们的使命是通过以太坊所代表的新范式,实现向更加开放的网络和金融系统的转变。我们的最高目标就是将隐私作为人类的集体权利,降低审查的风险,并以一种透明的、开放的态度来推进经济贸易。Status 正在建设的社区欢迎任何人加入并为此事业做出贡献。我们非常愿意得到你们的反馈。请通过https://join.status.im/chat/public/status 加入我们。
|
||||
@@ -20,7 +20,6 @@
|
||||
:DeviceEventEmitter #js {:addListener (fn [])}
|
||||
:Dimensions #js {:get (fn [])}})
|
||||
(def vector-icons (fn [] #js {:default #js {}}))
|
||||
(def webview-bridge (fn [] #js {:default #js {}}))
|
||||
(def webview (fn [] #js {:WebView #js {}}))
|
||||
(def touchid (fn [] #js {}))
|
||||
(def svg (fn [] #js {:default #js {}}))
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
:keycard-empty "images/ui/keycard-empty.png"
|
||||
:keycard-phone "images/ui/keycard-phone.png"
|
||||
:keycard-connection "images/ui/keycard-connection.png"
|
||||
:keycard-nfc-on "images/ui/keycard-nfc-on.png"
|
||||
:keycard-wrong "images/ui/keycard-wrong.png"
|
||||
:not-keycard "images/ui/not-keycard.png"
|
||||
:status-logo "images/ui/status-logo.png"
|
||||
|
||||
@@ -324,8 +324,6 @@
|
||||
(views/letsubs []
|
||||
(let [main-screen-view (create-main-screen-view current-view)]
|
||||
[main-screen-view styles/flex
|
||||
[(if (= current-view :chat-modal)
|
||||
view
|
||||
keyboard-avoiding-view)
|
||||
[keyboard-avoiding-view
|
||||
{:flex 1 :flex-direction :column}
|
||||
(apply vector view styles/flex components)]])))
|
||||
|
||||
@@ -45,6 +45,7 @@ target 'StatusIm' do
|
||||
pod 'SQLCipher', '~>3.0'
|
||||
pod 'SSZipArchive'
|
||||
|
||||
|
||||
target 'StatusImTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
|
||||
@@ -199,15 +199,13 @@ PODS:
|
||||
- React
|
||||
- react-native-netinfo (4.4.0):
|
||||
- React
|
||||
- react-native-safe-area-context (0.6.0):
|
||||
- react-native-safe-area-context (0.7.3):
|
||||
- React
|
||||
- react-native-shake (3.4.0):
|
||||
- React
|
||||
- react-native-splash-screen (3.2.0):
|
||||
- React
|
||||
- react-native-webview (6.11.1):
|
||||
- React
|
||||
- react-native-webview-bridge (0.33.17):
|
||||
- react-native-webview (8.0.7):
|
||||
- React
|
||||
- React-RCTActionSheet (0.61.5):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.61.5)
|
||||
@@ -244,9 +242,13 @@ PODS:
|
||||
- React-cxxreact (= 0.61.5)
|
||||
- React-jsi (= 0.61.5)
|
||||
- ReactCommon/jscallinvoker (= 0.61.5)
|
||||
- ReactNativeDarkMode (0.2.2):
|
||||
- React
|
||||
- RNCMaskedView (0.1.6):
|
||||
- React
|
||||
- RNFS (2.14.1):
|
||||
- React
|
||||
- RNGestureHandler (1.5.2):
|
||||
- RNGestureHandler (1.6.0):
|
||||
- React
|
||||
- RNImageCropPicker (0.25.3):
|
||||
- QBImagePickerController
|
||||
@@ -257,7 +259,11 @@ PODS:
|
||||
- React
|
||||
- RNLanguages (3.0.2):
|
||||
- React
|
||||
- RNScreens (1.0.0-alpha.23):
|
||||
- RNReactNativeHapticFeedback (1.9.0):
|
||||
- React
|
||||
- RNReanimated (1.7.0):
|
||||
- React
|
||||
- RNScreens (2.3.0):
|
||||
- React
|
||||
- RNSVG (9.11.1):
|
||||
- React
|
||||
@@ -298,7 +304,6 @@ DEPENDENCIES:
|
||||
- react-native-shake (from `../node_modules/react-native-shake`)
|
||||
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||
- react-native-webview (from `../node_modules/react-native-webview`)
|
||||
- react-native-webview-bridge (from `../node_modules/react-native-webview-bridge`)
|
||||
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
|
||||
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
|
||||
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
|
||||
@@ -310,11 +315,15 @@ DEPENDENCIES:
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- ReactNativeDarkMode (from `../node_modules/react-native-dark-mode`)
|
||||
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
- RNKeychain (from `../node_modules/react-native-keychain`)
|
||||
- RNLanguages (from `../node_modules/react-native-languages`)
|
||||
- RNReactNativeHapticFeedback (from `../node_modules/react-native-haptic-feedback`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
- RNScreens (from `../node_modules/react-native-screens`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- SQLCipher (~> 3.0)
|
||||
@@ -377,8 +386,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-splash-screen"
|
||||
react-native-webview:
|
||||
:path: "../node_modules/react-native-webview"
|
||||
react-native-webview-bridge:
|
||||
:path: "../node_modules/react-native-webview-bridge"
|
||||
React-RCTActionSheet:
|
||||
:path: "../node_modules/react-native/Libraries/ActionSheetIOS"
|
||||
React-RCTAnimation:
|
||||
@@ -399,6 +406,10 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/Vibration"
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
ReactNativeDarkMode:
|
||||
:path: "../node_modules/react-native-dark-mode"
|
||||
RNCMaskedView:
|
||||
:path: "../node_modules/@react-native-community/masked-view"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
@@ -409,6 +420,10 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-keychain"
|
||||
RNLanguages:
|
||||
:path: "../node_modules/react-native-languages"
|
||||
RNReactNativeHapticFeedback:
|
||||
:path: "../node_modules/react-native-haptic-feedback"
|
||||
RNReanimated:
|
||||
:path: "../node_modules/react-native-reanimated"
|
||||
RNScreens:
|
||||
:path: "../node_modules/react-native-screens"
|
||||
RNSVG:
|
||||
@@ -440,11 +455,10 @@ SPEC CHECKSUMS:
|
||||
react-native-image-resizer: 4516052af6ae0248caf4ccf356caecefe60072d7
|
||||
react-native-mail: 7e37dfbe93ff0d4c7df346b738854dbed533e86f
|
||||
react-native-netinfo: 6bb847e64f45a2d69c6173741111cfd95c669301
|
||||
react-native-safe-area-context: d288138da2c800caa111f9352e9333f186a06ead
|
||||
react-native-safe-area-context: e200d4433aba6b7e60b52da5f37af11f7a0b0392
|
||||
react-native-shake: de052eaa3eadc4a326b8ddd7ac80c06e8d84528c
|
||||
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
||||
react-native-webview: 0658813bcc4b6c22f3cbb035a2227aa896a8cbc0
|
||||
react-native-webview-bridge: 3023f6b0e84cdf8e4a96511d2b04e73b038f95f0
|
||||
react-native-webview: f51a7a42278b01b07464a65c586aa0086c1e741e
|
||||
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
|
||||
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
|
||||
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
|
||||
@@ -455,12 +469,16 @@ SPEC CHECKSUMS:
|
||||
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
|
||||
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
|
||||
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
|
||||
ReactNativeDarkMode: 0178ffca3b10f6a7c9f49d6f9810232b328fa949
|
||||
RNCMaskedView: a88953beefbd347a29072d9eba90e42945fe291e
|
||||
RNFS: a8fbe7060fa49157d819466404794ad9c58e58cf
|
||||
RNGestureHandler: 946a7691e41df61e2c4b1884deab41a4cdc3afff
|
||||
RNGestureHandler: dde546180bf24af0b5f737c8ad04b6f3fa51609a
|
||||
RNImageCropPicker: bfb3ea9c8622f290532e2fe63f369e0d5a52f597
|
||||
RNKeychain: 216f37338fcb9e5c3a2530f1e3295f737a690cb1
|
||||
RNLanguages: 962e562af0d34ab1958d89bcfdb64fafc37c513e
|
||||
RNScreens: f28b48b8345f2f5f39ed6195518291515032a788
|
||||
RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071
|
||||
RNReanimated: 031fe8d9ea93c2bd689a40f05320ef9d96f74d7f
|
||||
RNScreens: 03bf608b92ac0acf323f47d8f5b63a8f829340c8
|
||||
RNSVG: be27aa7c58819f97399388ae53d7fa0572f32c7f
|
||||
RSKImageCropper: a446db0e8444a036b34f3c43db01b2373baa4b2a
|
||||
SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990
|
||||
@@ -468,6 +486,6 @@ SPEC CHECKSUMS:
|
||||
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
|
||||
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
|
||||
|
||||
PODFILE CHECKSUM: 0483a7693bfa7c6ef9f214cdc7f614f67dec7448
|
||||
PODFILE CHECKSUM: 37924c57abbfcd77aec07d65c45ecba137cdf289
|
||||
|
||||
COCOAPODS: 1.8.4
|
||||
|
||||
@@ -647,6 +647,7 @@
|
||||
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
|
||||
"$(SRCROOT)/../node_modules/react-native-splash-screen/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-config/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-webview/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS",
|
||||
);
|
||||
INFOPLIST_FILE = StatusIm/Info.plist;
|
||||
@@ -696,6 +697,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-camera/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-webview/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-fs/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-languages/RNLanguages",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
@@ -782,6 +784,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-camera/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-webview/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-fs/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-languages/RNLanguages",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
@@ -845,6 +848,7 @@
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../node_modules/react-native/React/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-camera/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-webview/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-fs/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-languages/RNLanguages",
|
||||
"$(SRCROOT)/../modules/react-native-status/ios/RCTStatus/**",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "appearance.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "appearance@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "appearance@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 694 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "arrow_down.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "arrow_down@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "arrow_down@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 202 B |
|
After Width: | Height: | Size: 286 B |
|
After Width: | Height: | Size: 380 B |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "keycard_logo_big.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "keycard_logo_big@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "keycard_logo_big@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 598 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "nfc.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "nfc-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "nfc-2.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.5 KiB |