Compare commits

..
607 changed files with 15423 additions and 12440 deletions
+12 -13
View File
@@ -16,19 +16,18 @@
:clj-kondo-config {:level :error}
:cond-else {:level :error}
:consistent-alias {:level :error
:aliases {clojure.set set
clojure.string string
clojure.walk walk
malli.core malli
malli.dev.pretty malli.pretty
malli.dev.virhe malli.virhe
malli.error malli.error
malli.generator malli.generator
malli.transform malli.transform
malli.util malli.util
schema.core schema
status-im.feature-flags ff
taoensso.timbre log}}
:aliases {clojure.set set
clojure.string string
clojure.walk walk
malli.core malli
malli.dev.pretty malli.pretty
malli.dev.virhe malli.virhe
malli.error malli.error
malli.generator malli.generator
malli.transform malli.transform
malli.util malli.util
schema.core schema
taoensso.timbre log}}
:deprecated-namespace {:level :warning}
:docstring-blank {:level :error}
:equals-true {:level :error}
-1
View File
@@ -34,4 +34,3 @@ STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1
TEST_STATEOFUS=1
FAST_CREATE_COMMUNITY_ENABLED=1
FLAG_NEW_CONTACT_UI_ENABLED=0
-3
View File
@@ -194,6 +194,3 @@ test/appium/tests/users.py
## git hooks
lefthook.yml
## build time logs
/logs/*.log
+27 -38
View File
@@ -36,8 +36,6 @@ endif
export TMPDIR = /tmp/tmp-status-mobile-$(BUILD_TAG)
# This has to be specified for both the Node.JS server process and the Qt process.
export REACT_SERVER_PORT ?= 5001
# Default metro port used by scripts/run-android.sh.
export RCT_METRO_PORT ?= 8081
# Fix for ERR_OSSL_EVP_UNSUPPORTED error.
export NODE_OPTIONS += --openssl-legacy-provider
# The path can be anything, but home is usually safest.
@@ -46,7 +44,7 @@ export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
# Our custom config is located in nix/nix.conf
export NIX_USER_CONF_FILES = $(PWD)/nix/nix.conf
# Location of symlinks to derivations that should not be garbage collected
export _NIX_GCROOTS = ./.nix-gcroots
export _NIX_GCROOTS = /nix/var/nix/gcroots/per-user/$(USER)/status-mobile
# Defines which variables will be kept for Nix pure shell, use semicolon as divider
export _NIX_KEEP ?= TMPDIR,BUILD_ENV,\
BUILD_TYPE,BUILD_NUMBER,COMMIT_HASH,\
@@ -56,6 +54,12 @@ export _NIX_KEEP ?= TMPDIR,BUILD_ENV,\
# Useful for Android 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)
export NIX_IGNORE_SYMLINK_STORE=1
endif
#----------------
# Nix targets
#----------------
@@ -156,12 +160,10 @@ pod-install: export TARGET := ios
pod-install: ##@prepare Run 'pod install' to install podfiles and update Podfile.lock
cd ios && pod install; cd --
FLEETS_FILE := ./resources/config/fleets.json
update-fleets: ##@prepare Download up-to-date JSON file with current fleets state
curl -s https://fleets.status.im/ \
| sed 's/"warning": "/"warning": "DO NOT EDIT! /' \
> $(FLEETS_FILE)
echo >> $(FLEETS_FILE)
> resources/config/fleets.json
$(KEYSTORE_PATH): export TARGET := keytool
$(KEYSTORE_PATH):
@@ -210,7 +212,7 @@ build-fdroid: ##@build Build release for F-Droid
build-android: export BUILD_ENV ?= prod
build-android: export BUILD_TYPE ?= nightly
build-android: export ORG_GRADLE_PROJECT_versionCode ?= $(TMP_BUILD_NUMBER)
build-android: export BUILD_NUMBER ?= $(TMP_BUILD_NUMBER)
build-android: export ANDROID_ABI_SPLIT ?= false
build-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
build-android: ##@build Build unsigned Android APK
@@ -263,7 +265,7 @@ run-clojure: ##@run Watch for and build Clojure changes for mobile
run-metro: export TARGET := clojure
run-metro: ##@run Start Metro to build React Native changes
@scripts/run-metro.sh
@scripts/start-react-native.sh
run-re-frisk: export TARGET := clojure
run-re-frisk: ##@run Start re-frisk server
@@ -271,18 +273,22 @@ run-re-frisk: ##@run Start re-frisk server
# TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix
run-android: export TARGET := android
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
run-android: export ORG_GRADLE_PROJECT_hermesEnabled := false
# INFO: If it's empty (no devices attached, parsing issues, script error) - for Nix it's the same as not set.
run-android: export ANDROID_ABI_INCLUDE ?= $(shell ./scripts/adb_devices_abis.sh)
run-android: ##@run Build Android APK and start it on the device
@scripts/run-android.sh
npx react-native run-android --appIdSuffix debug
SIMULATOR=iPhone 13
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios: export TARGET := ios
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios: ##@run Build iOS app and start it in on the simulator
@scripts/run-ios.sh "${SIMULATOR}"
run-ios: export XCBeautify=$(shell which xcbeautify) # for react-native-cli to pick this up and to auto format output
run-ios: ##@run Build iOS app and start it in a simulator/device
ifneq ("$(SIMULATOR)", "")
npx react-native run-ios --simulator="$(SIMULATOR)"
else
npx react-native run-ios
endif
show-ios-devices: ##@other shows connected ios device and its name
xcrun xctrace list devices
@@ -290,8 +296,11 @@ show-ios-devices: ##@other shows connected ios device and its name
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios-device: export TARGET := ios
run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios-device: ##@run iOS app and start it on the first connected iPhone
@scripts/run-ios-device.sh
run-ios-device: ##@run iOS app and start it on a connected device by its name
ifndef DEVICE_NAME
$(error Usage: make run-ios-device DEVICE_NAME=your-device-name)
endif
react-native run-ios --device "$(DEVICE_NAME)"
#--------------
# Tests
@@ -359,20 +368,15 @@ test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connection
"until [ -f $$SHADOW_OUTPUT_TO ] ; do sleep 1 ; done ; node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO --repl"
test-unit: export SHADOW_OUTPUT_TO := target/unit_test/test.js
test-unit: export SHADOW_NS_REGEXP := ^(?!tests\.integration-test)(?!tests\.contract-test).*-test$$
test-unit: export SHADOW_NS_REGEXP := ^(?!status-im\.integration-test).*-test$$
test-unit: ##@test Run unit tests
test-unit: _test-clojure
test-integration: export SHADOW_OUTPUT_TO := target/integration_test/test.js
test-integration: export SHADOW_NS_REGEXP := ^tests\.integration-test.*$$
test-integration: export SHADOW_NS_REGEXP := ^status-im\.integration-test.*$$
test-integration: ##@test Run integration tests
test-integration: _test-clojure
test-contract: export SHADOW_OUTPUT_TO := target/contract_test/test.js
test-contract: export SHADOW_NS_REGEXP := ^tests\.contract-test.*$$
test-contract: ##@test Run contract tests
test-contract: _test-clojure
android-test: jsbundle
android-test: export TARGET := android
android-test:
@@ -448,18 +452,3 @@ repl-clojure: ##@repl Start Clojure repl for mobile App
yarn shadow-cljs cljs-repl mobile
repl-nix: nix-repl ##@repl Start an interactive Nix REPL
#--------------
# Dev Automation Flows
#--------------
auto-login: export TARGET := default
auto-login: ##@auto runs flow for login or onboarding app on simulator/emulator
maestro test "maestro/create-account-or-login.yaml"
auto-custom: export TARGET := default
auto-custom: ##@auto runs any custom maestro automation flow on simulator/emulator
ifndef FLOW
$(error Usage: make automate FLOW=your-maestro-flow-file.yaml)
endif
maestro test "$(FLOW)"
+3 -3
View File
@@ -37,7 +37,7 @@ project dependencies, coding guidelines and testing procedures.
Check out our [coding guidelines](doc/new-guidelines.md).
- **Community Management**
Metcalfe's law states that the value of a network is proportional to the square of the number of connected users of the system - without community Status is meaningless. We're looking to create a positive, fun environment to explore new ideas, experiment and grow the Status community. Building a community takes a lot of work but the people you'll meet and the long-lasting relationships you form will be well worth it, check out our [Mission and Community Principles](https://status.app/manifesto)
Metcalfe's law states that the value of a network is proportional to the square of the number of connected users of the system - without community Status is meaningless. We're looking to create a positive, fun environment to explore new ideas, experiment and grow the Status community. Building a community takes a lot of work but the people you'll meet and the long-lasting relationships you form will be well worth it, check out our [Mission and Community Principles](https://status.im/about)
- **Specification / Documentation**
John Dewey once said, "Education is not preparation for life; education is life *itself* ". Developers and Designers need guidance and it all starts from documentation and specifications. Our software is only as good as its documentation, check out our [docs](doc/) and see how you can improve what we have.
@@ -53,10 +53,10 @@ Status is a visual interface to make permanent changes on the Blockchain, it han
- **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://join.status.im/chat/public/status)
## Give me Binaries!
You can get our Beta builds for both Android and iOS on our [website](https://status.app), through our [nightly builds](https://status.im/nightly/), or by [building it yourself](doc/starting-guide.md).
You can get our Beta builds for both Android and iOS on our [website](https://status.im), through our [nightly builds](https://status.im/nightly/), or by [building it yourself](https://status.im/technical/build_status/).
## Core Contributors
+14 -13
View File
@@ -267,24 +267,25 @@ android {
dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
implementation("androidx.core:core-splashscreen:1.0.0")
// we don't use hermes for debug but we need its pom file for release builds
// https://github.com/status-im/status-mobile/pull/18675
implementation("com.facebook.react:hermes-android")
// FIXME: implementing both hermes & JSC increases bundle size by ~ 2MB
implementation(jscFlavor)
implementation "androidx.core:core-splashscreen:1.0.0"
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
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") // required by status-mobile/android/app/src/main/java/im/status/ethereum/MainApplication.java
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
implementation 'androidx.multidex:multidex:2.0.1' // required by status-mobile/android/app/src/main/java/im/status/ethereum/MainApplication.java
implementation project(':react-native-blur')
implementation project(':react-native-status')
implementation project(':react-native-status-keycard')
implementation("com.github.status-im:function:0.0.1")
implementation("com.facebook.fresco:fresco:2.5.0")
implementation("com.facebook.fresco:animated-gif:2.5.0")
implementation("com.squareup.okhttp3:okhttp-tls:4.9.2")
implementation 'com.github.status-im:function:0.0.1'
implementation 'com.facebook.fresco:fresco:2.5.0'
implementation 'com.facebook.fresco:animated-gif:2.5.0'
implementation "com.squareup.okhttp3:okhttp-tls:4.9.2"
implementation("com.google.prefab:cli:2.0.0")
}
+1 -3
View File
@@ -57,6 +57,4 @@ newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
hermesEnabled=false
hermesEnabled=true
+3 -3
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.4'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'linux && x86_64 && nix-2.19' }
agent { label 'linux && x86_64 && nix-2.14' }
options {
timestamps()
@@ -15,7 +15,7 @@ pipeline {
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '20',
artifactNumToKeepStr: '1',
artifactNumToKeepStr: '10',
))
/* Allows combined build to copy */
copyArtifactPermission('/status-mobile/*')
+7 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.4'
pipeline {
agent { label 'linux' }
@@ -13,7 +13,7 @@ pipeline {
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
artifactNumToKeepStr: '10',
))
}
@@ -35,6 +35,8 @@ pipeline {
stage('Prep') {
steps { script {
println("Current JOB: ${env.JOB_NAME}")
/* just for a shorter access */
btype = utils.getBuildType()
} }
}
stage('Build') {
@@ -82,8 +84,10 @@ pipeline {
when { expression { params.PUBLISH } }
steps { script {
switch (btype) {
case 'nightly': /* Create JSON file with newest build URLs */
case 'nightly':
/* Create JSON file with newest build URLs */
s3.updateBucketJSON(urls, 'latest.json');
build(job: 'website/status.im', wait: false);
break;
case 'release':
github.publishReleaseFiles(repo: 'status-mobile');
+1 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.4'
pipeline {
agent { label 'linux' }
@@ -23,7 +23,6 @@ pipeline {
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
+9 -5
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.4'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'macos && arm64 && nix-2.19 && xcode-15.1' }
agent { label 'macos && arm64 && nix-2.14 && xcode-15.1' }
parameters {
string(
@@ -23,7 +23,7 @@ pipeline {
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '20',
artifactNumToKeepStr: '1',
artifactNumToKeepStr: '10',
))
/* Allows combined build to copy */
copyArtifactPermission('/status-mobile/*')
@@ -39,6 +39,8 @@ pipeline {
LANGUAGE = "en_US.UTF-8"
TARGET = 'ios'
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
FASTLANE_DISABLE_COLORS = 1
BUNDLE_PATH = "${HOME}/.bundle"
}
@@ -63,7 +65,7 @@ pipeline {
}
post {
failure {
archiveArtifacts 'logs/*'
archiveArtifacts 'ios/logs/*'
}
}
}
@@ -76,7 +78,9 @@ pipeline {
}
stage('Upload') {
steps { script {
env.DIAWI_URL = ios.uploadToDiawi()
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
env.DIAWI_URL = ios.uploadToDiawi()
}
env.PKG_URL = env.DIAWI_URL
jenkins.setBuildDesc(IPA: env.PKG_URL)
} }
+4 -12
View File
@@ -1,21 +1,21 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.8.4'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
pipeline {
agent { label 'linux && x86_64 && nix-2.19' }
agent { label 'linux && x86_64 && nix-2.14' }
options {
timestamps()
/* Prevent Jenkins jobs from running forever */
timeout(time: 20, unit: 'MINUTES')
timeout(time: 15, unit: 'MINUTES')
/* Limit builds retained */
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '20',
artifactNumToKeepStr: '1',
artifactNumToKeepStr: '10',
))
/* Abort old PR builds. */
disableConcurrentBuilds(
@@ -62,14 +62,6 @@ pipeline {
}
}
}
stage('Contract Tests') {
steps {
sh """#!/bin/bash
set -eo pipefail
make test-contract 2>&1 | tee -a ${LOG_FILE}
"""
}
}
stage('Integration Tests') {
steps {
sh """#!/bin/bash
+1 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
@@ -29,11 +29,6 @@ pipeline {
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
stages {
+1 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
@@ -47,11 +47,6 @@ pipeline {
options {
disableConcurrentBuilds()
timeout(time: 90, unit: 'MINUTES')
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
stages {
+1 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
@@ -28,11 +28,6 @@ pipeline {
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
+3 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
agent { label 'macos' }
@@ -10,6 +10,8 @@ pipeline {
LC_ALL = 'en_US.UTF-8'
TARGET = 'ios'
FASTLANE_DISABLE_COLORS = 1
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
/* avoid writing to r/o /nix */
GEM_HOME = '~/.rubygems'
}
+4 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
agent { label params.AGENT_LABEL }
@@ -18,6 +18,8 @@ pipeline {
}
environment {
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
/* we source .bash_profile to be able to use nix-store */
NIX_SSHOPTS = "-oStrictHostKeyChecking=no"
NIX_CONF_DIR = "${env.WORKSPACE}/nix"
@@ -34,7 +36,6 @@ pipeline {
buildDiscarder(logRotator(
numToKeepStr: '20',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
@@ -81,7 +82,7 @@ pipeline {
env.NIXPKGS_SYSTEM_OVERRIDE = nixSysOverride(os, arch, 'android')
/* Build/fetch deps required to build android release. */
nix.build(
attr: 'targets.mobile.android.build.buildInputs',
attr: 'targets.mobile.android.release.buildInputs',
sandbox: false,
pure: false,
link: false
+3 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
agent { label 'linux' }
@@ -10,6 +10,8 @@ pipeline {
LC_ALL = 'en_US.UTF-8'
TARGET = 'ios'
FASTLANE_DISABLE_COLORS = 1
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
/* avoid writing to r/o /nix */
GEM_HOME = '~/.rubygems'
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.7'
library 'status-jenkins-lib@v1.7.15'
pipeline {
agent {
-4
View File
@@ -10,8 +10,6 @@
[Coding guidelines](new-guidelines.md)
[UI components coding guidelines](ui-guidelines.md)
[Release Checklist](release-checklist.md)
[Release Guide](release-guide.md)
@@ -30,8 +28,6 @@
[Contributing to status-go](status-go-changes.md)
[Malli schemas (recorded demo)](https://www.youtube.com/watch?v=SlRio70aYVI) ([slides](files/forging-code-with-schemas-sep-2023-slides.pdf))
## Testing
[How to run local tests](testing.md)
+2 -2
View File
@@ -144,9 +144,9 @@ used for keycard
used for svg icons, mostly collectibles are using svg
TODO: updating requires a pod update on iOS
## "react-native-biometrics": "^3.0.1"
## "react-native-touch-id": "^4.4.1"
used for biometric authentication on Android and iOS
used for touch-id identification
## "react-native-webview": "git+https://github.com/status-im/react-native-webview.git#v8.0.7_3"
+2 -1
View File
@@ -122,9 +122,10 @@ See below:
Do the following:
Ensure you have 2 terminals running the following
Ensure you have 3 terminals running the following
- `make run-clojure`
- `make run-metro`
- `make run-ios` / `make run-android`
[See the STARTING GUIDE for details](STARTING_GUIDE.md#development)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

+23 -37
View File
@@ -4,41 +4,22 @@ This document provides information on how to start developing Status App.
# Getting Started
To start developing clone the status-mobile repo in the directory of your choice.
To start developing start a shell for the platform you are interested in.
```
git clone https://github.com/status-im/status-mobile.git
make shell TARGET=android
```
This step will take a while the first time as it will download all dependencies.
Then open a terminal and cd into this directory.
# Development
```
cd status-mobile
```
There are three steps necessary to start development, in this case for Android:
Then build the clojure terminal
1. `make run-clojure` - Compiles Clojure into JavaScript, watches for changes on cljs files, and hot-reloads code in the app.
2. `make run-metro` - Starts metro bundler and watches JavaScript code.
3. `make run-android` or `make run-ios` - Builds the Android/iOS app and starts it on the device.
```
make run-clojure
```
note: ⚠️ This might take a while if this is your first time.
This command installs `nix` and pulls in all the dependencies.
Do answer with "Y" to all the prompts and press "Enter" when `nix` setup asks you to Acknowledge.
This command builds the `jsbundle` and then compiles `Clojure` into `JavaScript`, watches for changes on `cljs` files, and hot-reloads code in the app.
wait till you see the following message :
```
[:mobile] Build completed. (1801 files, 52 compiled, 0 warnings, 9.52s)
```
Once the clojure terminal is running you need to run the appropriate command next for your platform in a separate terminal :
`make run-android` or `make run-ios`
These commands will build the app, start a metro bundler and deploy the app on your simulator OR connected device (android only). For building and deploying to connected iPhones use `make run-ios-device` instead of `make run-ios`
Also check [developing on a physical iOS Device](#Additional-requirements-for-developing-on-physical-ios-device).
The first two will continue watching for changes and keep re-building the app. They need to be ready first.
The last one will exit once the app is up and ready.
## Simulators and Devices
### Android
@@ -65,9 +46,13 @@ Running `make run-ios` will target `iPhone 13` by default.
If you need to run on any other simulator, you can specify the simulator type by adding the `SIMULATOR` flag:
```sh
make run-ios SIMULATOR="iPhone 15"
make run-ios SIMULATOR="iPhone 13"
```
#### Running on a physical device
Some manual steps are necessary for [developing on a physical iOS Device](#physical-ios-device).
# Build release
To build the app, you can simply run on of the following:
@@ -117,15 +102,16 @@ Steps:
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)
## Additional requirements for developing on Physical iOS Device
## Physical iOS Device
To use a physical iPhone your device UDID must be added to provisioning profiles and your Apple account invited as Developer to Status team.
1. [Get your UDID of your iPhone.](https://www.extentia.com/post/finding-the-udid-of-an-ios-device)
2. Request from someone with access like @cammellos or @jakubgs to
- Add the UDID to development devices on Apple Developer Portal.
- Invite your Apple account to be Developer in Status team.
3. Open XCode using the project from `status-mobile/ios` directory.
- You might see error: `Select a development team in the Signing & Capabilities editor`
- Select `Status Research & Development GmbH` as the development team.
4. In a new terminal execute `make clean` and then `make xcode-clean`
- Add the UDID to development devices on Apple Developer Portal.
- Invite your Apple account to be Developer in Status team.
3. Run a build in XCode using the project from `status-mobile/ios` directory.
- You might see error: `Select a development team in the Signing & Capabilities editor`
- Select `Status Research & Development GmbH` as the development team and rebuild again.
Once build finishes Status should start on your iPhone with its logs in terminal running `make run-metro`.
+6 -32
View File
@@ -2,12 +2,14 @@
## Unit & integration tests
To run all tests:
To run tests:
```
make test
```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
@@ -49,46 +51,18 @@ Here I'm showing a terminal-only experience using Tmux (left pane Emacs, right p
[2022-12-19 13-17.webm](https://user-images.githubusercontent.com/46027/208471199-1909c446-c82d-42a0-9350-0c15ca562713.webm)
## Component tests only
## Component tests
To run tests:
```
make component-test
make component-test
```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
make component-test-watch
make component-test-watch
```
Check [component tests doc](./component-tests-overview.md) for more.
## Unit tests only
To run unit tests:
```
make test-unit
```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
make test-unit WATCH=true
```
## Integration tests only
To run integration tests:
```
make test-integration
```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
make test-integration WATCH=true
```
+20 -1
View File
@@ -88,7 +88,6 @@ info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this
Update yarn.lock file. In order to do this, perform the following steps on a clean `status-mobile` repo:
```
cd status-mobile
make shell
yarn install
```
and don't forget to commit updated `yarn.lock` together with `package.json`.
@@ -128,3 +127,23 @@ Status-mobile uses `shadow-cljs` for hot reloading changes and uses its own [rel
### Solution
Open react native's [In-App Developer Menu](https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu) and press "Disable Fast Refresh" or "Disable Hot Reloading"
## App Crashes after few reloads
### Cause
For x86 CPU architecture Android Devices, Hermes is creating the issue and the app crashes after a few reloads.
([Original Issue](https://github.com/status-im/status-mobile/issues/14031))
<details>
<summary>How to Find CPU architecture</summary>
CPU architecture of android device can be found using
- `adb shell uname -m` or
- `adb shell getprop ro.product.cpu.abilist`
</details>
### Solution
Disable Hermes while building the app
`make run-android DISABLE_HERMES=true`
-254
View File
@@ -1,254 +0,0 @@
# UI components coding guidelines
> [!IMPORTANT]
> React apps are made out of components. A component is a piece of the UI (user interface) that has its own logic and appearance. A component can be as small as a button, or as large as an entire screen.
> React components are JavaScript functions that return markup
> This document will provide best practices on how to write efficient React components in ClojureScript
At the time of creating the Status app, the Reagent library was a solid choice. Back then, hooks didn't exist, and there weren't any libraries providing effective global state management. After Reagent's emergence, another library called Re-frame built upon Reagent. Together, they offered powerful tools for developing React applications with ClojureScript. However, as React evolved, significant changes occurred. Class components, utilized in Reagent, became deprecated. Instead, functional components and hooks emerged for state management. In Status 2.0, we began incorporating more functional components and hooks, resulting in a blend of both approaches. To simplify matters and reduce confusion, we opted to transition to functional components and hooks for local state management.
BEFORE:
```clojure
(defn- view-internal
[_ _]
(let [pressed? (reagent/atom false)]
(fn
[{:keys [theme on-press on-long-press icon]}]
[rn/pressable
{:style (style/main @pressed? theme)
:on-press on-press
:on-press-in #(reset! pressed? true)
:on-press-out #(reset! pressed? nil)
:on-long-press on-long-press}
[quo.icons/icon icon]])))
(def view (theme/with-theme view-internal))
```
NOW:
```clojure
(defn view
[{:keys [on-press on-long-press icon]}]
(let [[pressed? set-pressed] (rn/use-state false)
theme (theme/use-theme-value)
on-press-in (rn/use-callback #(set-pressed true))
on-press-out (rn/use-callback #(set-pressed nil))]
[rn/pressable
{:style (style/main pressed? theme)
:on-press on-press
:on-press-in on-press-in
:on-press-out on-press-out
:on-long-press on-long-press}
[quo.icons/icon icon]]))
```
- We no longer need to create an anonymous function for rendering. This removes unnecessary confusion and the need for specific knowledge on how it works and why it was needed.
- `rn/use-state` is used instead of `reagent/atom`
- State values no longer need to be dereferenced; they are accessible as regular symbols. This eliminates a common bug where the "@" symbol was inadvertently omitted.
- `theme/with-theme` wrapper is not needed anymore, `(theme/use-theme-value)` hook can be used directly in the components
- `:f>` not needed anymore, all components are functional by default
- `rn/use-callback` hook should be used for anon callback functions
> [!IMPORTANT]
> DO NOT USE anon functions directly in the props
BAD
```clojure
(defn view
[]
(let [[pressed? set-pressed] (rn/use-state false)]
[rn/pressable
{:style (style/main pressed?)
:on-press-in #(set-pressed true)
:on-press-out #(set-pressed nil)}]))
```
GOOD:
```clojure
(defn view
[]
(let [[pressed? set-pressed] (rn/use-state false)
on-press-in (rn/use-callback #(set-pressed true))
on-press-out (rn/use-callback #(set-pressed nil))]
[rn/pressable
{:style (style/main pressed?)
:on-press-in on-press-in
:on-press-out on-press-out}]))
```
## Global state and subscriptions
For global state management, we utilize Re-frame subscriptions. They can be likened to React state. To obtain the state, `(rf/sub [])` is employed, and to modify it, `(rf/dispatch [])` is utilized. However, they update components in a similar manner to React states.
```clojure
(defn view
[{:keys [selected-tab]}]
(let [collectible-list (rf/sub [:wallet/all-collectibles])
on-collectible-press (rn/use-callback
(fn [{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id])))]
[rn/view {:style style/container}
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view {:collectibles collectible-list
:on-collectible-press on-collectible-press}])
[activity/view]]))
```
## Regular atoms
In certain instances, components utilized regular atoms; however, they should now be used with `rn/use-ref-atom`
BEFORE:
```clojure
(defn view
[]
(let [focused? (atom false)]
(fn []
(let [on-clear #(reset! status (if @focused? :active :default))
on-focus #(reset! focused? true)
on-blur #(reset! focused? false)]))))
```
NOW:
```clojure
(defn view
[]
(let [focused? (rn/use-ref-atom false)
on-clear (rn/use-callback #(set-status (if @focused? :active :default)))
on-focus (rn/use-callback #(reset! focused? true))
on-blur (rn/use-callback #(reset! focused? false))]))
```
## Effects
LIFECYCLE:
```clojure
(defn view
[{:keys []}]
(let [opacity (reanimated/use-shared-value 0)]
(rn/use-mount #(reanimated/animate opacity 1))
[rn/view
{:style (style/opacity opacity)}]))
```
```clojure
(defn view
[{:keys []}]
(let []
(rn/use-unmount #(rn/dispatch [:unmounted]))
[rn/view]))
```
> [!IMPORTANT]
> Effects should NOT be utilized as a response to state changes for modifying logic. If you're unsure how to achieve this without using effects, please consult the team in the general chat. There may be instances where using effects is appropriate, so we can explore a solution together and enhance our guidelines.
BAD:
```clojure
(defn f-zoom-button
[{:keys [selected? current-zoom]}]
(let [size (reanimated/use-shared-value (if selected? 37 25))]
(rn/use-effect #(reanimated/animate size (if selected? 37 25)) [current-zoom])
[rn/touchable-opacity
{:style (style/zoom-button-container size)}]))
```
BAD:
```clojure
(defn view
[collectible-list (rf/sub [:wallet/all-collectibles])]
(let []
(rn/use-effect #(rn/dispatch [:all-collectibles-changed]) [collectible-list])
[rn/view]))
```
Instead `:all-collectibles-changed` should be used in the handler which changes `collectible-list` state
## Performance tips
To begin with, we need to understand that there are two distinct stages for a component: creation and update. React creates a render tree, a UI tree, composed of the rendered components.
![react_tree.png](react_tree.png)
### Component creation
For component creation, the most critical factor is the number of elements involved, so we should strive to minimize them. For instance, it's advisable to avoid using unnecessary wrappers or containers.
BAD:
```clojure
(defn view
[]
(let []
[rn/view {:style {:padding-top 20}}
[quo/button]]))
```
GOOD:
```clojure
(defn view
[]
(let []
[quo/button {:container-style {:padding-top 20}}]))
```
### Component updates
For component updates, it's crucial to recognize that React will invoke the function where state is utilized. Therefore, if you utilize state in the root component, React will execute the root function and re-render the entire root component along with all its children (unless optimizations like memoization are implemented).
BAD:
```clojure
(defn component
[{:keys [label]}]
(let []
[rn/text label]))
(defn component2
[{:keys [label2]}]
(let []
[rn/text label2]))
(defn screen
[]
(let [screen-params (rf/sub [:screen-params])]
[component screen-params]
[component1]
[component2 screen-params]
[component3]
[rn/view {:padding-top 20}
[quo/button]]))
```
Here, we have lost control over the `screen-params` map. It can contain any data, and if any field within this map changes, the entire screen function will be executed, resulting in the re-rendering of both `component` and `component2`.
GOOD:
```clojure
(defn component
[]
(let [label (rf/sub [:screen-params-label])]
[rn/text label]))
(defn component2
[]
(let [label2 (rf/sub [:screen-params-label2])]
[rn/text label2]))
(defn screen
[]
(let []
[component]
[component1]
[component2]
[component3]
[rn/view {:padding-top 20}
[quo/button]]))
```
So, now the screen component function will never be invoked, and `component` and `component2` will be re-rendered only when `label` or `label2` have changed.
+2 -3
View File
@@ -1,5 +1,4 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
@@ -97,7 +96,7 @@ end
# if false - read list of devices from AppStoreConnect, and upgrade the provisioning profiles from it
# `pr_build`:
# if true - uses StatusImPR scheme and postfixed app id with `.pr` to build an app, which can be used in parallel with release
# if false - uses StatusIm scheme to build the release app
# if false - uses StatusIm scheme to build the release app
def build_ios_adhoc(readonly: false, pr_build: false)
# PR builds should appear as a separate App on iOS
@@ -124,7 +123,7 @@ def build_ios_adhoc(readonly: false, pr_build: false)
export_method: 'ad-hoc',
output_name: 'StatusIm',
output_directory: 'status-ios',
buildlog_path: 'logs',
buildlog_path: 'ios/logs',
export_options: {
signingStyle: 'manual',
provisioningProfiles: {
+6 -6
View File
@@ -305,8 +305,6 @@ PODS:
- glog
- react-native-background-timer (2.2.0):
- React
- react-native-biometrics (3.0.1):
- React-Core
- react-native-blob-util (0.13.18):
- React-Core
- react-native-blur (4.3.3):
@@ -519,6 +517,8 @@ PODS:
- SocketRocket (0.6.1)
- SSZipArchive (2.4.3)
- TOCropViewController (2.6.1)
- TouchID (4.4.1):
- React
- Yoga (1.14.0)
DEPENDENCIES:
@@ -548,7 +548,6 @@ DEPENDENCIES:
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-biometrics (from `../node_modules/react-native-biometrics`)
- react-native-blob-util (from `../node_modules/react-native-blob-util`)
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
- "react-native-cameraroll (from `../node_modules/@react-native-camera-roll/camera-roll`)"
@@ -604,6 +603,7 @@ DEPENDENCIES:
- RNSVG (from `../node_modules/react-native-svg`)
- secp256k1 (from `https://github.com/status-im/secp256k1.swift.git`)
- SSZipArchive (= 2.4.3)
- TouchID (from `../node_modules/react-native-touch-id`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
@@ -669,8 +669,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/logger"
react-native-background-timer:
:path: "../node_modules/react-native-background-timer"
react-native-biometrics:
:path: "../node_modules/react-native-biometrics"
react-native-blob-util:
:path: "../node_modules/react-native-blob-util"
react-native-blur:
@@ -780,6 +778,8 @@ EXTERNAL SOURCES:
secp256k1:
:git: https://github.com/status-im/secp256k1.swift.git
:submodules: true
TouchID:
:path: "../node_modules/react-native-touch-id"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
@@ -822,7 +822,6 @@ SPEC CHECKSUMS:
React-jsinspector: aef73cbd43b70675f572214d10fa438c89bf11ba
React-logger: 2e4aee3e11b3ec4fa6cfd8004610bbb3b8d6cca4
react-native-background-timer: 1f7d560647b40e6a60b01c452ba29c54bf581fc4
react-native-biometrics: 352e5a794bfffc46a0c86725ea7dc62deb085bdc
react-native-blob-util: 600972b1782380a5a7d5db61a3817ea32349dae9
react-native-blur: c6d0a1dc2b4b519f7afe3b14d8151998632b6d18
react-native-cameraroll: 4701ae7c3dbcd3f5e9e150ca17f250a276154b35
@@ -882,6 +881,7 @@ SPEC CHECKSUMS:
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
Yoga: 86fed2e4d425ee4c6eab3813ba1791101ee153c6
PODFILE CHECKSUM: 3f98ce893757dfa17e609ef7cd24fa41635b73a6
+5 -5
View File
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
@@ -542,7 +542,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ../logs/react-native-xcode.log 2>&1";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
};
28606042DA81A750949525E4 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
@@ -578,7 +578,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ../logs/react-native-xcode.log 2>&1";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
};
3AAD2AD724A3A60E0075D594 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
@@ -592,7 +592,7 @@
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/usr/bin/env sh";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ../logs/set_xcode_version.log 2>&1";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ./logs/set_xcode_version.log 2>&1";
};
523CD6BCB20FD78FBF3564AD /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@@ -716,7 +716,7 @@
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/usr/bin/env sh";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ../logs/set_xcode_version.log 2>&1";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ./logs/set_xcode_version.log 2>&1";
};
/* End PBXShellScriptBuildPhase section */
+1 -3
View File
@@ -74,8 +74,6 @@
</dict>
<key>NSCameraUsageDescription</key>
<string>Status uses camera to take pictures and scan QR codes.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Status needs access to the local network to give you the ability to connect with peers.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Location access is required for some DApps to function properly.</string>
<key>NSLocationWhenInUseUsageDescription</key>
@@ -135,7 +133,7 @@
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<true/>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A00000080400010101</string>
+14
View File
@@ -0,0 +1,14 @@
# Description
This directory is the destination of logs created by Fastlane and React Native Xcode script.
# Logs
* `react-native-xcode.log` - Output from `node_modules/react-native/scripts/react-native-xcode.sh`.
- Created by redirecting output of `shellScript` in `ios/StatusIm.xcodeproj/project.pbxproj`.
* `Status PR-StatusImPR.log - Created by [Fastlane Gym](https://docs.fastlane.tools/actions/gym/).
- Configred via [`Fastfile`](../Fastfile) using `buildlog_path` argument for `build_ios_app`.
# CI
These log files are uploaded to Jenkins as CI job artifacts on failure using `archiveArtifacts`.
-27
View File
@@ -1,27 +0,0 @@
# Description
This directory is the destination of logs created during build time of debug builds and logs created by Fastlane on CI.
# Logs
* `xcrun_device_install.log` - Output from `status-mobile/scripts/run-ios-device.sh`.
- Created by redirecting output of `xcrun simctl install "$UDID" "$APP_PATH"`.
* `xcrun_device_process_launch.log` - Output from `status-mobile/scripts/run-ios-device.sh`.
- Created by specifying `--json-output` flag for `xcrun devicectl device process launch --no-activate --verbose --device "${DEVICE_UUID}" "${INSTALLATION_URL}"`.
* `xcrun_device_process_resume.log` - Output from `status-mobile/scripts/run-ios-device.sh`.
- Created by redirecting output of `xcrun devicectl device process resume --device "${DEVICE_UUID}" --pid "${STATUS_PID}"`.
* `adb_install.log` - Output from `scripts/run-android.sh`.
- Created by redirecting output of `adb install -r ./result/app-debug.apk`.
* `adb_shell_monkey.log` - Output from `status-mobile/scripts/run-android.sh`.
- Created by redirecting output of `adb shell monkey -p im.status.ethereum.debug 1 >`.
* `ios_simulators_list.log` - Output from `status-mobile/scripts/run-ios.sh`.
- Created by redirecting output of `xcrun simctl list devices -j`.
# CI
These log files are uploaded to Jenkins as CI job artifacts on failure using `archiveArtifacts`.
* `react-native-xcode.log` - Output from `node_modules/react-native/scripts/react-native-xcode.sh`.
- Created by redirecting output of `shellScript` in `ios/StatusIm.xcodeproj/project.pbxproj`.
* `Status PR-StatusImPR.log - Created by [Fastlane Gym](https://docs.fastlane.tools/actions/gym/).
- Configred via [`Fastfile`](../Fastfile) using `buildlog_path` argument for `build_ios_app`.
-11
View File
@@ -1,11 +0,0 @@
appId: im.status.ethereum.debug
---
- runFlow: # to run onboarding flow only when device is in onboarding state
when:
visible: "Im new to Status"
file: onboarding.yaml
- runFlow: # to run login flow only when device is on login screen
when:
visible: "Profile password"
file: login.yaml
-5
View File
@@ -1,5 +0,0 @@
appId: im.status.ethereum.debug
---
- tapOn: "password-input"
- inputText: "password123" # update your account password here
- tapOn: login-button
-15
View File
@@ -1,15 +0,0 @@
appId: im.status.ethereum.debug
---
- tapOn: "Im new to Status"
- tapOn: "small-option-card"
- tapOn: "Your name"
- inputText: "DeviceA"
- tapOn: "submit-create-profile-button"
- inputText: "password123"
- tapOn: "Repeat password"
- inputText: "password123"
- tapOn: "disclaimer-touchable-opacity"
- tapOn: "Confirm password"
- tapOn: "skip-identifiers"
- tapOn: "enable-notifications-later-button"
- tapOn: "welcome-button"
@@ -342,14 +342,4 @@ public class AccountManager extends ReactContextBaseJavaModule {
final String keyStoreDir = this.utils.getKeyStorePath(keyUID);
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.deleteMultiaccount(keyUID, keyStoreDir), callback);
}
@ReactMethod
public void getRandomMnemonic(final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.getRandomMnemonic(), callback);
}
@ReactMethod
public void createAccountFromMnemonicAndDeriveAccountsForPaths(final String mnemonic, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.createAccountFromMnemonicAndDeriveAccountsForPaths(mnemonic), callback);
}
}
@@ -1,102 +0,0 @@
package im.status.ethereum.pushnotifications;
import android.content.Context;
import android.content.Intent;
import android.app.Service;
import android.os.IBinder;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.provider.Settings;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import android.os.Build;
import im.status.ethereum.module.R;
public class ForegroundService extends Service {
private static final String CHANNEL_ID = "status-service";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent i, int flags, int startId) {
// NOTE: recent versions of Android require the service to display
// a sticky notification to inform the user that the service is running
Context context = getApplicationContext();
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
Intent intent = null;
String notificationContentText = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager =
context.getSystemService(NotificationManager.class);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
context.getResources().getString(R.string.status_service),
NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(false);
notificationManager.createNotificationChannel(channel);
// Create intent that takes the user to the notification channel settings so they can hide it
intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
intent.putExtra(Settings.EXTRA_CHANNEL_ID, CHANNEL_ID);
notificationContentText = context.getResources().getString(R.string.tap_to_hide_notification);
} else {
// For older versions of android intent takes the user to the Status app
Class intentClass;
String packageName = context.getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
String className = launchIntent.getComponent().getClassName();
try {
intentClass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return 0;
}
intent = new Intent(context, intentClass);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationContentText = context.getResources().getString(R.string.keep_status_running);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE);
Intent stopIntent = new Intent(PushNotificationHelper.ACTION_TAP_STOP);
PendingIntent stopPendingIntent = PendingIntent.getBroadcast(context, 0, stopIntent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE);
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_notify_status)
.setContentTitle(context.getResources().getString(R.string.background_service_opened))
.setContentText(notificationContentText)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent)
.setNumber(0)
.addAction(R.drawable.ic_stat_notify_status,
context.getResources().getString(R.string.stop),
stopPendingIntent)
.build();
// the id of the foreground notification MUST NOT be 0
startForeground(1, notification);
return START_STICKY;
}
}
@@ -0,0 +1,88 @@
package im.status.ethereum.pushnotifications
import android.content.Context
import android.content.Intent
import android.app.Service
import android.os.IBinder
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.provider.Settings
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import android.os.Build
import im.status.ethereum.module.R
class ForegroundService : Service() {
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(i: Intent?, flags: Int, startId: Int): Int {
// NOTE: recent versions of Android require the service to display
// a sticky notification to inform the user that the service is running
val context: Context = getApplicationContext()
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
var intent: Intent? = null
var notificationContentText: String? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java)
val channel = NotificationChannel(CHANNEL_ID,
context.getResources().getString(R.string.status_service),
NotificationManager.IMPORTANCE_HIGH)
channel.setShowBadge(false)
notificationManager.createNotificationChannel(channel)
// Create intent that takes the user to the notification channel settings so they can hide it
intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName())
intent.putExtra(Settings.EXTRA_CHANNEL_ID, CHANNEL_ID)
notificationContentText = context.getResources().getString(R.string.tap_to_hide_notification)
} else {
// For older versions of android intent takes the user to the Status app
val intentClass: java.lang.Class<*>
val packageName: String = context.getPackageName()
val launchIntent: Intent? = context.getPackageManager().getLaunchIntentForPackage(packageName)
val className: String? = launchIntent?.getComponent()?.getClassName()
if (className == null) {
return 0
}
intentClass = try {
java.lang.Class.forName(className)
} catch (e: java.lang.ClassNotFoundException) {
e.printStackTrace()
return 0
}
intent = Intent(context, intentClass)
intent.addCategory(Intent.CATEGORY_BROWSABLE)
intent.setAction(Intent.ACTION_VIEW)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
notificationContentText = context.getResources().getString(R.string.keep_status_running)
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)
val stopIntent = Intent(PushNotificationHelper.ACTION_TAP_STOP)
val stopPendingIntent: PendingIntent = PendingIntent.getBroadcast(context, 0, stopIntent,
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE)
val notification: Notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_notify_status)
.setContentTitle(context.getResources().getString(R.string.background_service_opened))
.setContentText(notificationContentText)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent)
.setNumber(0)
.addAction(R.drawable.ic_stat_notify_status,
context.getResources().getString(R.string.stop),
stopPendingIntent)
.build()
// the id of the foreground notification MUST NOT be 0
startForeground(1, notification)
return START_STICKY
}
companion object {
private const val CHANNEL_ID = "status-service"
}
}
@@ -1,146 +0,0 @@
package im.status.ethereum.pushnotifications;
import android.app.Activity;
import android.app.Application;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationManagerCompat;
import java.security.SecureRandom;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import android.util.Log;
import im.status.ethereum.pushnotifications.PushNotificationJsDelivery;
public class PushNotification extends ReactContextBaseJavaModule implements ActivityEventListener {
public static final String LOG_TAG = "PushNotification";
private final SecureRandom mRandomNumberGenerator = new SecureRandom();
private PushNotificationHelper pushNotificationHelper;
private PushNotificationJsDelivery delivery;
private ReactApplicationContext reactContext;
private boolean started;
public PushNotification(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
reactContext.addActivityEventListener(this);
Application applicationContext = (Application) reactContext.getApplicationContext();
IntentFilter intentFilter = new IntentFilter();
pushNotificationHelper = new PushNotificationHelper(applicationContext, intentFilter);
delivery = new PushNotificationJsDelivery(reactContext);
}
@Override
public String getName() {
return "PushNotification";
}
// removed @Override temporarily just to get it working on different versions of RN
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
onActivityResult(requestCode, resultCode, data);
}
// removed @Override temporarily just to get it working on different versions of RN
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Ignored, required to implement ActivityEventListener for RN 0.33
}
private Bundle getBundleFromIntent(Intent intent) {
Bundle bundle = null;
if (intent.hasExtra("notification")) {
bundle = intent.getBundleExtra("notification");
} else if (intent.hasExtra("google.message_id")) {
bundle = new Bundle();
bundle.putBundle("data", intent.getExtras());
}
if(null != bundle && !bundle.getBoolean("foreground", false) && !bundle.containsKey("userInteraction")) {
bundle.putBoolean("userInteraction", true);
}
return bundle;
}
@Override
public void onNewIntent(Intent intent) {
Bundle bundle = this.getBundleFromIntent(intent);
if (bundle != null) {
delivery.notifyNotification(bundle);
}
}
@ReactMethod
/**
* Creates a channel if it does not already exist. Returns whether the channel was created.
*/
public void createChannel(ReadableMap channelInfo, Callback callback) {
boolean created = pushNotificationHelper.createChannel(channelInfo);
if(callback != null) {
callback.invoke(created);
}
}
@ReactMethod
public void presentLocalNotification(ReadableMap details) {
if (!this.started) {
return;
}
Bundle bundle = Arguments.toBundle(details);
// If notification ID is not provided by the user, generate one at random
if (bundle.getString("id") == null) {
bundle.putString("id", String.valueOf(mRandomNumberGenerator.nextInt()));
}
pushNotificationHelper.sendToNotificationCentre(bundle);
}
@ReactMethod
public void clearMessageNotifications(String conversationId) {
if (this.started) {
pushNotificationHelper.clearMessageNotifications(conversationId);
}
}
@ReactMethod
public void clearAllMessageNotifications() {
pushNotificationHelper.clearAllMessageNotifications();
}
@ReactMethod
public void enableNotifications() {
this.started = true;
this.pushNotificationHelper.start();
}
@ReactMethod
public void disableNotifications() {
if (this.started) {
this.started = false;
this.pushNotificationHelper.stop();
}
}
}
@@ -0,0 +1,135 @@
package im.status.ethereum.pushnotifications
import android.app.Activity
import android.app.Application
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import androidx.core.app.NotificationManagerCompat
import com.facebook.react.bridge.ActivityEventListener
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.WritableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import android.util.Log
import im.status.ethereum.pushnotifications.PushNotificationJsDelivery
class PushNotification(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), ActivityEventListener {
companion object {
const val LOG_TAG = "PushNotification"
}
private val mRandomNumberGenerator: java.security.SecureRandom = java.security.SecureRandom()
private val pushNotificationHelper: PushNotificationHelper
private val delivery: PushNotificationJsDelivery
private val reactContext: ReactApplicationContext
private var started = false
init {
this.reactContext = reactContext
reactContext.addActivityEventListener(this)
val applicationContext: Application = reactContext.getApplicationContext() as Application
val intentFilter = IntentFilter()
pushNotificationHelper = PushNotificationHelper(applicationContext, intentFilter)
delivery = PushNotificationJsDelivery(reactContext)
}
override fun getName(): String {
return "PushNotification"
}
// removed @Override temporarily just to get it working on different versions of RN
override fun onActivityResult(activity: Activity?, requestCode: Int, resultCode: Int, data: Intent?) {
onActivityResult(requestCode, resultCode, data)
}
// removed @Override temporarily just to get it working on different versions of RN
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// Ignored, required to implement ActivityEventListener for RN 0.33
}
private fun getBundleFromIntent(intent: Intent): Bundle? {
var bundle: Bundle? = null
if (intent.hasExtra("notification")) {
bundle = intent.getBundleExtra("notification")
} else if (intent.hasExtra("google.message_id")) {
bundle = Bundle()
bundle.putBundle("data", intent.getExtras())
}
if (null != bundle && !bundle.getBoolean("foreground", false) && !bundle.containsKey("userInteraction")) {
bundle.putBoolean("userInteraction", true)
}
return bundle
}
override fun onNewIntent(intent: Intent) {
val bundle: Bundle? = getBundleFromIntent(intent)
if (bundle != null) {
delivery.notifyNotification(bundle)
}
}
// Creates a channel if it does not already exist. Returns whether the channel was created.
@ReactMethod
fun createChannel(channelInfo: ReadableMap?, callback: Callback?) {
if (channelInfo == null) {
return
}
val created: Boolean = pushNotificationHelper.createChannel(channelInfo)
if (callback != null) {
callback.invoke(created)
}
}
@ReactMethod
fun presentLocalNotification(details: ReadableMap?) {
if (!started) {
return
}
val bundle: Bundle? = Arguments.toBundle(details)
if (bundle == null) {
return
}
// If notification ID is not provided by the user, generate one at random
if (bundle.getString("id") == null) {
bundle.putString("id", mRandomNumberGenerator.nextInt().toString())
}
pushNotificationHelper.sendToNotificationCentre(bundle)
}
@ReactMethod
fun clearMessageNotifications(conversationId: String?) {
if (started && conversationId != null) {
pushNotificationHelper.clearMessageNotifications(conversationId)
}
}
@ReactMethod
fun clearAllMessageNotifications() {
pushNotificationHelper.clearAllMessageNotifications()
}
@ReactMethod
fun enableNotifications() {
started = true
pushNotificationHelper.start()
}
@ReactMethod
fun disableNotifications() {
if (started) {
started = false
pushNotificationHelper.stop()
}
}
}
@@ -1,93 +0,0 @@
package im.status.ethereum.pushnotifications;
import android.os.Build;
import android.app.Application;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import im.status.ethereum.pushnotifications.PushNotificationJsDelivery;
import static im.status.ethereum.pushnotifications.PushNotification.LOG_TAG;
public class PushNotificationActions extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
String intentActionPrefix = context.getPackageName() + ".ACTION_";
Log.i(LOG_TAG, "PushNotificationBootEventReceiver loading scheduled notifications");
if (null == intent.getAction() || !intent.getAction().startsWith(intentActionPrefix)) {
return;
}
final Bundle bundle = intent.getBundleExtra("notification");
// Dismiss the notification popup.
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
int notificationID = Integer.parseInt(bundle.getString("id"));
boolean autoCancel = bundle.getBoolean("autoCancel", true);
if(autoCancel) {
if (bundle.containsKey("tag")) {
String tag = bundle.getString("tag");
manager.cancel(tag, notificationID);
} else {
manager.cancel(notificationID);
}
}
boolean invokeApp = bundle.getBoolean("invokeApp", true);
// Notify the action.
if(invokeApp) {
IntentFilter intentFilter = new IntentFilter();
PushNotificationHelper helper = new PushNotificationHelper((Application) context.getApplicationContext(), intentFilter);
helper.invokeApp(bundle);
} else {
// We need to run this on the main thread, as the React code assumes that is true.
// Namely, DevServerHelper constructs a Handler() without a Looper, which triggers:
// "Can't create handler inside thread that has not called Looper.prepare()"
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
// Construct and load our normal React JS code bundle
final ReactInstanceManager mReactInstanceManager = ((ReactApplication) context.getApplicationContext()).getReactNativeHost().getReactInstanceManager();
ReactContext context = mReactInstanceManager.getCurrentReactContext();
PushNotificationJsDelivery delivery = new PushNotificationJsDelivery(context);
// If it's constructed, send a notification
if (context != null) {
delivery.notifyNotificationAction(bundle);
} else {
// Otherwise wait for construction, then send the notification
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
public void onReactContextInitialized(ReactContext context) {
PushNotificationJsDelivery delivery = new PushNotificationJsDelivery(context);
delivery.notifyNotificationAction(bundle);
mReactInstanceManager.removeReactInstanceEventListener(this);
}
});
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
// Construct it in the background
mReactInstanceManager.createReactContextInBackground();
}
}
}
});
}
}
}
@@ -0,0 +1,89 @@
package im.status.ethereum.pushnotifications
import android.os.Build
import android.app.Application
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.facebook.react.ReactApplication
import com.facebook.react.ReactInstanceManager
import com.facebook.react.bridge.ReactContext
import im.status.ethereum.pushnotifications.PushNotificationJsDelivery
class PushNotificationActions : BroadcastReceiver() {
companion object {
const val LOG_TAG = "PushNotification"
}
override fun onReceive(context: Context, intent: Intent) {
val intentActionPrefix: String = context.getPackageName() + ".ACTION_"
Log.i(LOG_TAG, "PushNotificationBootEventReceiver loading scheduled notifications")
var intentAction: String? = intent.getAction()
if (intentAction == null || !intentAction.startsWith(intentActionPrefix)) {
return
}
val bundle: Bundle? = intent.getBundleExtra("notification")
if (bundle == null) {
return
}
// Dismiss the notification popup.
val manager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationID: Int? = bundle.getString("id")?.toInt()
val autoCancel: Boolean = bundle.getBoolean("autoCancel", true)
if (notificationID != null && autoCancel) {
if (bundle.containsKey("tag")) {
val tag: String? = bundle.getString("tag")
if (tag != null) {
manager.cancel(tag, notificationID)
}
} else {
manager.cancel(notificationID)
}
}
val invokeApp: Boolean = bundle.getBoolean("invokeApp", true)
// Notify the action.
if (invokeApp) {
val intentFilter = IntentFilter()
val helper = PushNotificationHelper(context.getApplicationContext() as Application, intentFilter)
helper.invokeApp(bundle)
} else {
// We need to run this on the main thread, as the React code assumes that is true.
// Namely, DevServerHelper constructs a Handler() without a Looper, which triggers:
// "Can't create handler inside thread that has not called Looper.prepare()"
val handler = Handler(Looper.getMainLooper())
handler.post(object : java.lang.Runnable {
override fun run() {
// Construct and load our normal React JS code bundle
val mReactInstanceManager: ReactInstanceManager = (context.getApplicationContext() as ReactApplication).getReactNativeHost().getReactInstanceManager()
val context: ReactContext? = mReactInstanceManager.getCurrentReactContext()
// If it's constructed, send a notification
if (context != null) {
val delivery = PushNotificationJsDelivery(context)
delivery.notifyNotificationAction(bundle)
} else {
// Otherwise wait for construction, then send the notification
mReactInstanceManager.addReactInstanceEventListener(object : ReactInstanceManager.ReactInstanceEventListener {
override fun onReactContextInitialized(context: ReactContext) {
val delivery = PushNotificationJsDelivery(context)
delivery.notifyNotificationAction(bundle)
mReactInstanceManager.removeReactInstanceEventListener(this)
}
})
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
// Construct it in the background
mReactInstanceManager.createReactContextInBackground()
}
}
}
})
}
}
}
@@ -1,886 +0,0 @@
// https://github.com/zo0r/react-native-push-notification/blob/bedc8f646aab67d594f291449fbfa24e07b64fe8/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java Copy-Paste with removed firebase
package im.status.ethereum.pushnotifications;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AlarmManager;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.Base64;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.Person;
import androidx.core.graphics.drawable.IconCompat;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import im.status.ethereum.module.R;
import static im.status.ethereum.pushnotifications.PushNotification.LOG_TAG;
public class PushNotificationHelper {
private Context context;
private static final long DEFAULT_VIBRATION = 300L;
private static final String CHANNEL_ID = "status-im-notifications";
public static final String ACTION_DELETE_NOTIFICATION = "im.status.ethereum.module.DELETE_NOTIFICATION";
public static final String ACTION_TAP_STOP = "im.status.ethereum.module.TAP_STOP";
final int flag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE : PendingIntent.FLAG_CANCEL_CURRENT;
private NotificationManager notificationManager;
private HashMap<String, Person> persons;
private HashMap<String, StatusMessageGroup> messageGroups;
private IntentFilter intentFilter;
public PushNotificationHelper(Application context, IntentFilter intentFilter) {
this.context = context;
this.intentFilter = intentFilter;
this.persons = new HashMap<String, Person>();
this.messageGroups = new HashMap<String, StatusMessageGroup>();
this.notificationManager = context.getSystemService(NotificationManager.class);
this.registerBroadcastReceiver();
}
public Intent getOpenAppIntent(String deepLink) {
Class intentClass;
String packageName = context.getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
String className = launchIntent.getComponent().getClassName();
try {
intentClass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
Intent intent = new Intent(context, intentClass);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setAction(Intent.ACTION_VIEW);
//NOTE: you might wonder, why the heck did he decide to set these flags in particular. Well,
//the answer is a simple as it can get in the Android native development world. I noticed
//that my initial setup was opening the app but wasn't triggering any events on the js side, like
//the links do from the browser. So I compared both intents and noticed that the link from
//the browser produces an intent with the flag 0x14000000. I found out that it was the following
//flags in this link:
//https://stackoverflow.com/questions/52390129/android-intent-setflags-issue
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (deepLink != null) {
intent.setData(Uri.parse(deepLink));
}
return intent;
}
//NOTE: we use a dynamically created BroadcastReceiver here so that we can capture
//intents from notifications and act on them. For instance when tapping/dismissing
//a chat notification we want to clear the chat so that next messages don't show
//the messages that we have seen again
private final BroadcastReceiver notificationActionReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == ACTION_DELETE_NOTIFICATION) {
String groupId = intent.getExtras().getString("im.status.ethereum.groupId");
if (groupId != null) {
cleanGroup(groupId);
}
}
if (intent.getAction() == ACTION_TAP_STOP) {
stop();
System.exit(0);
}
Log.e(LOG_TAG, "intent received: " + intent.getAction());
}
};
public void registerBroadcastReceiver() {
this.intentFilter.addAction(ACTION_DELETE_NOTIFICATION);
this.intentFilter.addAction(ACTION_TAP_STOP);
context.registerReceiver(notificationActionReceiver, this.intentFilter);
Log.e(LOG_TAG, "Broadcast Receiver registered");
}
private NotificationManager notificationManager() {
return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
public void invokeApp(Bundle bundle) {
String packageName = context.getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
String className = launchIntent.getComponent().getClassName();
try {
Class<?> activityClass = Class.forName(className);
Intent activityIntent = new Intent(context, activityClass);
if(bundle != null) {
activityIntent.putExtra("notification", bundle);
}
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
} catch(Exception e) {
Log.e(LOG_TAG, "Class not found", e);
return;
}
}
public void sendToNotificationCentre(final Bundle bundle) {
PushNotificationPicturesAggregator aggregator = new PushNotificationPicturesAggregator(new PushNotificationPicturesAggregator.Callback() {
public void call(Bitmap largeIconImage, Bitmap bigPictureImage) {
sendToNotificationCentreWithPicture(bundle, largeIconImage, bigPictureImage);
}
});
aggregator.setLargeIconUrl(context, bundle.getString("largeIconUrl"));
aggregator.setBigPictureUrl(context, bundle.getString("bigPictureUrl"));
}
public void handleConversation(final Bundle bundle) {
if (bundle.getBoolean("deleted")){
this.removeStatusMessage(bundle);
} else {
this.addStatusMessage(bundle);
}
}
public void clearMessageNotifications(String conversationId) {
notificationManager.cancel(conversationId.hashCode());
cleanGroup(conversationId);
}
public void clearAllMessageNotifications() {
notificationManager.cancelAll();
}
public void sendToNotificationCentreWithPicture(final Bundle bundle, Bitmap largeIconBitmap, Bitmap bigPictureBitmap) {
try {
Class intentClass = getMainActivityClass();
if (intentClass == null) {
Log.e(LOG_TAG, "No activity class found for the notification");
return;
}
if (bundle.getBoolean("isConversation")) {
this.handleConversation(bundle);
return;
}
if (bundle.getString("message") == null) {
// this happens when a 'data' notification is received - we do not synthesize a local notification in this case
Log.d(LOG_TAG, "Ignore this message if you sent data-only notification. Cannot send to notification centre because there is no 'message' field in: " + bundle);
return;
}
String notificationIdString = bundle.getString("id");
if (notificationIdString == null) {
Log.e(LOG_TAG, "No notification ID specified for the notification");
return;
}
Resources res = context.getResources();
String packageName = context.getPackageName();
String title = bundle.getString("title");
if (title == null) {
ApplicationInfo appInfo = context.getApplicationInfo();
title = context.getPackageManager().getApplicationLabel(appInfo).toString();
}
int priority = NotificationCompat.PRIORITY_HIGH;
final String priorityString = bundle.getString("priority");
if (priorityString != null) {
switch (priorityString.toLowerCase()) {
case "max":
priority = NotificationCompat.PRIORITY_MAX;
break;
case "high":
priority = NotificationCompat.PRIORITY_HIGH;
break;
case "low":
priority = NotificationCompat.PRIORITY_LOW;
break;
case "min":
priority = NotificationCompat.PRIORITY_MIN;
break;
case "default":
priority = NotificationCompat.PRIORITY_DEFAULT;
break;
default:
priority = NotificationCompat.PRIORITY_HIGH;
}
}
int visibility = NotificationCompat.VISIBILITY_PRIVATE;
final String visibilityString = bundle.getString("visibility");
if (visibilityString != null) {
switch (visibilityString.toLowerCase()) {
case "private":
visibility = NotificationCompat.VISIBILITY_PRIVATE;
break;
case "public":
visibility = NotificationCompat.VISIBILITY_PUBLIC;
break;
case "secret":
visibility = NotificationCompat.VISIBILITY_SECRET;
break;
default:
visibility = NotificationCompat.VISIBILITY_PRIVATE;
}
}
String channel_id = bundle.getString("channelId");
if(channel_id == null) {
channel_id = this.getNotificationDefaultChannelId();
}
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, channel_id)
.setContentTitle(title)
.setTicker(bundle.getString("ticker"))
.setVisibility(visibility)
.setPriority(priority)
.setAutoCancel(bundle.getBoolean("autoCancel", true))
.setOnlyAlertOnce(bundle.getBoolean("onlyAlertOnce", false));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // API 24 and higher
// Restore showing timestamp on Android 7+
// Source: https://developer.android.com/reference/android/app/Notification.Builder.html#setShowWhen(boolean)
boolean showWhen = bundle.getBoolean("showWhen", true);
notification.setShowWhen(showWhen);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API 26 and higher
// Changing Default mode of notification
notification.setDefaults(Notification.DEFAULT_LIGHTS);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { // API 20 and higher
String group = bundle.getString("group");
if (group != null) {
notification.setGroup(group);
}
if (bundle.containsKey("groupSummary") || bundle.getBoolean("groupSummary")) {
notification.setGroupSummary(bundle.getBoolean("groupSummary"));
}
}
String numberString = bundle.getString("number");
if (numberString != null) {
notification.setNumber(Integer.parseInt(numberString));
}
// Small icon
int smallIconResId = 0;
String smallIcon = bundle.getString("smallIcon");
if (smallIcon != null && !smallIcon.isEmpty()) {
smallIconResId = res.getIdentifier(smallIcon, "mipmap", packageName);
} else if(smallIcon == null) {
smallIconResId = res.getIdentifier("ic_stat_notify_status", "drawable", packageName);
}
if (smallIconResId == 0) {
smallIconResId = res.getIdentifier("ic_launcher", "mipmap", packageName);
if (smallIconResId == 0) {
smallIconResId = android.R.drawable.ic_dialog_info;
}
}
notification.setSmallIcon(smallIconResId);
// Large icon
if(largeIconBitmap == null) {
int largeIconResId = 0;
String largeIcon = bundle.getString("largeIcon");
if (largeIcon != null && !largeIcon.isEmpty()) {
largeIconResId = res.getIdentifier(largeIcon, "mipmap", packageName);
} else if(largeIcon == null) {
largeIconResId = res.getIdentifier("ic_launcher", "mipmap", packageName);
}
// Before Lolipop there was no large icon for notifications.
if (largeIconResId != 0 && (largeIcon != null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId);
}
}
Bundle author = bundle.getBundle("notificationAuthor");
if (largeIconBitmap == null && author != null) {
String base64Image = author.getString("icon").split(",")[1];
byte[] decodedString = Base64.decode(base64Image, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
notification.setLargeIcon(getCircleBitmap(decodedByte));
} else if (largeIconBitmap != null){
notification.setLargeIcon(largeIconBitmap);
}
String message = bundle.getString("message");
notification.setContentText(message);
String subText = bundle.getString("subText");
if (subText != null) {
notification.setSubText(subText);
}
String bigText = bundle.getString("bigText");
if (bigText == null) {
bigText = message;
}
NotificationCompat.Style style;
if(bigPictureBitmap != null) {
style = new NotificationCompat.BigPictureStyle()
.bigPicture(bigPictureBitmap)
.setBigContentTitle(title)
.setSummaryText(message);
} else {
style = new NotificationCompat.BigTextStyle().bigText(bigText);
}
notification.setStyle(style);
Intent intent = new Intent(context, intentClass);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
bundle.putBoolean("foreground", this.isApplicationInForeground());
bundle.putBoolean("userInteraction", true);
intent.putExtra("notification", bundle);
Uri soundUri = null;
if (!bundle.containsKey("playSound") || bundle.getBoolean("playSound")) {
String soundName = bundle.getString("soundName");
if (soundName == null) {
soundName = "default";
}
soundUri = getSoundUri(soundName);
notification.setSound(soundUri);
}
if (soundUri == null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notification.setSound(null);
}
if (bundle.containsKey("ongoing") || bundle.getBoolean("ongoing")) {
notification.setOngoing(bundle.getBoolean("ongoing"));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notification.setCategory(NotificationCompat.CATEGORY_CALL);
String color = bundle.getString("color");
int defaultColor = -1;
if (color != null) {
notification.setColor(Color.parseColor(color));
} else if (defaultColor != -1) {
notification.setColor(defaultColor);
}
}
int notificationID = notificationIdString.hashCode();
notification.setContentIntent(createOnTapIntent(context, notificationID, bundle.getString("deepLink")))
.setDeleteIntent(createOnDismissedIntent(context, notificationID, bundle.getString("deepLink")));
NotificationManager notificationManager = notificationManager();
long[] vibratePattern = new long[]{0};
if (!bundle.containsKey("vibrate") || bundle.getBoolean("vibrate")) {
long vibration = bundle.containsKey("vibration") ? (long) bundle.getDouble("vibration") : DEFAULT_VIBRATION;
if (vibration == 0)
vibration = DEFAULT_VIBRATION;
vibratePattern = new long[]{0, vibration};
notification.setVibrate(vibratePattern);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Define the shortcutId
String shortcutId = bundle.getString("shortcutId");
if (shortcutId != null) {
notification.setShortcutId(shortcutId);
}
Long timeoutAfter = (long) bundle.getDouble("timeoutAfter");
if (timeoutAfter != null && timeoutAfter >= 0) {
notification.setTimeoutAfter(timeoutAfter);
}
}
Long when = (long) bundle.getDouble("when");
if (when != null && when >= 0) {
notification.setWhen(when);
}
notification.setUsesChronometer(bundle.getBoolean("usesChronometer", false));
notification.setChannelId(channel_id);
JSONArray actionsArray = null;
try {
actionsArray = bundle.getString("actions") != null ? new JSONArray(bundle.getString("actions")) : null;
} catch (JSONException e) {
Log.e(LOG_TAG, "Exception while converting actions to JSON object.", e);
}
if (actionsArray != null) {
// No icon for now. The icon value of 0 shows no icon.
int icon = 0;
// Add button for each actions.
for (int i = 0; i < actionsArray.length(); i++) {
String action;
try {
action = actionsArray.getString(i);
} catch (JSONException e) {
Log.e(LOG_TAG, "Exception while getting action from actionsArray.", e);
continue;
}
Intent actionIntent = new Intent(context, PushNotificationActions.class);
actionIntent.setAction(packageName + ".ACTION_" + i);
actionIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// Add "action" for later identifying which button gets pressed.
bundle.putString("action", action);
actionIntent.putExtra("notification", bundle);
actionIntent.setPackage(packageName);
PendingIntent pendingActionIntent = PendingIntent.getBroadcast(context, notificationID, actionIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
notification.addAction(new NotificationCompat.Action.Builder(icon, action, pendingActionIntent).build());
} else {
notification.addAction(icon, action, pendingActionIntent);
}
}
}
if (!(this.isApplicationInForeground() && bundle.getBoolean("ignoreInForeground"))) {
Notification info = notification.build();
info.defaults |= Notification.DEFAULT_LIGHTS;
if (bundle.containsKey("tag")) {
String tag = bundle.getString("tag");
notificationManager.notify(tag, notificationID, info);
} else {
notificationManager.notify(notificationID, info);
}
}
} catch (Exception e) {
Log.e(LOG_TAG, "failed to send push notification", e);
}
}
private boolean checkOrCreateChannel(NotificationManager manager, String channel_id, String channel_name, String channel_description, Uri soundUri, int importance, long[] vibratePattern, boolean showBadge) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return false;
if (manager == null)
return false;
NotificationChannel channel = manager.getNotificationChannel(channel_id);
if (
channel == null && channel_name != null && channel_description != null ||
channel != null &&
(
channel_name != null && !channel.getName().equals(channel_name) ||
channel_description != null && !channel.getDescription().equals(channel_description)
)
) {
// If channel doesn't exist create a new one.
// If channel name or description is updated then update the existing channel.
channel = new NotificationChannel(channel_id, channel_name, importance);
channel.setDescription(channel_description);
channel.enableLights(true);
channel.enableVibration(vibratePattern != null);
channel.setVibrationPattern(vibratePattern);
channel.setShowBadge(showBadge);
if (soundUri != null) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
channel.setSound(soundUri, audioAttributes);
} else {
channel.setSound(null, null);
}
manager.createNotificationChannel(channel);
return true;
}
return false;
}
public boolean createChannel(ReadableMap channelInfo) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return false;
String channelId = channelInfo.getString("channelId");
String channelName = channelInfo.getString("channelName");
String channelDescription = channelInfo.hasKey("channelDescription") ? channelInfo.getString("channelDescription") : "";
String soundName = channelInfo.hasKey("soundName") ? channelInfo.getString("soundName") : "default";
int importance = channelInfo.hasKey("importance") ? channelInfo.getInt("importance") : 4;
boolean vibrate = channelInfo.hasKey("vibrate") && channelInfo.getBoolean("vibrate");
long[] vibratePattern = vibrate ? new long[] { DEFAULT_VIBRATION } : null;
boolean showBadge = channelInfo.hasKey("showBadge") && channelInfo.getBoolean("showBadge");
NotificationManager manager = notificationManager();
Uri soundUri = getSoundUri(soundName);
return checkOrCreateChannel(manager, channelId, channelName, channelDescription, soundUri, importance, vibratePattern, showBadge);
}
public String getNotificationDefaultChannelId() {
return this.CHANNEL_ID;
}
private Uri getSoundUri(String soundName) {
if (soundName == null || "default".equalsIgnoreCase(soundName)) {
return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
} else {
// sound name can be full filename, or just the resource name.
// So the strings 'my_sound.mp3' AND 'my_sound' are accepted
// The reason is to make the iOS and android javascript interfaces compatible
int resId;
if (context.getResources().getIdentifier(soundName, "raw", context.getPackageName()) != 0) {
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
} else {
soundName = soundName.substring(0, soundName.lastIndexOf('.'));
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName());
}
return Uri.parse("android.resource://" + context.getPackageName() + "/" + resId);
}
}
public Class getMainActivityClass() {
String packageName = context.getPackageName();
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
String className = launchIntent.getComponent().getClassName();
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
public boolean isApplicationInForeground() {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processInfos = activityManager.getRunningAppProcesses();
if (processInfos != null) {
for (RunningAppProcessInfo processInfo : processInfos) {
if (processInfo.processName.equals(context.getPackageName())
&& processInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND
&& processInfo.pkgList.length > 0) {
return true;
}
}
}
return false;
}
private Bitmap getCircleBitmap(Bitmap bitmap) {
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final int color = Color.RED;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
bitmap.recycle();
return output;
}
private Person getPerson(Bundle bundle) {
String name = bundle.getString("name");
return new Person.Builder().setName(name).build();
}
private StatusMessage createMessage(Bundle data) {
Person author = getPerson(data.getBundle("notificationAuthor"));
long timeStampLongValue = (long) data.getDouble("timestamp");
return new StatusMessage(data.getString("id"), author, timeStampLongValue, data.getString("message"));
}
private PendingIntent createGroupOnDismissedIntent(Context context, int notificationId, String groupId, String deepLink) {
Intent intent = new Intent(ACTION_DELETE_NOTIFICATION);
intent.putExtra("im.status.ethereum.deepLink", deepLink);
intent.putExtra("im.status.ethereum.groupId", groupId);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent, flag);
}
private PendingIntent createGroupOnTapIntent(Context context, int notificationId, String groupId, String deepLink) {
Intent intent = getOpenAppIntent(deepLink);
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag);
}
private PendingIntent createOnTapIntent(Context context, int notificationId, String deepLink) {
Intent intent = getOpenAppIntent(deepLink);
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag);
}
private PendingIntent createOnDismissedIntent(Context context, int notificationId, String deepLink) {
Intent intent = new Intent(ACTION_DELETE_NOTIFICATION);
intent.putExtra("im.status.ethereum.deepLink", deepLink);
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent, flag);
}
public void removeStatusMessage(Bundle bundle) {
String conversationId = bundle.getString("conversationId");
StatusMessageGroup group = this.messageGroups.get(conversationId);
NotificationManager notificationManager = notificationManager();
if (group == null) {
group = new StatusMessageGroup(conversationId);
}
this.messageGroups.put(conversationId, group);
String id = bundle.getString("id");
group.removeMessage(id);
this.showMessages(bundle);
}
public StatusMessageGroup getMessageGroup(String conversationId) {
return this.messageGroups.get(conversationId);
}
public void addStatusMessage(Bundle bundle) {
String conversationId = bundle.getString("conversationId");
StatusMessageGroup group = this.messageGroups.get(conversationId);
NotificationManager notificationManager = notificationManager();
if (group == null) {
group = new StatusMessageGroup(conversationId);
}
this.messageGroups.put(conversationId, group);
group.addMessage(createMessage(bundle));
this.showMessages(bundle);
}
public void showMessages(Bundle bundle) {
String conversationId = bundle.getString("conversationId");
StatusMessageGroup group = this.messageGroups.get(conversationId);
NotificationManager notificationManager = notificationManager();
NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle("Me");
ArrayList<StatusMessage> messages = group.getMessages();
if (messages.size() == 0) {
notificationManager.cancel(conversationId.hashCode());
return;
}
for (int i = 0; i < messages.size(); i++) {
StatusMessage message = messages.get(i);
messagingStyle.addMessage(message.getText(),
message.getTimestamp(),
message.getAuthor());
}
if (bundle.getString("title") != null) {
messagingStyle.setConversationTitle(bundle.getString("title"));
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_notify_status)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setStyle(messagingStyle)
.setGroup(conversationId)
.setOnlyAlertOnce(true)
.setGroupSummary(true)
.setContentIntent(createGroupOnTapIntent(context, conversationId.hashCode(), conversationId, bundle.getString("deepLink")))
.setDeleteIntent(createGroupOnDismissedIntent(context, conversationId.hashCode(), conversationId, bundle.getString("deepLink")))
.setNumber(messages.size() + 1)
.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= 21) {
builder.setVibrate(new long[0]);
}
notificationManager.notify(conversationId.hashCode(), builder.build());
}
class StatusMessageGroup {
private ArrayList<StatusMessage> messages;
private String id;
StatusMessageGroup(String id) {
this.id = id;
this.messages = new ArrayList<StatusMessage>();
}
public ArrayList<StatusMessage> getMessages() {
return messages;
}
public void addMessage(StatusMessage message) {
this.messages.add(message);
}
public void removeMessage(String id) {
ArrayList<StatusMessage> newMessages = new ArrayList<StatusMessage>();
for(StatusMessage message: this.messages) {
if(!message.id.equals(id)) {
newMessages.add(message);
}
}
this.messages = newMessages;
}
public String getId() {
return this.id;
}
}
class StatusMessage {
public Person getAuthor() {
return author;
}
public long getTimestamp() {
return timestamp;
}
public String getText() {
return text;
}
private String id;
private Person author;
private long timestamp;
private String text;
StatusMessage(String id, Person author, long timestamp, String text) {
this.id = id;
this.author = author;
this.timestamp = timestamp;
this.text = text;
}
}
private void removeGroup(String groupId) {
this.messageGroups.remove(groupId);
}
private void cleanGroup(String groupId) {
removeGroup(groupId);
if (messageGroups.size() == 0) {
notificationManager.cancelAll();
}
}
public void start() {
Log.e(LOG_TAG, "Starting Foreground Service");
Intent serviceIntent = new Intent(context, ForegroundService.class);
context.startService(serviceIntent);
this.registerBroadcastReceiver();
}
public void stop() {
Log.e(LOG_TAG, "Stopping Foreground Service");
//NOTE: we cancel all the current notifications, because the intents can't be used anymore
//since the broadcast receiver will be killed as well and won't be able to handle any intent
notificationManager.cancelAll();
Intent serviceIntent = new Intent(context, ForegroundService.class);
context.stopService(serviceIntent);
context.unregisterReceiver(notificationActionReceiver);
}
}
@@ -0,0 +1,771 @@
// https://github.com/zo0r/react-native-push-notification/blob/bedc8f646aab67d594f291449fbfa24e07b64fe8/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java Copy-Paste with removed firebase
package im.status.ethereum.pushnotifications
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.app.AlarmManager
import android.app.Application
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.BroadcastReceiver
import android.content.SharedPreferences
import android.content.pm.ApplicationInfo
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect
import android.graphics.RectF
import android.media.AudioAttributes
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.service.notification.StatusBarNotification
import android.util.Log
import android.util.Base64
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.Person
import androidx.core.graphics.drawable.IconCompat
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableArray
import com.facebook.react.bridge.WritableMap
import org.json.JSONArray
import org.json.JSONException
import im.status.ethereum.module.R
class PushNotificationHelper(context: Application, intentFilter: IntentFilter) {
companion object {
const val LOG_TAG = "PushNotification"
private const val DEFAULT_VIBRATION: Long = 300L
private const val CHANNEL_ID = "status-im-notifications"
const val ACTION_DELETE_NOTIFICATION = "im.status.ethereum.module.DELETE_NOTIFICATION"
const val ACTION_TAP_STOP = "im.status.ethereum.module.TAP_STOP"
}
private val context: Context
val flag: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE else PendingIntent.FLAG_CANCEL_CURRENT
private val notificationManager: NotificationManager
private val persons: HashMap<String, Person>
private val messageGroups: HashMap<String, StatusMessageGroup>
private val intentFilter: IntentFilter
fun getOpenAppIntent(deepLink: String?): Intent? {
val intentClass: java.lang.Class<*>
val packageName: String = context.getPackageName()
val launchIntent: Intent? = context.getPackageManager().getLaunchIntentForPackage(packageName)
if (launchIntent == null) {
return null
}
val className: String? = launchIntent.getComponent()?.getClassName()
if (className == null) {
return null
}
intentClass = try {
java.lang.Class.forName(className)
} catch (e: java.lang.ClassNotFoundException) {
e.printStackTrace()
return null
}
val intent = Intent(context, intentClass)
intent.addCategory(Intent.CATEGORY_BROWSABLE)
intent.setAction(Intent.ACTION_VIEW)
//NOTE: you might wonder, why the heck did he decide to set these flags in particular. Well,
//the answer is a simple as it can get in the Android native development world. I noticed
//that my initial setup was opening the app but wasn't triggering any events on the js side, like
//the links do from the browser. So I compared both intents and noticed that the link from
//the browser produces an intent with the flag 0x14000000. I found out that it was the following
//flags in this link:
//https://stackoverflow.com/questions/52390129/android-intent-setflags-issue
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
if (deepLink != null) {
intent.setData(Uri.parse(deepLink))
}
return intent
}
//NOTE: we use a dynamically created BroadcastReceiver here so that we can capture
//intents from notifications and act on them. For instance when tapping/dismissing
//a chat notification we want to clear the chat so that next messages don't show
//the messages that we have seen again
private val notificationActionReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
if (intent.getAction() === ACTION_DELETE_NOTIFICATION) {
val groupId: String? = intent.getExtras()?.getString("im.status.ethereum.groupId")
if (groupId != null) {
cleanGroup(groupId)
}
}
if (intent.getAction() === ACTION_TAP_STOP) {
stop()
java.lang.System.exit(0)
}
Log.e(LOG_TAG, "intent received: " + intent.getAction())
}
}
init {
this.context = context
this.intentFilter = intentFilter
persons = HashMap<String, Person>()
messageGroups = HashMap<String, StatusMessageGroup>()
notificationManager = context.getSystemService(NotificationManager::class.java)
registerBroadcastReceiver()
}
fun registerBroadcastReceiver() {
intentFilter.addAction(ACTION_DELETE_NOTIFICATION)
intentFilter.addAction(ACTION_TAP_STOP)
context.registerReceiver(notificationActionReceiver, intentFilter)
Log.e(LOG_TAG, "Broadcast Receiver registered")
}
private fun notificationManager(): NotificationManager {
return context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
fun invokeApp(bundle: Bundle?) {
val packageName: String = context.getPackageName()
val launchIntent: Intent? = context.getPackageManager().getLaunchIntentForPackage(packageName)
if (launchIntent == null) {
return
}
val className: String? = launchIntent.getComponent()?.getClassName()
if (className == null) {
return
}
try {
val activityClass: java.lang.Class<*> = java.lang.Class.forName(className)
val activityIntent = Intent(context, activityClass)
if (bundle != null) {
activityIntent.putExtra("notification", bundle)
}
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(activityIntent)
} catch (e: java.lang.Exception) {
Log.e(LOG_TAG, "Class not found", e)
return
}
}
fun sendToNotificationCentre(bundle: Bundle) {
val aggregator = PushNotificationPicturesAggregator(object : PushNotificationPicturesAggregator.Callback {
override fun call(largeIconImage: Bitmap?, bigPictureImage: Bitmap?) {
sendToNotificationCentreWithPicture(bundle, largeIconImage, bigPictureImage)
}
})
aggregator.setLargeIconUrl(context, bundle.getString("largeIconUrl"))
aggregator.setBigPictureUrl(context, bundle.getString("bigPictureUrl"))
}
fun handleConversation(bundle: Bundle) {
if (bundle.getBoolean("deleted")) {
removeStatusMessage(bundle)
} else {
addStatusMessage(bundle)
}
}
fun clearMessageNotifications(conversationId: String) {
notificationManager.cancel(conversationId.hashCode())
cleanGroup(conversationId)
}
fun clearAllMessageNotifications() {
notificationManager.cancelAll()
}
fun sendToNotificationCentreWithPicture(bundle: Bundle, largeIconBitmap: Bitmap?, bigPictureBitmap: Bitmap?) {
var largeIconBitmap: Bitmap? = largeIconBitmap
try {
val intentClass: java.lang.Class<*>? = mainActivityClass
if (intentClass == null) {
Log.e(LOG_TAG, "No activity class found for the notification")
return
}
if (bundle.getBoolean("isConversation")) {
handleConversation(bundle)
return
}
if (bundle.getString("message") == null) {
// this happens when a 'data' notification is received - we do not synthesize a local notification in this case
Log.d(LOG_TAG, "Ignore this message if you sent data-only notification. Cannot send to notification centre because there is no 'message' field in: $bundle")
return
}
val notificationIdString: String? = bundle.getString("id")
if (notificationIdString == null) {
Log.e(LOG_TAG, "No notification ID specified for the notification")
return
}
val res: Resources = context.getResources()
val packageName: String = context.getPackageName()
var title: String? = bundle.getString("title")
if (title == null) {
val appInfo: ApplicationInfo = context.getApplicationInfo()
title = context.getPackageManager().getApplicationLabel(appInfo).toString()
}
var priority: Int = NotificationCompat.PRIORITY_HIGH
val priorityString: String? = bundle.getString("priority")
if (priorityString != null) {
priority = when (priorityString.lowercase()) {
"max" -> NotificationCompat.PRIORITY_MAX
"high" -> NotificationCompat.PRIORITY_HIGH
"low" -> NotificationCompat.PRIORITY_LOW
"min" -> NotificationCompat.PRIORITY_MIN
"default" -> NotificationCompat.PRIORITY_DEFAULT
else -> NotificationCompat.PRIORITY_HIGH
}
}
var visibility: Int = NotificationCompat.VISIBILITY_PRIVATE
val visibilityString: String? = bundle.getString("visibility")
if (visibilityString != null) {
visibility = when (visibilityString.lowercase()) {
"private" -> NotificationCompat.VISIBILITY_PRIVATE
"public" -> NotificationCompat.VISIBILITY_PUBLIC
"secret" -> NotificationCompat.VISIBILITY_SECRET
else -> NotificationCompat.VISIBILITY_PRIVATE
}
}
var channel_id: String? = bundle.getString("channelId")
if (channel_id == null) {
channel_id = notificationDefaultChannelId
}
val notification: NotificationCompat.Builder = NotificationCompat.Builder(context, channel_id)
.setContentTitle(title)
.setTicker(bundle.getString("ticker"))
.setVisibility(visibility)
.setPriority(priority)
.setAutoCancel(bundle.getBoolean("autoCancel", true))
.setOnlyAlertOnce(bundle.getBoolean("onlyAlertOnce", false))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // API 24 and higher
// Restore showing timestamp on Android 7+
// Source: https://developer.android.com/reference/android/app/Notification.Builder.html#setShowWhen(boolean)
val showWhen: Boolean = bundle.getBoolean("showWhen", true)
notification.setShowWhen(showWhen)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // API 26 and higher
// Changing Default mode of notification
notification.setDefaults(Notification.DEFAULT_LIGHTS)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { // API 20 and higher
val group: String? = bundle.getString("group")
if (group != null) {
notification.setGroup(group)
}
if (bundle.containsKey("groupSummary") || bundle.getBoolean("groupSummary")) {
notification.setGroupSummary(bundle.getBoolean("groupSummary"))
}
}
val numberString: String? = bundle.getString("number")
if (numberString != null) {
notification.setNumber(numberString.toInt())
}
// Small icon
var smallIconResId = 0
val smallIcon: String? = bundle.getString("smallIcon")
if (smallIcon != null && !smallIcon.isEmpty()) {
smallIconResId = res.getIdentifier(smallIcon, "mipmap", packageName)
} else if (smallIcon == null) {
smallIconResId = res.getIdentifier("ic_stat_notify_status", "drawable", packageName)
}
if (smallIconResId == 0) {
smallIconResId = res.getIdentifier("ic_launcher", "mipmap", packageName)
if (smallIconResId == 0) {
smallIconResId = android.R.drawable.ic_dialog_info
}
}
notification.setSmallIcon(smallIconResId)
// Large icon
if (largeIconBitmap == null) {
var largeIconResId = 0
val largeIcon: String? = bundle.getString("largeIcon")
if (largeIcon != null && !largeIcon.isEmpty()) {
largeIconResId = res.getIdentifier(largeIcon, "mipmap", packageName)
} else if (largeIcon == null) {
largeIconResId = res.getIdentifier("ic_launcher", "mipmap", packageName)
}
// Before Lolipop there was no large icon for notifications.
if (largeIconResId != 0 && (largeIcon != null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId)
}
}
val author: Bundle? = bundle.getBundle("notificationAuthor")
if (largeIconBitmap == null && author != null) {
val base64Image: String? = author.getString("icon")?.split(",")?.get(1)
if (base64Image != null) {
val decodedString: ByteArray = Base64.decode(base64Image, Base64.DEFAULT)
val decodedByte: Bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.size)
notification.setLargeIcon(getCircleBitmap(decodedByte))
}
} else if (largeIconBitmap != null) {
notification.setLargeIcon(largeIconBitmap)
}
val message: String? = bundle.getString("message")
if (message != null) {
notification.setContentText(message)
}
val subText: String? = bundle.getString("subText")
if (subText != null) {
notification.setSubText(subText)
}
var bigText: String? = bundle.getString("bigText")
if (bigText == null) {
bigText = message
}
val style: NotificationCompat.Style
style = if (bigPictureBitmap != null) {
NotificationCompat.BigPictureStyle()
.bigPicture(bigPictureBitmap)
.setBigContentTitle(title)
.setSummaryText(message)
} else {
NotificationCompat.BigTextStyle().bigText(bigText)
}
notification.setStyle(style)
val intent = Intent(context, intentClass)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
bundle.putBoolean("foreground", isApplicationInForeground)
bundle.putBoolean("userInteraction", true)
intent.putExtra("notification", bundle)
var soundUri: Uri? = null
if (!bundle.containsKey("playSound") || bundle.getBoolean("playSound")) {
var soundName: String? = bundle.getString("soundName")
if (soundName == null) {
soundName = "default"
}
soundUri = getSoundUri(soundName)
notification.setSound(soundUri)
}
if (soundUri == null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notification.setSound(null)
}
if (bundle.containsKey("ongoing") || bundle.getBoolean("ongoing")) {
notification.setOngoing(bundle.getBoolean("ongoing"))
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notification.setCategory(NotificationCompat.CATEGORY_CALL)
val color: String? = bundle.getString("color")
val defaultColor = -1
if (color != null) {
notification.setColor(Color.parseColor(color))
} else if (defaultColor != -1) {
notification.setColor(defaultColor)
}
}
val notificationID = notificationIdString.hashCode()
var deepLink: String? = bundle.getString("deepLink")
if (deepLink != null) {
notification
.setContentIntent(createOnTapIntent(context, notificationID, deepLink))
.setDeleteIntent(createOnDismissedIntent(context, notificationID, deepLink))
}
val notificationManager: NotificationManager = notificationManager()
if (!bundle.containsKey("vibrate") || bundle.getBoolean("vibrate")) {
var vibration = if (bundle.containsKey("vibration")) bundle.getDouble("vibration") as Long else DEFAULT_VIBRATION
if (vibration == 0L) {
vibration = DEFAULT_VIBRATION
}
val vibrationPattern: LongArray = longArrayOf(0L, vibration)
notification.setVibrate(vibrationPattern)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Define the shortcutId
val shortcutId: String? = bundle.getString("shortcutId")
if (shortcutId != null) {
notification.setShortcutId(shortcutId)
}
val timeoutAfter = bundle.getDouble("timeoutAfter") as Long
if (timeoutAfter != null && timeoutAfter >= 0) {
notification.setTimeoutAfter(timeoutAfter)
}
}
val `when` = bundle.getDouble("when") as Long
if (`when` != null && `when` >= 0) {
notification.setWhen(`when`)
}
notification.setUsesChronometer(bundle.getBoolean("usesChronometer", false))
notification.setChannelId(channel_id)
var actionsArray: JSONArray? = null
try {
actionsArray = if (bundle.getString("actions") != null) JSONArray(bundle.getString("actions")) else null
} catch (e: JSONException) {
Log.e(LOG_TAG, "Exception while converting actions to JSON object.", e)
}
if (actionsArray != null) {
// No icon for now. The icon value of 0 shows no icon.
val icon = 0
// Add button for each actions.
for (i in 0 until actionsArray.length()) {
var action: String
action = try {
actionsArray.getString(i)
} catch (e: JSONException) {
Log.e(LOG_TAG, "Exception while getting action from actionsArray.", e)
continue
}
val actionIntent = Intent(context, PushNotificationActions::class.java)
actionIntent.setAction("$packageName.ACTION_$i")
actionIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
// Add "action" for later identifying which button gets pressed.
bundle.putString("action", action)
actionIntent.putExtra("notification", bundle)
actionIntent.setPackage(packageName)
val pendingActionIntent: PendingIntent = PendingIntent.getBroadcast(context, notificationID, actionIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
notification.addAction(NotificationCompat.Action.Builder(icon, action, pendingActionIntent).build())
} else {
notification.addAction(icon, action, pendingActionIntent)
}
}
}
if (!(isApplicationInForeground && bundle.getBoolean("ignoreInForeground"))) {
val info: Notification = notification.build()
info.defaults = info.defaults or Notification.DEFAULT_LIGHTS
if (bundle.containsKey("tag")) {
val tag: String? = bundle.getString("tag")
if (tag != null) {
notificationManager.notify(tag, notificationID, info)
}
} else {
notificationManager.notify(notificationID, info)
}
}
} catch (e: java.lang.Exception) {
Log.e(LOG_TAG, "failed to send push notification", e)
}
}
private fun checkOrCreateChannel(manager: NotificationManager?, channel_id: String, channel_name: String?, channel_description: String?, soundUri: Uri?, importance: Int, vibratePattern: LongArray?, showBadge: Boolean): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return false
if (manager == null) return false
var channel: NotificationChannel? = manager.getNotificationChannel(channel_id)
if (channel == null && channel_name != null && channel_description != null ||
channel != null &&
(channel_name != null && !channel.getName().equals(channel_name) ||
channel_description != null && !channel.getDescription().equals(channel_description))) {
// If channel doesn't exist create a new one.
// If channel name or description is updated then update the existing channel.
channel = NotificationChannel(channel_id, channel_name, importance)
channel.setDescription(channel_description)
channel.enableLights(true)
channel.enableVibration(vibratePattern != null)
channel.setVibrationPattern(vibratePattern)
channel.setShowBadge(showBadge)
if (soundUri != null) {
val audioAttributes: AudioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
channel.setSound(soundUri, audioAttributes)
} else {
channel.setSound(null, null)
}
manager.createNotificationChannel(channel)
return true
}
return false
}
fun createChannel(channelInfo: ReadableMap): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return false
}
val channelId: String? = channelInfo.getString("channelId")
val channelName: String? = channelInfo.getString("channelName")
val channelDescription = if (channelInfo.hasKey("channelDescription")) channelInfo.getString("channelDescription") else ""
val soundName = if (channelInfo.hasKey("soundName")) channelInfo.getString("soundName") else "default"
val importance = if (channelInfo.hasKey("importance")) channelInfo.getInt("importance") else 4
val vibrate = channelInfo.hasKey("vibrate") && channelInfo.getBoolean("vibrate")
val vibratePattern = if (vibrate) longArrayOf(DEFAULT_VIBRATION) else null
val showBadge = channelInfo.hasKey("showBadge") && channelInfo.getBoolean("showBadge")
val manager: NotificationManager = notificationManager()
val soundUri: Uri? = if (soundName != null) getSoundUri(soundName) else null
if (channelId != null) {
return checkOrCreateChannel(manager, channelId, channelName, channelDescription, soundUri, importance, vibratePattern, showBadge)
}
return false
}
val notificationDefaultChannelId: String
get() = CHANNEL_ID
private fun getSoundUri(soundName: String): Uri {
var soundName: String? = soundName
return if (soundName == null || "default".equals(soundName, ignoreCase = true)) {
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
} else {
// sound name can be full filename, or just the resource name.
// So the strings 'my_sound.mp3' AND 'my_sound' are accepted
// The reason is to make the iOS and android javascript interfaces compatible
val resId: Int
if (context.getResources().getIdentifier(soundName, "raw", context.getPackageName()) !== 0) {
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName())
} else {
soundName = soundName.substring(0, soundName.lastIndexOf('.'))
resId = context.getResources().getIdentifier(soundName, "raw", context.getPackageName())
}
Uri.parse("android.resource://" + context.getPackageName() + "/" + resId)
}
}
val mainActivityClass: java.lang.Class<*>?
get() {
val packageName: String = context.getPackageName()
val launchIntent: Intent? = context.getPackageManager().getLaunchIntentForPackage(packageName)
if (launchIntent == null) {
return null
}
val className: String? = launchIntent.getComponent()?.getClassName()
if (className == null) {
return null
}
return try {
java.lang.Class.forName(className)
} catch (e: java.lang.ClassNotFoundException) {
e.printStackTrace()
null
}
}
val isApplicationInForeground: Boolean
get() {
val activityManager: ActivityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val processInfos: List<RunningAppProcessInfo> = activityManager.getRunningAppProcesses()
if (processInfos != null) {
for (processInfo in processInfos) {
if (processInfo.processName.equals(context.getPackageName()) && processInfo.importance === RunningAppProcessInfo.IMPORTANCE_FOREGROUND && processInfo.pkgList.size > 0) {
return true
}
}
}
return false
}
private fun getCircleBitmap(bitmap: Bitmap): Bitmap {
val output: Bitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
val color: Int = Color.RED
val paint = Paint()
val rect = Rect(0, 0, bitmap.getWidth(), bitmap.getHeight())
val rectF = RectF(rect)
paint.setAntiAlias(true)
canvas.drawARGB(0, 0, 0, 0)
paint.setColor(color)
canvas.drawOval(rectF, paint)
paint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.SRC_IN))
canvas.drawBitmap(bitmap, rect, rect, paint)
bitmap.recycle()
return output
}
private fun getPerson(bundle: Bundle?): Person {
val builder = Person.Builder()
val name: String? = bundle?.getString("name")
if (name != null) {
builder.setName(name)
}
return builder.build()
}
private fun createMessage(data: Bundle): StatusMessage {
val notificationAuthor: Bundle? = data.getBundle("notificationAuthor")
val author: Person = getPerson(notificationAuthor)
val timeStampLongValue = data.getDouble("timestamp") as Long
val id: String? = data.getString("id")
val message: String? = data.getString("message")
return StatusMessage(id ?: "", author, timeStampLongValue, message ?: "")
}
private fun createGroupOnDismissedIntent(context: Context, notificationId: Int, groupId: String, deepLink: String?): PendingIntent {
val intent = Intent(ACTION_DELETE_NOTIFICATION)
if (deepLink != null) {
intent.putExtra("im.status.ethereum.deepLink", deepLink)
}
intent.putExtra("im.status.ethereum.groupId", groupId)
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent, flag)
}
private fun createGroupOnTapIntent(context: Context, notificationId: Int, groupId: String, deepLink: String?): PendingIntent {
val intent: Intent? = getOpenAppIntent(deepLink)
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag)
}
private fun createOnTapIntent(context: Context, notificationId: Int, deepLink: String?): PendingIntent {
val intent: Intent? = getOpenAppIntent(deepLink)
return PendingIntent.getActivity(context.getApplicationContext(), notificationId, intent, flag)
}
private fun createOnDismissedIntent(context: Context, notificationId: Int, deepLink: String): PendingIntent {
val intent = Intent(ACTION_DELETE_NOTIFICATION)
intent.putExtra("im.status.ethereum.deepLink", deepLink)
return PendingIntent.getBroadcast(context.getApplicationContext(), notificationId, intent, flag)
}
fun removeStatusMessage(bundle: Bundle) {
val conversationId: String? = bundle.getString("conversationId")
if (conversationId == null) {
return
}
var group: StatusMessageGroup? = if (conversationId != null) messageGroups.get(conversationId) else null
val notificationManager: NotificationManager = notificationManager()
if (group == null) {
group = StatusMessageGroup(conversationId)
}
messageGroups.put(conversationId, group)
val id: String? = bundle.getString("id")
if (id != null) {
group.removeMessage(id)
}
showMessages(bundle)
}
fun getMessageGroup(conversationId: String?): StatusMessageGroup? {
return messageGroups.get(conversationId)
}
fun addStatusMessage(bundle: Bundle) {
val conversationId: String? = bundle.getString("conversationId")
if (conversationId == null) {
return
}
var group: StatusMessageGroup? = if (conversationId != null) messageGroups.get(conversationId) else null
val notificationManager: NotificationManager = notificationManager()
if (group == null) {
group = StatusMessageGroup(conversationId)
}
messageGroups.put(conversationId, group)
group.addMessage(createMessage(bundle))
showMessages(bundle)
}
fun showMessages(bundle: Bundle) {
val conversationId: String? = bundle.getString("conversationId")
if (conversationId == null) {
return
}
val group: StatusMessageGroup? = if (conversationId != null) messageGroups.get(conversationId) else null
val notificationManager: NotificationManager = notificationManager()
val messagingStyle: NotificationCompat.MessagingStyle = NotificationCompat.MessagingStyle("Me")
var messages = if (group != null) group.getMessages() else null
if (messages == null || messages.size == 0) {
notificationManager.cancel(conversationId.hashCode())
return
}
for (i in messages.indices) {
val message: StatusMessage = messages.get(i)
messagingStyle.addMessage(message.text, message.timestamp, message.getAuthor())
}
val title: String? = bundle.getString("title")
if (title != null) {
messagingStyle.setConversationTitle(title)
}
val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_notify_status)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setStyle(messagingStyle)
.setGroup(conversationId)
.setOnlyAlertOnce(true)
.setGroupSummary(true)
.setContentIntent(createGroupOnTapIntent(context, conversationId.hashCode(), conversationId, bundle.getString("deepLink")))
.setDeleteIntent(createGroupOnDismissedIntent(context, conversationId.hashCode(), conversationId, bundle.getString("deepLink")))
.setNumber(messages.size + 1)
.setAutoCancel(true)
if (Build.VERSION.SDK_INT >= 21) {
builder.setVibrate(LongArray(0))
}
notificationManager.notify(conversationId.hashCode(), builder.build())
}
inner class StatusMessageGroup(val id: String) {
private var messages: java.util.ArrayList<StatusMessage>
init {
messages = java.util.ArrayList<StatusMessage>()
}
fun getMessages(): java.util.ArrayList<StatusMessage> {
return messages
}
fun addMessage(message: StatusMessage) {
messages.add(message)
}
fun removeMessage(id: String) {
val newMessages: java.util.ArrayList<StatusMessage> = java.util.ArrayList<StatusMessage>()
for (message in messages) {
if (message.id != id) {
newMessages.add(message)
}
}
messages = newMessages
}
}
inner class StatusMessage(val id: String, author: Person, timestamp: Long, text: String) {
fun getAuthor(): Person {
return author
}
private val author: Person
val timestamp: Long
val text: String
init {
this.author = author
this.timestamp = timestamp
this.text = text
}
}
private fun removeGroup(groupId: String) {
messageGroups.remove(groupId)
}
private fun cleanGroup(groupId: String) {
removeGroup(groupId)
if (messageGroups.size == 0) {
notificationManager.cancelAll()
}
}
fun start() {
Log.e(LOG_TAG, "Starting Foreground Service")
val serviceIntent = Intent(context, ForegroundService::class.java)
context.startService(serviceIntent)
registerBroadcastReceiver()
}
fun stop() {
Log.e(LOG_TAG, "Stopping Foreground Service")
//NOTE: we cancel all the current notifications, because the intents can't be used anymore
//since the broadcast receiver will be killed as well and won't be able to handle any intent
notificationManager.cancelAll()
val serviceIntent = Intent(context, ForegroundService::class.java)
context.stopService(serviceIntent)
context.unregisterReceiver(notificationActionReceiver)
}
}
@@ -1,86 +0,0 @@
package im.status.ethereum.pushnotifications;
import android.os.Build;
import android.app.Application;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Set;
import static im.status.ethereum.pushnotifications.PushNotification.LOG_TAG;
class PushNotificationJsDelivery {
private ReactContext reactContext;
PushNotificationJsDelivery(ReactContext context){
reactContext = context;
}
String convertJSON(Bundle bundle) {
try {
JSONObject json = convertJSONObject(bundle);
return json.toString();
} catch (JSONException e) {
return null;
}
}
// a Bundle is not a map, so we have to convert it explicitly
private JSONObject convertJSONObject(Bundle bundle) throws JSONException {
JSONObject json = new JSONObject();
Set<String> keys = bundle.keySet();
for (String key : keys) {
Object value = bundle.get(key);
if (value instanceof Bundle) {
json.put(key, convertJSONObject((Bundle)value));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
json.put(key, JSONObject.wrap(value));
} else {
json.put(key, value);
}
}
return json;
}
void notifyNotification(Bundle bundle) {
String bundleString = convertJSON(bundle);
WritableMap params = Arguments.createMap();
params.putString("dataJSON", bundleString);
sendEvent("remoteNotificationReceived", params);
}
void notifyNotificationAction(Bundle bundle) {
String bundleString = convertJSON(bundle);
WritableMap params = Arguments.createMap();
params.putString("dataJSON", bundleString);
sendEvent("notificationActionReceived", params);
}
void sendEvent(String eventName, Object params) {
if (reactContext.hasActiveCatalystInstance()) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
}
}
@@ -0,0 +1,81 @@
package im.status.ethereum.pushnotifications
import android.os.Build
import android.app.Application
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import org.json.JSONException
import org.json.JSONObject
internal class PushNotificationJsDelivery(context: ReactContext) {
companion object {
const val LOG_TAG = "PushNotification"
}
private val reactContext: ReactContext
init {
reactContext = context
}
fun convertJSON(bundle: Bundle): String? {
return try {
val json: JSONObject = convertJSONObject(bundle)
json.toString()
} catch (e: JSONException) {
null
}
}
// a Bundle is not a map, so we have to convert it explicitly
@kotlin.Throws(JSONException::class)
private fun convertJSONObject(bundle: Bundle): JSONObject {
val json = JSONObject()
val keys: Set<String> = bundle.keySet()
for (key in keys) {
val value: Any? = bundle.get(key)
if (value == null) {
continue
} else if (value is Bundle) {
json.put(key, convertJSONObject(value as Bundle))
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
json.put(key, JSONObject.wrap(value))
} else {
json.put(key, value)
}
}
return json
}
fun notifyNotification(bundle: Bundle) {
val bundleString = convertJSON(bundle)
val params: WritableMap = Arguments.createMap()
params.putString("dataJSON", bundleString)
sendEvent("remoteNotificationReceived", params)
}
fun notifyNotificationAction(bundle: Bundle) {
val bundleString = convertJSON(bundle)
val params: WritableMap = Arguments.createMap()
params.putString("dataJSON", bundleString)
sendEvent("notificationActionReceived", params)
}
fun sendEvent(eventName: String, params: Any?) {
if (reactContext.hasActiveCatalystInstance()) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit(eventName, params)
}
}
}
@@ -1,27 +0,0 @@
package im.status.ethereum.pushnotifications;
import im.status.ethereum.pushnotifications.PushNotification;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Collections;
import java.util.List;
public class PushNotificationPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Collections.<NativeModule>singletonList(new PushNotification(reactContext));
}
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
@@ -0,0 +1,22 @@
package im.status.ethereum.pushnotifications
import im.status.ethereum.pushnotifications.PushNotification
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.JavaScriptModule
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class PushNotificationPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf<NativeModule>(PushNotification(reactContext))
}
fun createJSModules(): List<java.lang.Class<out JavaScriptModule?>> {
return emptyList<java.lang.Class<out JavaScriptModule?>>()
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
@@ -1,136 +0,0 @@
package im.status.ethereum.pushnotifications;
import androidx.annotation.Nullable;
import com.facebook.common.executors.CallerThreadExecutor;
import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.DataSource;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.common.Priority;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import android.util.Log;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import java.util.concurrent.atomic.AtomicInteger;
import static im.status.ethereum.pushnotifications.PushNotification.LOG_TAG;
public class PushNotificationPicturesAggregator {
interface Callback {
public void call(Bitmap largeIconImage, Bitmap bigPictureImage);
}
private AtomicInteger count = new AtomicInteger(0);
private Bitmap largeIconImage;
private Bitmap bigPictureImage;
private Callback callback;
public PushNotificationPicturesAggregator(Callback callback) {
this.callback = callback;
}
public void setBigPicture(Bitmap bitmap) {
this.bigPictureImage = bitmap;
this.finished();
}
public void setBigPictureUrl(Context context, String url) {
if(null == url) {
this.setBigPicture(null);
return;
}
Uri uri = null;
try {
uri = Uri.parse(url);
} catch(Exception ex) {
Log.e(LOG_TAG, "Failed to parse bigPictureUrl", ex);
this.setBigPicture(null);
return;
}
final PushNotificationPicturesAggregator aggregator = this;
this.downloadRequest(context, uri, new BaseBitmapDataSubscriber() {
@Override
public void onNewResultImpl(@Nullable Bitmap bitmap) {
aggregator.setBigPicture(bitmap);
}
@Override
public void onFailureImpl(DataSource dataSource) {
aggregator.setBigPicture(null);
}
});
}
public void setLargeIcon(Bitmap bitmap) {
this.largeIconImage = bitmap;
this.finished();
}
public void setLargeIconUrl(Context context, String url) {
if(null == url) {
this.setLargeIcon(null);
return;
}
Uri uri = null;
try {
uri = Uri.parse(url);
} catch(Exception ex) {
Log.e(LOG_TAG, "Failed to parse largeIconUrl", ex);
this.setLargeIcon(null);
return;
}
final PushNotificationPicturesAggregator aggregator = this;
this.downloadRequest(context, uri, new BaseBitmapDataSubscriber() {
@Override
public void onNewResultImpl(@Nullable Bitmap bitmap) {
aggregator.setLargeIcon(bitmap);
}
@Override
public void onFailureImpl(DataSource dataSource) {
aggregator.setLargeIcon(null);
}
});
}
private void downloadRequest(Context context, Uri uri, BaseBitmapDataSubscriber subscriber) {
ImageRequest imageRequest = ImageRequestBuilder
.newBuilderWithSource(uri)
.setRequestPriority(Priority.HIGH)
.setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)
.build();
if(!Fresco.hasBeenInitialized()) {
Fresco.initialize(context);
}
DataSource<CloseableReference<CloseableImage>> dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, context);
dataSource.subscribe(subscriber, CallerThreadExecutor.getInstance());
}
private void finished() {
synchronized(this.count) {
int val = this.count.incrementAndGet();
if(val >= 2 && this.callback != null) {
this.callback.call(this.largeIconImage, this.bigPictureImage);
}
}
}
}
@@ -0,0 +1,112 @@
package im.status.ethereum.pushnotifications
import com.facebook.common.executors.CallerThreadExecutor
import com.facebook.common.references.CloseableReference
import com.facebook.datasource.DataSource
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.imagepipeline.common.Priority
import com.facebook.imagepipeline.core.ImagePipeline
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
import com.facebook.imagepipeline.image.CloseableImage
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
import android.util.Log
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import java.util.concurrent.atomic.AtomicInteger
class PushNotificationPicturesAggregator(private val callback: Callback?) {
companion object {
const val LOG_TAG = "PushNotification"
}
interface Callback {
fun call(largeIconImage: Bitmap?, bigPictureImage: Bitmap?)
}
private val count: AtomicInteger = AtomicInteger(0)
private var largeIconImage: Bitmap? = null
private var bigPictureImage: Bitmap? = null
fun setBigPicture(bitmap: Bitmap?) {
bigPictureImage = bitmap
finished()
}
fun setBigPictureUrl(context: Context, url: String?) {
if (null == url) {
setBigPicture(null)
return
}
var uri: Uri? = null
uri = try {
Uri.parse(url)
} catch (ex: java.lang.Exception) {
Log.e(LOG_TAG, "Failed to parse bigPictureUrl", ex)
setBigPicture(null)
return
}
val aggregator = this
downloadRequest(context, uri, object : BaseBitmapDataSubscriber() {
override fun onNewResultImpl(bitmap: Bitmap?) {
aggregator.setBigPicture(bitmap)
}
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
aggregator.setBigPicture(null)
}
})
}
fun setLargeIcon(bitmap: Bitmap?) {
largeIconImage = bitmap
finished()
}
fun setLargeIconUrl(context: Context, url: String?) {
if (null == url) {
setLargeIcon(null)
return
}
var uri: Uri? = null
uri = try {
Uri.parse(url)
} catch (ex: java.lang.Exception) {
Log.e(LOG_TAG, "Failed to parse largeIconUrl", ex)
setLargeIcon(null)
return
}
val aggregator = this
downloadRequest(context, uri, object : BaseBitmapDataSubscriber() {
override fun onNewResultImpl(bitmap: Bitmap?) {
aggregator.setLargeIcon(bitmap)
}
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
aggregator.setLargeIcon(null)
}
})
}
private fun downloadRequest(context: Context, uri: Uri?, subscriber: BaseBitmapDataSubscriber) {
val imageRequest: ImageRequest = ImageRequestBuilder
.newBuilderWithSource(uri)
.setRequestPriority(Priority.HIGH)
.setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)
.build()
if (!Fresco.hasBeenInitialized()) {
Fresco.initialize(context)
}
val dataSource: DataSource<CloseableReference<CloseableImage>> = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, context)
dataSource.subscribe(subscriber, CallerThreadExecutor.getInstance())
}
private fun finished() {
synchronized(count) {
val `val`: Int = count.incrementAndGet()
if (`val` >= 2 && callback != null) {
callback.call(largeIconImage, bigPictureImage)
}
}
}
}
@@ -214,20 +214,4 @@ RCT_EXPORT_METHOD(logout) {
NSLog(@"%@", result);
}
RCT_EXPORT_METHOD(getRandomMnemonic:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"GetRandomMnemonic() method called");
#endif
NSString *result = StatusgoGetRandomMnemonic();
callback(@[result]);
}
RCT_EXPORT_METHOD(createAccountFromMnemonicAndDeriveAccountsForPaths:(NSString *)mnemonic callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"createAccountFromMnemonicAndDeriveAccountsForPaths() method called");
#endif
NSString *result = StatusgoCreateAccountFromMnemonicAndDeriveAccountsForPaths(mnemonic);
callback(@[result]);
}
@end
@@ -4,25 +4,10 @@
#import "Statusgo.h"
#import "Utils.h"
@interface NetworkManager() <NSNetServiceBrowserDelegate>
@property (nonatomic, strong) NSNetServiceBrowser *serviceBrowser;
@property (nonatomic, copy) RCTResponseSenderBlock callback;
@end
@implementation NetworkManager
RCT_EXPORT_MODULE();
- (instancetype)init {
if ((self = [super init])) {
self.serviceBrowser = [[NSNetServiceBrowser alloc] init];
self.serviceBrowser.delegate = self;
}
return self;
}
RCT_EXPORT_METHOD(startSearchForLocalPairingPeers:(RCTResponseSenderBlock)callback) {
NSString *result = StatusgoStartSearchForLocalPairingPeers();
callback(@[result]);
@@ -110,39 +95,6 @@ RCT_EXPORT_METHOD(callPrivateRPC:(NSString *)payload
});
}
RCT_EXPORT_METHOD(requestLocalNetworkAccess:(RCTResponseSenderBlock)callback) {
self.callback = callback;
// Start browsing for services using TCP on the local network.
dispatch_async(dispatch_get_main_queue(), ^{
[self.serviceBrowser searchForServicesOfType:@"_http._tcp." inDomain:@""];
});
}
// NSNetServiceBrowser delegate method
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didNotSearch:(NSDictionary<NSString *,NSNumber *> *)errorDict {
RCTLogInfo(@"Failed to search for services: %@", errorDict);
if (self.callback) {
self.callback(@[@"Failed to search for services"]);
}
}
// NSNetServiceBrowser delegate method
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)moreComing {
RCTLogInfo(@"Found service: %@", service);
// we stop the search after finding the first service or wait until the search is finished.
[browser stop];
if (self.callback) {
self.callback(@[[NSNull null], @"Requested local network access and found service"]);
}
}
// NSNetServiceBrowser delegate method
- (void)netServiceBrowserDidStopSearch:(NSNetServiceBrowser *)browser {
RCTLogInfo(@"Stopped searching for services");
}
#pragma mark - Recover
RCT_EXPORT_METHOD(recover:(NSString *)message
@@ -120,12 +120,9 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(checkAddressChecksum:(NSString *)address)
return StatusgoCheckAddressChecksum(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isAddress:(NSString *)address) {
return StatusgoIsAddress(address);
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}
@end
+5 -7
View File
@@ -61,7 +61,7 @@ We will use the `make jsbundle` target as an example of a derivation you can bui
3. [`build.sh`](/nix/scripts/build.sh) calls `nix-build --attr targets.mobile.jsbundle` with extra arguments
4. `nix-build` builds the derivation from [`nix/mobile/jsbundle/default.nix`](/nix/mobile/jsbundle/default.nix)
The same can be done for other targets like `targets.mobile.android.build`.
The same can be done for other targets like `targets.mobile.android.release`.
Except in that case extra arguments are required which is why the [`scripts/release-android.sh`](/scripts/release-android.sh) is used in the `make release-android` target.
If you run `make release-android` you'll see the `nix-build` command used:
@@ -71,23 +71,21 @@ nix-build \
--fallback \
--no-out-link \
--show-trace \
--attr targets.mobile.android.build \
--attr targets.mobile.android.release \
--argstr secrets-file '/tmp/tmp-status-mobile-559a3a441/tmp.xAnrPuNtAP' \
--option extra-sandbox-paths '/home/joe/.gradle/status-im.keystore /tmp/tmp-status-mobile-559a3a441/tmp.xAnrPuNtAP' \
default.nix
```
Some of those are required which is why just calling:
```
nix-build --attr targets.mobile.android.build
nix-build --attr targets.mobile.android.release
```
Would fail.
# Garbage Collection
The `make nix-gc` target calls `nix-store --gc` and normally would remove almost everything, but to prevent that we place symlinks to protected derivations in `.nix-gcroots` folder. Specifically:
The `make nix-gc` target calls `nix-store --gc` and normally would remove almost everything, but to prevent that we place symlinks to protected derivations in `/nix/var/nix/gcroots` subfolder. Specifically:
```sh
_NIX_GCROOTS="${_NIX_GCROOTS:-${GIT_ROOT}/.nix-gcroots}
_NIX_GCROOTS="${_NIX_GCROOTS:-/nix/var/nix/gcroots/per-user/${USER}/status-mobile}"
```
These symlinks in turn will be symlinked from `/nix/var/nix/gcroots/auto` through use of `nix-store --add-gcroots`.
Whenever `nix/scripts/build.sh` or `nix/scripts/shell.sh` are called they update symlinks named after given targets in that folder. This in combination with `keep-outputs = true` set in `nix/nix.conf` prevents garbage collection from removing too much.
+1 -1
View File
@@ -28,7 +28,7 @@ export STATUS_GO_IPFS_GATEWAY_URL="https://ipfs.status.im/"
```
You can see the defaults in code:
- [`nix/status-go/default.nix`](./status-go/default.nix)
- [`nix/mobile/android/release.nix`](./mobile/android/build.nix)
- [`nix/mobile/android/release.nix`](./mobile/android/release.nix)
## Shell
+1 -1
View File
@@ -6,7 +6,7 @@ This directory contains the tools and the data that allows Nix to manage Gradle
Simply calling `generate.sh` should result in a `deps.json` file which is used in the derivation that provides Gradle dependencies when building the Android app.
You can see in [`nix/mobile/android/release.nix`](../../mobile/android/build.nix) that it's used via the `-Dmaven.repo.local='${deps.gradle}'` Gradle flag.
You can see in [`nix/mobile/android/release.nix`](../../mobile/android/release.nix) that it's used via the `-Dmaven.repo.local='${deps.gradle}'` Gradle flag.
# Files
+585 -79
View File
@@ -1055,6 +1055,21 @@
}
},
{
"path": "androidx/databinding/databinding-common/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"databinding-common-3.3.1.pom": {
"sha1": "2e932d3219ea5f6d1078b24a8a3ce24b209c9309",
"sha256": "sha256-J5Qv7Gy8ROM19MN5Rx/lo2BsA7Zwt+NG6lXxYtjrF10="
},
"databinding-common-3.3.1.jar": {
"sha1": "45795e2f688474b219d37beb7f9f6756578e6454",
"sha256": "sha256-mq9hUr+3QZCgovJ1St/aoqkP7Ef50KwR811ej5iYkyw="
}
}
},
{
"path": "androidx/databinding/databinding-common/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -1164,6 +1179,21 @@
}
},
{
"path": "androidx/databinding/databinding-compiler-common/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"databinding-compiler-common-3.3.1.pom": {
"sha1": "123c2b1dd44ec6e2441be9441bdf393462936928",
"sha256": "sha256-na2hPeqxkcTcC9T7EvFs12+r1ygfSfnOHIirb3kXyzI="
},
"databinding-compiler-common-3.3.1.jar": {
"sha1": "e96aa159e1ed5c5a3461d15adfc42ef5b1f68b59",
"sha256": "sha256-sfLOroi0d73GMp2r8SCNhCHFrT/HzPpEOXEOVBcvxh0="
}
}
},
{
"path": "androidx/databinding/databinding-compiler-common/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -2725,6 +2755,21 @@
}
},
{
"path": "com/android/databinding/baseLibrary/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"baseLibrary-3.3.1.pom": {
"sha1": "611fd96b47fdd27dd88afc23829975278d47774c",
"sha256": "sha256-dKLQobB7s6ExmWyEIG/CHmDQaT4pa7EI07c9B7hnUj8="
},
"baseLibrary-3.3.1.jar": {
"sha1": "702acc804e85563d3ae7b8ee49122e4f857dde83",
"sha256": "sha256-5QRyEqpp1J0FULCvlrQQC4xslwG4PD+24ZzGbzxK6cQ="
}
}
},
{
"path": "com/android/databinding/baseLibrary/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -3243,6 +3288,21 @@
}
},
{
"path": "com/android/tools/analytics-library/crash/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"crash-26.3.1.pom": {
"sha1": "7b667eb48f02b8ba2a981a962e9c1137e251c1e0",
"sha256": "sha256-m0FH4hP4dmWwzUXF6w47Q79EWJf5r9rKF/c8wjjF01c="
},
"crash-26.3.1.jar": {
"sha1": "46163f2cf0e16a1ba9be2ad6dddc39f1a1d6b613",
"sha256": "sha256-k5OoPOLz+pZ4LCU98yROaZo7PfGG3pJssTiVj6+VYpM="
}
}
},
{
"path": "com/android/tools/analytics-library/crash/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -3382,6 +3442,21 @@
}
},
{
"path": "com/android/tools/analytics-library/protos/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"protos-26.3.1.pom": {
"sha1": "d6015a3a017dcb62d9a9a56c28b5c47bb6727a91",
"sha256": "sha256-IP1qlda7IElg7qdLFBTEWy78J0+4Tf90MnqRYezfc3k="
},
"protos-26.3.1.jar": {
"sha1": "f35a0accd93cfbb4306268ea748e1ac49920a0a8",
"sha256": "sha256-70/09xLY//RrI3jBwQh5l1hXdvpsGhwgBpbXd0eNnUw="
}
}
},
{
"path": "com/android/tools/analytics-library/protos/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -3521,6 +3596,21 @@
}
},
{
"path": "com/android/tools/analytics-library/shared/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"shared-26.3.1.pom": {
"sha1": "af1e1e7d120696bfee452247b5224290d91d828f",
"sha256": "sha256-3Hxmxmp5mFLNaGRaEXOJSRxiTU1U+OzdX5QENgHtys4="
},
"shared-26.3.1.jar": {
"sha1": "3457faee7a68d84dcbd258889567153acfc731a2",
"sha256": "sha256-bSe5quJj4rwth0SR72dh86WuH34wzEq2v7ktd/2tO/A="
}
}
},
{
"path": "com/android/tools/analytics-library/shared/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -3660,6 +3750,21 @@
}
},
{
"path": "com/android/tools/analytics-library/tracker/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"tracker-26.3.1.pom": {
"sha1": "6775a4eeafd2ef5270750388ee53503eeafa688b",
"sha256": "sha256-+mgVCnuDFGnXWVQ1ZGPkmcJjl1ubk/YmTQ3qjRHlKwg="
},
"tracker-26.3.1.jar": {
"sha1": "26248cad2525e003752322cfc6bd86182df7daac",
"sha256": "sha256-JG6AgEtANgzjGNp7nRKUjgrUHQwpzHvbOGF9weaWnYg="
}
}
},
{
"path": "com/android/tools/analytics-library/tracker/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -3799,6 +3904,21 @@
}
},
{
"path": "com/android/tools/annotations/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"annotations-26.3.1.pom": {
"sha1": "bce2159e811cceee12498cb34812cbae1e7b8eda",
"sha256": "sha256-Y7XWCr1wC4On07xPXk1+cRxZsOB6WsMmd2FOP/1xJLE="
},
"annotations-26.3.1.jar": {
"sha1": "3d46d5da6d5dd17df682a22b914cdc6b84677731",
"sha256": "sha256-U0rc5Q64KdT4yXW8NOpVs49oxjAOAA4rR8Q6xnLQxyE="
}
}
},
{
"path": "com/android/tools/annotations/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -4226,6 +4346,21 @@
}
},
{
"path": "com/android/tools/build/apksig/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"apksig-3.3.1.pom": {
"sha1": "e916d810d293ce4ab620435b41d2e3bc67972cd3",
"sha256": "sha256-cGliMgmhK5sal8XJypuekagqDkDG4h4LlMc5barHh80="
},
"apksig-3.3.1.jar": {
"sha1": "5dc32667e573a18b05119685ac3f2b8c0f17182d",
"sha256": "sha256-NXs57dinjUgKlT5rl8CYWf1AyXLBpJtvnTvT1LmYyy0="
}
}
},
{
"path": "com/android/tools/build/apksig/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -4335,6 +4470,21 @@
}
},
{
"path": "com/android/tools/build/apkzlib/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"apkzlib-3.3.1.pom": {
"sha1": "02214cdec00c2553430192a7f36e9a28cf96bf6f",
"sha256": "sha256-IVhIC03ar9F8K15CEeAPstojFB93BY+VjRqUlFBZ0IU="
},
"apkzlib-3.3.1.jar": {
"sha1": "0563a5b71668b4fe7da03a0a3054c9fdd973d3cf",
"sha256": "sha256-ZAVmwOT1BZATm7z7sP90TB9tzZ8mL48tAVn8QZQTgcw="
}
}
},
{
"path": "com/android/tools/build/apkzlib/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -4474,6 +4624,21 @@
}
},
{
"path": "com/android/tools/build/builder-model/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"builder-model-3.3.1.pom": {
"sha1": "4011d22709777c4063e84d39dbfe4ed535a31905",
"sha256": "sha256-XVNezIVtl4YN/ZElCFrqki4FTrfZ4SRPg3p0n76b++M="
},
"builder-model-3.3.1.jar": {
"sha1": "2c47cf0451da2eaad484ccd2d580a8cfd23fa064",
"sha256": "sha256-BXtSlcP+jNze+uaN47+/nHbTnaI+BMw0ZdZgA3oxfwA="
}
}
},
{
"path": "com/android/tools/build/builder-model/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -4625,6 +4790,21 @@
}
},
{
"path": "com/android/tools/build/builder-test-api/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"builder-test-api-3.3.1.pom": {
"sha1": "e79a310b9c89fcb62f343b727f5747783c778861",
"sha256": "sha256-heZof7B9lqEFRE1Rouwnrz9798H5w72QcGZ9QblfZAY="
},
"builder-test-api-3.3.1.jar": {
"sha1": "c1a1ce91c0f34c43a52c54c1a2f6fdbaafadd3da",
"sha256": "sha256-KYnV5vE5YwFoEC40dwJCFbnKvew+Gqc4saBze0tfyww="
}
}
},
{
"path": "com/android/tools/build/builder-test-api/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -4776,6 +4956,21 @@
}
},
{
"path": "com/android/tools/build/builder/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"builder-3.3.1.pom": {
"sha1": "fbca96adc8069b8fcb01c7271c3b4be4f901b517",
"sha256": "sha256-pg/e6U4EqMemXDi6m2UFhcOkv0cisGFnuI85cO4UA+Q="
},
"builder-3.3.1.jar": {
"sha1": "e4d2ad1ef694fca700b3ab1f4df4b79313d17c98",
"sha256": "sha256-zoj1PYZLXN+oW1cC5yiz1u0NOqkoy2HghCRtSlUBXFI="
}
}
},
{
"path": "com/android/tools/build/builder/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -4897,6 +5092,21 @@
}
},
{
"path": "com/android/tools/build/bundletool/0.6.0",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"bundletool-0.6.0.pom": {
"sha1": "5a6e5b5af1687285125f43e00a8e5a8efe6f76a4",
"sha256": "sha256-YDqi6WyRrkPynACNA16mdo0fJya6qjAqXwzYBFfgRiI="
},
"bundletool-0.6.0.jar": {
"sha1": "fb944be26f692e6ac937924ad5be7faa4093dd80",
"sha256": "sha256-QAU1QDlstRlZ0GYLSihk7mqBaXi/AT/UwB3L7IlcS7o="
}
}
},
{
"path": "com/android/tools/build/bundletool/0.9.0",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5032,6 +5242,21 @@
}
},
{
"path": "com/android/tools/build/gradle-api/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"gradle-api-3.3.1.pom": {
"sha1": "c9a6cecdb5e233c2ffde76507bddc6f26ade5528",
"sha256": "sha256-3BUSdrg4w9TdT8QdcwRoOkTGotjb3ngpdN9p+1g8dRQ="
},
"gradle-api-3.3.1.jar": {
"sha1": "93aac19942998e480db4195212150fb30f7a78cd",
"sha256": "sha256-SMmx/OFMswX3/3XdL97Ds/qtZK/pFQbviYoEsIbmtBY="
}
}
},
{
"path": "com/android/tools/build/gradle-api/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5232,6 +5457,21 @@
}
},
{
"path": "com/android/tools/build/gradle/3.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"gradle-3.3.1.pom": {
"sha1": "1769370bffda87132eb79580bf54ccb9eb339020",
"sha256": "sha256-9eitp3Q6B3or5f+qF0Q0VmkSQa7ZEoYVgAXzUcRA/3w="
},
"gradle-3.3.1.jar": {
"sha1": "7d642f14aa35443dd7aeecd0600c17da37d3bccc",
"sha256": "sha256-9WSZq8Ux35uuhlFo5y8kCHAtSgH0bXuMGgowDWLcEb0="
}
}
},
{
"path": "com/android/tools/build/gradle/3.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5353,6 +5593,21 @@
}
},
{
"path": "com/android/tools/build/jetifier/jetifier-core/1.0.0-beta02",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"jetifier-core-1.0.0-beta02.pom": {
"sha1": "db878af76000b681798b114a5169163b1efe59ea",
"sha256": "sha256-kJGGklY7MCjkeLrxyUM3jfSIOTpSeJWMbzaWO2jfw7k="
},
"jetifier-core-1.0.0-beta02.jar": {
"sha1": "fa93fdb83bdfd51e80e09a808fb2515a7134d406",
"sha256": "sha256-72H4QwL4tB3OOFjB/H56kOx0omOgITsfZegMVhRaR5M="
}
}
},
{
"path": "com/android/tools/build/jetifier/jetifier-core/1.0.0-beta04",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5417,6 +5672,21 @@
}
},
{
"path": "com/android/tools/build/jetifier/jetifier-processor/1.0.0-beta02",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"jetifier-processor-1.0.0-beta02.pom": {
"sha1": "3bf006f5a449806a9ad493a99c9f9417b3040ef0",
"sha256": "sha256-+zYwiX233O8PE6VViKrYxkvcGPZ64KHizNR1igcioa8="
},
"jetifier-processor-1.0.0-beta02.jar": {
"sha1": "624d187319c8dfd6bc8281b4afbab87c39bbb005",
"sha256": "sha256-J+UFZWvlNLNIYHQy/EEeKVQLCE0NTkhlIyqnYswe9Aw="
}
}
},
{
"path": "com/android/tools/build/jetifier/jetifier-processor/1.0.0-beta04",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5511,6 +5781,21 @@
}
},
{
"path": "com/android/tools/build/manifest-merger/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"manifest-merger-26.3.1.pom": {
"sha1": "1aad18d13e7389cf148b1c6c468b2947ca23cbbd",
"sha256": "sha256-YNhLNKJlpgVeZhxpOvIFB1mgbYpuXLpk370esi0vpPU="
},
"manifest-merger-26.3.1.jar": {
"sha1": "aa94f738e318fc73059d9207f433f13556072d05",
"sha256": "sha256-hNrba75FBJgCeexO/2RdkaGgsPpagAQjmjS5vOZ1crU="
}
}
},
{
"path": "com/android/tools/build/manifest-merger/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5662,6 +5947,21 @@
}
},
{
"path": "com/android/tools/common/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"common-26.3.1.pom": {
"sha1": "b79360c83ea68ba7f0ac0fadf7c48e1a53511352",
"sha256": "sha256-mvrBYjeX9GBEevDT9gMuQfLdXx1N7pSbd3OBSR6NxVM="
},
"common-26.3.1.jar": {
"sha1": "b0e3aa846dd94f9608018f7ef6501d1069f6488c",
"sha256": "sha256-QashymLYGxzYciSbVSlD1rzTZmN32f1/cY3rQd7HM9Y="
}
}
},
{
"path": "com/android/tools/common/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5801,6 +6101,21 @@
}
},
{
"path": "com/android/tools/ddms/ddmlib/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"ddmlib-26.3.1.pom": {
"sha1": "14405d92c982c96ace23b7a4c505b0d9de58cd8d",
"sha256": "sha256-MhUp9OEUJ8VtX0uLtcJkLAHza1LkO1wwnEk81IM9sNE="
},
"ddmlib-26.3.1.jar": {
"sha1": "61ca2873fcce1012ba9782adf7e9b0e164fb6007",
"sha256": "sha256-oTYJ+lhJr4+Os0JzaOG8KMp7DwSvKGwLqVoAfrkkHro="
}
}
},
{
"path": "com/android/tools/ddms/ddmlib/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -5940,6 +6255,21 @@
}
},
{
"path": "com/android/tools/dvlib/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"dvlib-26.3.1.pom": {
"sha1": "c438f3c025bd878ac3b54368e012b3792f9c8928",
"sha256": "sha256-3lL/6GFK8OCRXxbiIujskxfriVuL9GtfE7hU8B2mDdY="
},
"dvlib-26.3.1.jar": {
"sha1": "971430b6163a834656d07434c46fee64d109ad8e",
"sha256": "sha256-cLMOL4Sc+kKqE7+GWenhTAKtfLSkbLKB4CKOuC5XM4s="
}
}
},
{
"path": "com/android/tools/dvlib/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -6184,6 +6514,21 @@
}
},
{
"path": "com/android/tools/layoutlib/layoutlib-api/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"layoutlib-api-26.3.1.pom": {
"sha1": "0355e0146c59a91fbb303d7faaa6d2d0413f5dde",
"sha256": "sha256-az/hSE+y4dWr/4VYc0KxX5tM3W6E/Vkjm9r7ShTtLXg="
},
"layoutlib-api-26.3.1.jar": {
"sha1": "969ef3a7c0c3b245a3efe8aff7a2f6f15ff4e824",
"sha256": "sha256-Tk6yS7wTU2sl1t063kHZJWr1rnuBpBe5a1WEMLUKQV4="
}
}
},
{
"path": "com/android/tools/layoutlib/layoutlib-api/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -6383,6 +6728,21 @@
}
},
{
"path": "com/android/tools/lint/lint-gradle-api/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"lint-gradle-api-26.3.1.pom": {
"sha1": "dbdbed4b5fa948b991335771c7005fc8aa8be73b",
"sha256": "sha256-6xds70C7k1Yy8gaACv2XSeMP+suuYIgzflDCP2vG5CA="
},
"lint-gradle-api-26.3.1.jar": {
"sha1": "d55e1bcbe4e7c0bb97f5c385a003c4339e38d07f",
"sha256": "sha256-RcBjcp/izzXWOh/9Ih17gtPkpxWay2AvqWuc/5BN5sk="
}
}
},
{
"path": "com/android/tools/lint/lint-gradle-api/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -6657,6 +7017,21 @@
}
},
{
"path": "com/android/tools/repository/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"repository-26.3.1.pom": {
"sha1": "ab5a2f6cbedccf4ff9efbd5301fe26c9d1aaea2a",
"sha256": "sha256-VRlYrn5H3gUTtUim8TrCf8Bv8/Ww/x6aQ8SAjzRz6zc="
},
"repository-26.3.1.jar": {
"sha1": "0fe4c713437ebfb8c68e95c717c063843bd63758",
"sha256": "sha256-UZR25PiBJMbbndC98J8MSqXMi/Hvq4Dd3uL3Wmug784="
}
}
},
{
"path": "com/android/tools/repository/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -6796,6 +7171,21 @@
}
},
{
"path": "com/android/tools/sdklib/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"sdklib-26.3.1.pom": {
"sha1": "d6cfc0d8a0f49620138cfaea6c51201c7c678633",
"sha256": "sha256-gnUcqRaojEMoL7ZX1kJerqAstwsEAJlroYEZr6GRRCE="
},
"sdklib-26.3.1.jar": {
"sha1": "85c3c1de8824ca1f5ff491690931256c23a7297b",
"sha256": "sha256-aEN9Fbfmle8G6Yu88HEQQJlVtjsBijR7pofwGuxQfQo="
}
}
},
{
"path": "com/android/tools/sdklib/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -6935,6 +7325,21 @@
}
},
{
"path": "com/android/tools/sdk-common/26.3.1",
"repo": "https://dl.google.com/dl/android/maven2",
"files": {
"sdk-common-26.3.1.pom": {
"sha1": "9b7b4248e21db9c342dba7c3e891f740246b97c3",
"sha256": "sha256-jFp1bExxaochJmmIvOMohkjrj3uDF3DFct1Pcp85iqg="
},
"sdk-common-26.3.1.jar": {
"sha1": "c9bed0f05024f919fe6168ef381afbe72074a272",
"sha256": "sha256-s2dcStd5EUHIfzaADxkUIz8q9Rx2b+F67BsVIsgOL8g="
}
}
},
{
"path": "com/android/tools/sdk-common/26.5.4",
"repo": "https://dl.google.com/dl/android/maven2",
@@ -10937,6 +11342,17 @@
}
},
{
"path": "com/google/guava/guava-parent/26.0-jre",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"guava-parent-26.0-jre.pom": {
"sha1": "3a638a46e3277ff6a3d43d2a50bcccfac2966815",
"sha256": "sha256-u31c1BfA19714+Jwkv3SNSLT/CUa2KB5VsE84Fc66qM="
}
}
},
{
"path": "com/google/guava/guava-parent/27.0.1-jre",
"repo": "https://repo.maven.apache.org/maven2",
@@ -11089,6 +11505,21 @@
}
},
{
"path": "com/google/guava/guava/26.0-jre",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"guava-26.0-jre.pom": {
"sha1": "7883e19f8b0cca8c4498d476743e31b107674155",
"sha256": "sha256-HDN63JpKtLhE2oHahZNlgbiUbHy3EoTF3L2vHqp+4Qk="
},
"guava-26.0-jre.jar": {
"sha1": "6a806eff209f36f635f943e16d97491f00f6bfab",
"sha256": "sha256-oOnKutZlvCC80rAfEI5fwD91bhOuqAq6rbn0BwM76iw="
}
}
},
{
"path": "com/google/guava/guava/27.0.1-jre",
"repo": "https://repo.maven.apache.org/maven2",
@@ -11344,12 +11775,12 @@
},
{
"path": "com/google/protobuf/protobuf-bom/4.26.0-RC1",
"path": "com/google/protobuf/protobuf-bom/4.0.0-rc-2",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"protobuf-bom-4.26.0-RC1.pom": {
"sha1": "95b890ee6f318b67514a9d3573c78aebfd8cf4c1",
"sha256": "sha256-rGscgQUEAvrvFw6SnyMSbIw7N0J6SEgo4bo8nmAbO04="
"protobuf-bom-4.0.0-rc-2.pom": {
"sha1": "1cf14b7774313bc34805dd58fffa3cbc35601184",
"sha256": "sha256-45/pSYKw70HwkoTPbtPkj0Bsu/ZtioKD0MYmk04KYTI="
}
}
},
@@ -11520,16 +11951,16 @@
},
{
"path": "com/google/protobuf/protobuf-java/4.26.0-RC1",
"path": "com/google/protobuf/protobuf-java/4.0.0-rc-2",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"protobuf-java-4.26.0-RC1.pom": {
"sha1": "9b053265705abd2eb8dd06831b4728ed19e8f79a",
"sha256": "sha256-cexXywR1/FPS885SUYezfvvww1TAjy6gAtAmxJVxn0Y="
"protobuf-java-4.0.0-rc-2.pom": {
"sha1": "8fab0fe0746b1d370663a3db7dd483c2c4d34a6f",
"sha256": "sha256-q//aKX5NdsCktWMRsnjG/L3jNI9g/ucIGLN119ZzT50="
},
"protobuf-java-4.26.0-RC1.jar": {
"sha1": "a4718e6e4943736bb27aa3c7f8ef3c0a851c35b1",
"sha256": "sha256-cgTa51zMiegEQa2I9pyGy9psCQ5tPJU9MfMoC8DyDDg="
"protobuf-java-4.0.0-rc-2.jar": {
"sha1": "ae590f34383d2d6fde2b3b8e2ffb668e64579099",
"sha256": "sha256-PMJSvvZfetM8UwzuxxZkzR2gsmUhrWZzpl2fpJMegio="
}
}
},
@@ -11627,38 +12058,38 @@
},
{
"path": "com/google/protobuf/protobuf-parent/4.26.0-RC1",
"path": "com/google/protobuf/protobuf-parent/4.0.0-rc-2",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"protobuf-parent-4.26.0-RC1.pom": {
"sha1": "80963cafb79bc1b0f5dd2c1c82c67016c2362ad4",
"sha256": "sha256-n+4hEMufYvUwFQts4WiDUYKyGGnivQQhyc2bS7fODMs="
"protobuf-parent-4.0.0-rc-2.pom": {
"sha1": "c5391c7917ca1197cbbda4efc6454a87e7e7107e",
"sha256": "sha256-4NJwgSugXAqrlx4wtRyl0VcmYBkGxiGsIM3LLkq2fi8="
}
}
},
{
"path": "com/google/truth/truth-parent/1.4.0",
"path": "com/google/truth/truth-parent/1.2.0",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"truth-parent-1.4.0.pom": {
"sha1": "08b3f870d82e4e34caa1aa94ca03c29d9b40d3d2",
"sha256": "sha256-K+3ssiZ3EYKh/sxgh3NFLyTPuMEjreDzymb4pmmU3Gs="
"truth-parent-1.2.0.pom": {
"sha1": "d24447b2a11846a354e503575ed95e393ba5158d",
"sha256": "sha256-Q8/2l2yxZ5ETlTWluYDpwTW8Fgxk7hGc/6qNHv9aquI="
}
}
},
{
"path": "com/google/truth/truth/1.4.0",
"path": "com/google/truth/truth/1.2.0",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"truth-1.4.0.pom": {
"sha1": "6ff4bdfe8a3758a755b52ad894b7d983c88e4850",
"sha256": "sha256-v4+lYqfRXWNEU9f/LidC/eACm2VNhwtK0uejf89mTnY="
"truth-1.2.0.pom": {
"sha1": "44853be2a0532449235377b3eea680b679cefa7e",
"sha256": "sha256-4snQPEXLKYR49KPOM37mXXsk+nVA/PSEy/OkvuQCuVo="
},
"truth-1.4.0.jar": {
"sha1": "2a9475ed8cf2081b859fda8f9c860d5c449cd9ed",
"sha256": "sha256-I1wo6W7mcBqwHMhS+ylMsPNHVvY2qBVLmu8I+xIVu8Q="
"truth-1.2.0.jar": {
"sha1": "0135db6c1dfab1b3ca326c8ce51c09381d332d43",
"sha256": "sha256-tGEIQNXjffFOZqqwuEDA7j+l6Vl9o6KQIGQYcXHCM5o="
}
}
},
@@ -13690,16 +14121,16 @@
},
{
"path": "net/bytebuddy/byte-buddy-agent/1.14.11",
"path": "net/bytebuddy/byte-buddy-agent/1.14.10",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"byte-buddy-agent-1.14.11.pom": {
"sha1": "00a2165ce3253489dd9fd0836a169dfce74e2042",
"sha256": "sha256-VBMQ/3WsTurkYFUJn8Ec3b5TqcBe6vry9wMgZQ2zzOk="
"byte-buddy-agent-1.14.10.pom": {
"sha1": "ab24aa41b81d9496ec9ccd188a0449327d93bfdf",
"sha256": "sha256-U7yX6ca/fC0OX5y6x9Xeaykk2RbPS4F+ajo1kpx5a0o="
},
"byte-buddy-agent-1.14.11.jar": {
"sha1": "f9cb566608fbac6bc7bf54901a7aa11543a989ee",
"sha256": "sha256-L1N6Yhpk+nAT1oxpWnajTujXna105jXKyhbdViV664A="
"byte-buddy-agent-1.14.10.jar": {
"sha1": "90ed94ac044ea8953b224304c762316e91fd6b31",
"sha256": "sha256-Z5k6idR8pY/4aIAqREjd0VDl/k5aVkXe2ZDXtNVXprk="
}
}
},
@@ -13727,12 +14158,12 @@
},
{
"path": "net/bytebuddy/byte-buddy-parent/1.14.11",
"path": "net/bytebuddy/byte-buddy-parent/1.14.10",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"byte-buddy-parent-1.14.11.pom": {
"sha1": "696bf3e007e88bd1c0c2d877d74e0f3c56f2b96f",
"sha256": "sha256-RsDxP8l3jcLrtpdIgjqixMvwfqt9GMaqGRxSnRZQiSs="
"byte-buddy-parent-1.14.10.pom": {
"sha1": "4c560a925c30d5911dc875af5af4737e21b397be",
"sha256": "sha256-xpghkGD7DlZaDyyWCU6Ssg7+FG/WFjayyeTAO9m6Sns="
}
}
},
@@ -13768,16 +14199,16 @@
},
{
"path": "net/bytebuddy/byte-buddy/1.14.11",
"path": "net/bytebuddy/byte-buddy/1.14.10",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"byte-buddy-1.14.11.pom": {
"sha1": "5ecfcd2f75aa8c7b6347d864a4d0a5212c360301",
"sha256": "sha256-NYRJ1sc1OFhFCN2K5s/eVrr0o0t2e3HZzEZE8PH0IRo="
"byte-buddy-1.14.10.pom": {
"sha1": "8806052a8770a6b3e14362ed0ce6ef263e6a20ab",
"sha256": "sha256-zVh4KEX/ju3y7YOgw+30Xu65nhTAWvii6QGGDqCAzq8="
},
"byte-buddy-1.14.11.jar": {
"sha1": "725602eb7c8c56b51b9c21f273f9df5c909d9e7d",
"sha256": "sha256-Yq4oGH7SsGKBPaap1We/7nM8NBWCaZti3ZgCMHKaAxM="
"byte-buddy-1.14.10.jar": {
"sha1": "8117daf4a612122eb4f517f66adff778cb8b4737",
"sha256": "sha256-MObgRGQ3pn2zfit/fTP1B4fd/ZcDWTGd/QVGnaoty84="
}
}
},
@@ -17391,6 +17822,21 @@
}
},
{
"path": "org/jetbrains/kotlin/kotlin-reflect/1.3.20",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-reflect-1.3.20.pom": {
"sha1": "7cc0e8dc8e9bf863127aee4501449e25e85a6f78",
"sha256": "sha256-ajZdjTUpX69X8t86ssuQQgnaqsiQb8Y3R9Pjv6sJPeI="
},
"kotlin-reflect-1.3.20.jar": {
"sha1": "cd49eec32cf964333faf59e04b4085eac7008477",
"sha256": "sha256-7hqSbtZY594ObfAkLNV0s7TgjmT+emgngibG8tM3Mjg="
}
}
},
{
"path": "org/jetbrains/kotlin/kotlin-reflect/1.3.50",
"repo": "https://repo.maven.apache.org/maven2",
@@ -17512,16 +17958,16 @@
},
{
"path": "org/jetbrains/kotlin/kotlin-reflect/2.0.0-Beta3",
"path": "org/jetbrains/kotlin/kotlin-reflect/2.0.0-Beta2",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-reflect-2.0.0-Beta3.pom": {
"sha1": "dc97aad46542eaa0cb64120911ac1013483969ac",
"sha256": "sha256-NnPskjZQvqH3zdWL94mDT/EMvy51senYGEbKjz+ya64="
"kotlin-reflect-2.0.0-Beta2.pom": {
"sha1": "71908b10dd3fefa0509880918948931ad0b8d7c8",
"sha256": "sha256-TmkaczZz+Eqbux6yz2SyE9WhflLrknrULgk8j/2sfUs="
},
"kotlin-reflect-2.0.0-Beta3.jar": {
"sha1": "6915153788502bdccc98753f41dcbd5bf7c7e128",
"sha256": "sha256-k4zOXYaKP8MBwjWAOLuEt0ahsLlSHtdnldJma/o0e2Y="
"kotlin-reflect-2.0.0-Beta2.jar": {
"sha1": "0cf9ed5d13e31c4e4ab74be627b7cedc0ecc7715",
"sha256": "sha256-PAz62O51jigTUVGhAJHGrWdbLoVdCFwwhhI883u50bw="
}
}
},
@@ -17781,6 +18227,21 @@
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib-common/1.3.20",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-stdlib-common-1.3.20.pom": {
"sha1": "507fa9faf5120c5c5247bc1b23476ad91760c09c",
"sha256": "sha256-BIjdHCYv5hfXc2K8Sa+BjYztQJQ6pbA8GITb8kdRCjA="
},
"kotlin-stdlib-common-1.3.20.jar": {
"sha1": "7d7934e26ce34da1a0a8d00e38038d7cf3375e89",
"sha256": "sha256-Br3Yrto0fvbvPk6diKASVMzbcHhLaXSV9qQh/WY6tkk="
}
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib-common/1.3.31",
"repo": "https://repo.maven.apache.org/maven2",
@@ -18066,6 +18527,21 @@
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.20",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-stdlib-jdk7-1.3.20.pom": {
"sha1": "665178dfa4d04de64edecf5f0dbda61b55f8f4e3",
"sha256": "sha256-SdtmBiZNOmpI+QgzXASEYirVyPTfjEjdSgAmdA4eFsU="
},
"kotlin-stdlib-jdk7-1.3.20.jar": {
"sha1": "aa17d6fd473ce53061a7b2b9d2ae96f547cae93d",
"sha256": "sha256-/Sr3C90rwCT7A8vtYzyhQ4cso2pqFuIYzGfIkLefsx0="
}
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.50",
"repo": "https://repo.maven.apache.org/maven2",
@@ -18246,6 +18722,21 @@
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.20",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-stdlib-jdk8-1.3.20.pom": {
"sha1": "5c65523f57e3918ef722a15faae5173fc9a31331",
"sha256": "sha256-DF+73Rh7hSpRoKP7YskCSdpOdN//jf/5RphOL3AlCkI="
},
"kotlin-stdlib-jdk8-1.3.20.jar": {
"sha1": "b1f3cb184c4ce4139741454df2f8fca5320f822d",
"sha256": "sha256-bAgx5+OsqjkL8i952B8y8hLcj94ZgHo1Sk7k9migxHg="
}
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.50",
"repo": "https://repo.maven.apache.org/maven2",
@@ -18471,6 +18962,21 @@
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib/1.3.20",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-stdlib-1.3.20.pom": {
"sha1": "9d1e01f424795aa471a8def0b5dc8aeeb537aafd",
"sha256": "sha256-Mu+dGkDXXOr0F5KW7VTdylp+ekpl4aAZ5kmOusg14Rw="
},
"kotlin-stdlib-1.3.20.jar": {
"sha1": "eb2a232734e09fcd1b958a5c7520a93c6de38b32",
"sha256": "sha256-YB+RDalo+z2o6te2Tta/XJcQ2DzqN+SmMYR+fWiOM2E="
}
}
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib/1.3.31",
"repo": "https://repo.maven.apache.org/maven2",
@@ -18769,28 +19275,28 @@
},
{
"path": "org/jetbrains/kotlin/kotlin-stdlib/2.0.0-Beta3",
"path": "org/jetbrains/kotlin/kotlin-stdlib/2.0.0-Beta2",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"kotlin-stdlib-2.0.0-Beta3.pom": {
"sha1": "1005b3f259dffb93f972e5227eb18fc579b71811",
"sha256": "sha256-2qxjaqrwUBME9CbB4lpEKGV4qi2VGn8USteyCSZ8lq4="
"kotlin-stdlib-2.0.0-Beta2.pom": {
"sha1": "a1310fbc42c0cbc786766d2e35dcbfdaf3f8a8b1",
"sha256": "sha256-8upeJFveFokz2f2rBOXj2KZ9+OzyWxWtqZ9/2qcJGnI="
},
"kotlin-stdlib-2.0.0-Beta3-all.jar": {
"sha1": "845c7a75152307a41522e800bb9706a58e02b228",
"sha256": "sha256-YwNHMM8zT64dAULHPNt+zLXQ5xTeAvtP/HKybthMDWI="
"kotlin-stdlib-2.0.0-Beta2-all.jar": {
"sha1": "c844df2813fa56f8baa346530a5172ccf03277d0",
"sha256": "sha256-o8TV9hZ9IGumB5g+8nq6R6YU+VxlRV0PJ3IsSsMRsSM="
},
"kotlin-stdlib-2.0.0-Beta3-common.jar": {
"kotlin-stdlib-2.0.0-Beta2-common.jar": {
"sha1": "e0224f6b9468655e1feffe789ab7ebd4965a9431",
"sha256": "sha256-ikItp8AZFxM/bokvCF68e2Q+oNGbbJxTILtPDnj7uMI="
},
"kotlin-stdlib-2.0.0-Beta3.jar": {
"sha1": "9982637ebb69602015ed823cceca7054d2ab8bbe",
"sha256": "sha256-1+6KuGuMgmiuPLpxx+cJSZ3/pnVOMmLdtzmk3mwB0ro="
"kotlin-stdlib-2.0.0-Beta2.jar": {
"sha1": "61be8a13ad24f43c915ba6962440cd30af4700ec",
"sha256": "sha256-yDOkRXCSzieZ5nejro0ku4suO6qDwWlDBdnb5ZHgquA="
},
"kotlin-stdlib-2.0.0-Beta3.module": {
"sha1": "5026675037ebf81e108eb3cc581a24570ec7ceb2",
"sha256": "sha256-rlVFQM89Ga0h57LsViIgT8iSdE18G0rd/TN7/u9UKrU="
"kotlin-stdlib-2.0.0-Beta2.module": {
"sha1": "22702775430e8d3a9f8d824167e00484e07d5932",
"sha256": "sha256-J6vVZxhfZbGpw8tTtV4RQTPJrkFqMwetPevDDG/iO/U="
}
}
},
@@ -19055,16 +19561,16 @@
},
{
"path": "org/junit/junit-bom/5.10.2",
"path": "org/junit/junit-bom/5.10.1",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"junit-bom-5.10.2.pom": {
"sha1": "b25ed98a5bd08cdda60e569cf22822a760e76019",
"sha256": "sha256-Fp3ZBKSw9lIM/+ZYzGIpK/6fPBSpifqSEgckzeQ6mWg="
"junit-bom-5.10.1.pom": {
"sha1": "41a86ea51227739a5b7ca3430ae88ce44a64a42a",
"sha256": "sha256-IcSwKG9LIAaVd/9LIJeKhcEArIpGtvHIZy+6qzN7w/I="
},
"junit-bom-5.10.2.module": {
"sha1": "ce536748a853ae6ac09e7815fce0678a96cff778",
"sha256": "sha256-3iOxFLPkEZqP5usXvtWjhSgWaYus5nBxV51tkn67CAo="
"junit-bom-5.10.1.module": {
"sha1": "1b577334c47deb59a29dc31e5211499d0eb3c17b",
"sha256": "sha256-IbCvz//i7LN3D16wCuehn+rulOdx+jkYFzhQ2ueAZ7c="
}
}
},
@@ -19160,16 +19666,16 @@
},
{
"path": "org/mockito/mockito-core/5.10.0",
"path": "org/mockito/mockito-core/5.8.0",
"repo": "https://repo.maven.apache.org/maven2",
"files": {
"mockito-core-5.10.0.pom": {
"sha1": "25e309d012d326eef980de463edeb2a592cf9cdb",
"sha256": "sha256-D4gyKTuHHyO2/0QkET7mXBdfq9G2uswY7Dg8s5akOq8="
"mockito-core-5.8.0.pom": {
"sha1": "a2b7b33c5d649a2f48b1e7aab95d81671f66875f",
"sha256": "sha256-dJWKzd4UjzC/ox/8CFi2L3H2PMws602KjGfX9CjUOi0="
},
"mockito-core-5.10.0.jar": {
"sha1": "b3812fa2ee069f1d0b41c1c0155da79d0e1dcde0",
"sha256": "sha256-AyP1kbBNOg18qevuu56fNKB8DskWm3RE7jlRtx1MrVY="
"mockito-core-5.8.0.jar": {
"sha1": "df310627f77f859114ad31e1376fff0dce263cca",
"sha256": "sha256-wyD2YqA8KVHtzFGkS2TXmo6ZQ3P/VIRTtf2vad6+RoI="
}
}
},
+33
View File
@@ -49,6 +49,7 @@ androidx.core:core:1.7.0
androidx.cursoradapter:cursoradapter:1.0.0
androidx.customview:customview:1.0.0
androidx.databinding:databinding-common:3.2.1
androidx.databinding:databinding-common:3.3.1
androidx.databinding:databinding-common:3.5.4
androidx.databinding:databinding-common:4.1.0
androidx.databinding:databinding-common:7.0.4
@@ -56,6 +57,7 @@ androidx.databinding:databinding-common:7.2.1
androidx.databinding:databinding-common:7.3.1
androidx.databinding:databinding-common:7.4.2
androidx.databinding:databinding-compiler-common:3.2.1
androidx.databinding:databinding-compiler-common:3.3.1
androidx.databinding:databinding-compiler-common:3.5.4
androidx.databinding:databinding-compiler-common:4.1.0
androidx.databinding:databinding-compiler-common:7.0.4
@@ -157,6 +159,7 @@ com.android.databinding:baseLibrary:1.0-rc5
com.android.databinding:baseLibrary:3.0.0
com.android.databinding:baseLibrary:3.0.1
com.android.databinding:baseLibrary:3.2.1
com.android.databinding:baseLibrary:3.3.1
com.android.databinding:baseLibrary:3.5.4
com.android.databinding:baseLibrary:4.1.0
com.android.databinding:baseLibrary:7.0.4
@@ -167,6 +170,7 @@ com.android.databinding:compilerCommon:1.0-rc5
com.android.databinding:compilerCommon:3.0.0
com.android.databinding:compilerCommon:3.0.1
com.android.tools.analytics-library:crash:26.2.1
com.android.tools.analytics-library:crash:26.3.1
com.android.tools.analytics-library:crash:26.5.4
com.android.tools.analytics-library:crash:27.1.0
com.android.tools.analytics-library:crash:30.0.4
@@ -176,6 +180,7 @@ com.android.tools.analytics-library:crash:30.4.2
com.android.tools.analytics-library:protos:26.0.0
com.android.tools.analytics-library:protos:26.0.1
com.android.tools.analytics-library:protos:26.2.1
com.android.tools.analytics-library:protos:26.3.1
com.android.tools.analytics-library:protos:26.5.4
com.android.tools.analytics-library:protos:27.1.0
com.android.tools.analytics-library:protos:30.0.4
@@ -185,6 +190,7 @@ com.android.tools.analytics-library:protos:30.4.2
com.android.tools.analytics-library:shared:26.0.0
com.android.tools.analytics-library:shared:26.0.1
com.android.tools.analytics-library:shared:26.2.1
com.android.tools.analytics-library:shared:26.3.1
com.android.tools.analytics-library:shared:26.5.4
com.android.tools.analytics-library:shared:27.1.0
com.android.tools.analytics-library:shared:30.0.4
@@ -194,6 +200,7 @@ com.android.tools.analytics-library:shared:30.4.2
com.android.tools.analytics-library:tracker:26.0.0
com.android.tools.analytics-library:tracker:26.0.1
com.android.tools.analytics-library:tracker:26.2.1
com.android.tools.analytics-library:tracker:26.3.1
com.android.tools.analytics-library:tracker:26.5.4
com.android.tools.analytics-library:tracker:27.1.0
com.android.tools.analytics-library:tracker:30.0.4
@@ -201,10 +208,12 @@ com.android.tools.analytics-library:tracker:30.2.1
com.android.tools.analytics-library:tracker:30.3.1
com.android.tools.analytics-library:tracker:30.4.2
com.android.tools.build.jetifier:jetifier-core:1.0.0-alpha10
com.android.tools.build.jetifier:jetifier-core:1.0.0-beta02
com.android.tools.build.jetifier:jetifier-core:1.0.0-beta04
com.android.tools.build.jetifier:jetifier-core:1.0.0-beta09
com.android.tools.build.jetifier:jetifier-core:1.0.0-beta10
com.android.tools.build.jetifier:jetifier-processor:1.0.0-alpha10
com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta02
com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta04
com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta09
com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta10
@@ -223,6 +232,7 @@ com.android.tools.build:aaptcompiler:7.4.2
com.android.tools.build:apksig:3.0.0
com.android.tools.build:apksig:3.0.1
com.android.tools.build:apksig:3.2.1
com.android.tools.build:apksig:3.3.1
com.android.tools.build:apksig:3.5.4
com.android.tools.build:apksig:4.1.0
com.android.tools.build:apksig:7.0.4
@@ -230,6 +240,7 @@ com.android.tools.build:apksig:7.2.1
com.android.tools.build:apksig:7.3.1
com.android.tools.build:apksig:7.4.2
com.android.tools.build:apkzlib:3.2.1
com.android.tools.build:apkzlib:3.3.1
com.android.tools.build:apkzlib:3.5.4
com.android.tools.build:apkzlib:4.1.0
com.android.tools.build:apkzlib:7.0.4
@@ -241,6 +252,7 @@ com.android.tools.build:builder-model:1.5.0
com.android.tools.build:builder-model:3.0.0
com.android.tools.build:builder-model:3.0.1
com.android.tools.build:builder-model:3.2.1
com.android.tools.build:builder-model:3.3.1
com.android.tools.build:builder-model:3.5.4
com.android.tools.build:builder-model:4.1.0
com.android.tools.build:builder-model:7.0.4
@@ -252,6 +264,7 @@ com.android.tools.build:builder-test-api:1.5.0
com.android.tools.build:builder-test-api:3.0.0
com.android.tools.build:builder-test-api:3.0.1
com.android.tools.build:builder-test-api:3.2.1
com.android.tools.build:builder-test-api:3.3.1
com.android.tools.build:builder-test-api:3.5.4
com.android.tools.build:builder-test-api:4.1.0
com.android.tools.build:builder-test-api:7.0.4
@@ -263,6 +276,7 @@ com.android.tools.build:builder:1.5.0
com.android.tools.build:builder:3.0.0
com.android.tools.build:builder:3.0.1
com.android.tools.build:builder:3.2.1
com.android.tools.build:builder:3.3.1
com.android.tools.build:builder:3.5.4
com.android.tools.build:builder:4.1.0
com.android.tools.build:builder:7.0.4
@@ -270,6 +284,7 @@ com.android.tools.build:builder:7.2.1
com.android.tools.build:builder:7.3.1
com.android.tools.build:builder:7.4.2
com.android.tools.build:bundletool:0.5.0
com.android.tools.build:bundletool:0.6.0
com.android.tools.build:bundletool:0.9.0
com.android.tools.build:bundletool:0.14.0
com.android.tools.build:bundletool:1.6.0
@@ -279,6 +294,7 @@ com.android.tools.build:bundletool:1.11.4
com.android.tools.build:gradle-api:3.0.0
com.android.tools.build:gradle-api:3.0.1
com.android.tools.build:gradle-api:3.2.1
com.android.tools.build:gradle-api:3.3.1
com.android.tools.build:gradle-api:3.5.4
com.android.tools.build:gradle-api:4.1.0
com.android.tools.build:gradle-api:7.0.4
@@ -295,6 +311,7 @@ com.android.tools.build:gradle:1.5.0
com.android.tools.build:gradle:3.0.0
com.android.tools.build:gradle:3.0.1
com.android.tools.build:gradle:3.2.1
com.android.tools.build:gradle:3.3.1
com.android.tools.build:gradle:3.5.4
com.android.tools.build:gradle:4.1.0
com.android.tools.build:gradle:7.0.4
@@ -305,6 +322,7 @@ com.android.tools.build:manifest-merger:24.5.0
com.android.tools.build:manifest-merger:26.0.0
com.android.tools.build:manifest-merger:26.0.1
com.android.tools.build:manifest-merger:26.2.1
com.android.tools.build:manifest-merger:26.3.1
com.android.tools.build:manifest-merger:26.5.4
com.android.tools.build:manifest-merger:27.1.0
com.android.tools.build:manifest-merger:30.0.4
@@ -318,6 +336,7 @@ com.android.tools.ddms:ddmlib:24.5.0
com.android.tools.ddms:ddmlib:26.0.0
com.android.tools.ddms:ddmlib:26.0.1
com.android.tools.ddms:ddmlib:26.2.1
com.android.tools.ddms:ddmlib:26.3.1
com.android.tools.ddms:ddmlib:26.5.4
com.android.tools.ddms:ddmlib:27.1.0
com.android.tools.ddms:ddmlib:30.0.4
@@ -336,6 +355,7 @@ com.android.tools.layoutlib:layoutlib-api:24.5.0
com.android.tools.layoutlib:layoutlib-api:26.0.0
com.android.tools.layoutlib:layoutlib-api:26.0.1
com.android.tools.layoutlib:layoutlib-api:26.2.1
com.android.tools.layoutlib:layoutlib-api:26.3.1
com.android.tools.layoutlib:layoutlib-api:26.5.4
com.android.tools.layoutlib:layoutlib-api:27.1.0
com.android.tools.layoutlib:layoutlib-api:30.0.4
@@ -351,6 +371,7 @@ com.android.tools.lint:lint-checks:24.5.0
com.android.tools.lint:lint-checks:26.0.0
com.android.tools.lint:lint-checks:26.0.1
com.android.tools.lint:lint-gradle-api:26.2.1
com.android.tools.lint:lint-gradle-api:26.3.1
com.android.tools.lint:lint-gradle-api:26.5.4
com.android.tools.lint:lint-gradle-api:27.1.0
com.android.tools.lint:lint-model:27.1.0
@@ -391,6 +412,7 @@ com.android.tools:annotations:24.5.0
com.android.tools:annotations:26.0.0
com.android.tools:annotations:26.0.1
com.android.tools:annotations:26.2.1
com.android.tools:annotations:26.3.1
com.android.tools:annotations:26.5.4
com.android.tools:annotations:27.1.0
com.android.tools:annotations:30.0.4
@@ -402,6 +424,7 @@ com.android.tools:common:24.5.0
com.android.tools:common:26.0.0
com.android.tools:common:26.0.1
com.android.tools:common:26.2.1
com.android.tools:common:26.3.1
com.android.tools:common:26.5.4
com.android.tools:common:27.1.0
com.android.tools:common:30.0.4
@@ -413,6 +436,7 @@ com.android.tools:dvlib:24.5.0
com.android.tools:dvlib:26.0.0
com.android.tools:dvlib:26.0.1
com.android.tools:dvlib:26.2.1
com.android.tools:dvlib:26.3.1
com.android.tools:dvlib:26.5.4
com.android.tools:dvlib:27.1.0
com.android.tools:dvlib:30.0.4
@@ -422,6 +446,7 @@ com.android.tools:dvlib:30.4.2
com.android.tools:repository:26.0.0
com.android.tools:repository:26.0.1
com.android.tools:repository:26.2.1
com.android.tools:repository:26.3.1
com.android.tools:repository:26.5.4
com.android.tools:repository:27.1.0
com.android.tools:repository:30.0.4
@@ -433,6 +458,7 @@ com.android.tools:sdklib:24.5.0
com.android.tools:sdklib:26.0.0
com.android.tools:sdklib:26.0.1
com.android.tools:sdklib:26.2.1
com.android.tools:sdklib:26.3.1
com.android.tools:sdklib:26.5.4
com.android.tools:sdklib:27.1.0
com.android.tools:sdklib:30.0.4
@@ -444,6 +470,7 @@ com.android.tools:sdk-common:24.5.0
com.android.tools:sdk-common:26.0.0
com.android.tools:sdk-common:26.0.1
com.android.tools:sdk-common:26.2.1
com.android.tools:sdk-common:26.3.1
com.android.tools:sdk-common:26.5.4
com.android.tools:sdk-common:27.1.0
com.android.tools:sdk-common:30.0.4
@@ -563,6 +590,7 @@ com.google.guava:failureaccess:1.0.1
com.google.guava:guava:17.0
com.google.guava:guava:22.0
com.google.guava:guava:23.0
com.google.guava:guava:26.0-jre
com.google.guava:guava:27.0.1-jre
com.google.guava:guava:28.1-jre
com.google.guava:guava:29.0-jre
@@ -789,6 +817,7 @@ org.jetbrains.kotlin:kotlin-project-model:1.6.20
org.jetbrains.kotlin:kotlin-project-model:1.9.0
org.jetbrains.kotlin:kotlin-reflect:1.1.3-2
org.jetbrains.kotlin:kotlin-reflect:1.2.0
org.jetbrains.kotlin:kotlin-reflect:1.3.20
org.jetbrains.kotlin:kotlin-reflect:1.3.50
org.jetbrains.kotlin:kotlin-reflect:1.3.72
org.jetbrains.kotlin:kotlin-reflect:1.4.32
@@ -805,6 +834,7 @@ org.jetbrains.kotlin:kotlin-scripting-jvm:1.6.20
org.jetbrains.kotlin:kotlin-scripting-jvm:1.9.0
org.jetbrains.kotlin:kotlin-script-runtime:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.20
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50
org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72
org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32
@@ -813,6 +843,7 @@ org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.22
org.jetbrains.kotlin:kotlin-stdlib-common:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.20
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32
@@ -821,6 +852,7 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.20
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.22
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.20
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32
@@ -829,6 +861,7 @@ org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.22
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0
org.jetbrains.kotlin:kotlin-stdlib:1.1.3-2
org.jetbrains.kotlin:kotlin-stdlib:1.2.71
org.jetbrains.kotlin:kotlin-stdlib:1.3.20
org.jetbrains.kotlin:kotlin-stdlib:1.3.50
org.jetbrains.kotlin:kotlin-stdlib:1.3.72
org.jetbrains.kotlin:kotlin-stdlib:1.4.32
+46 -12
View File
@@ -62,6 +62,7 @@ https://dl.google.com/dl/android/maven2/androidx/core/core/1.7.0/core-1.7.0.pom
https://dl.google.com/dl/android/maven2/androidx/cursoradapter/cursoradapter/1.0.0/cursoradapter-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/customview/customview/1.0.0/customview-1.0.0.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/3.2.1/databinding-common-3.2.1.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/3.3.1/databinding-common-3.3.1.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/3.5.4/databinding-common-3.5.4.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/4.1.0/databinding-common-4.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/7.0.4/databinding-common-7.0.4.pom
@@ -69,6 +70,7 @@ https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/7.3.1/databinding-common-7.3.1.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-common/7.4.2/databinding-common-7.4.2.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-compiler-common/3.2.1/databinding-compiler-common-3.2.1.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-compiler-common/3.3.1/databinding-compiler-common-3.3.1.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-compiler-common/3.5.4/databinding-compiler-common-3.5.4.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-compiler-common/4.1.0/databinding-compiler-common-4.1.0.pom
https://dl.google.com/dl/android/maven2/androidx/databinding/databinding-compiler-common/7.0.4/databinding-compiler-common-7.0.4.pom
@@ -168,6 +170,7 @@ https://dl.google.com/dl/android/maven2/android/arch/lifecycle/runtime/1.0.0/run
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.0.0/baseLibrary-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.0.1/baseLibrary-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.2.1/baseLibrary-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.3.1/baseLibrary-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.5.4/baseLibrary-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/4.1.0/baseLibrary-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/7.0.4/baseLibrary-7.0.4.pom
@@ -202,6 +205,7 @@ https://dl.google.com/dl/android/maven2/com/android/support/support-v4/26.0.2/su
https://dl.google.com/dl/android/maven2/com/android/support/support-vector-drawable/26.0.2/support-vector-drawable-26.0.2.pom
https://dl.google.com/dl/android/maven2/com/android/support/support-vector-drawable/27.0.1/support-vector-drawable-27.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/crash/26.2.1/crash-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/crash/26.3.1/crash-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/crash/26.5.4/crash-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/crash/27.1.0/crash-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/crash/30.0.4/crash-30.0.4.pom
@@ -211,6 +215,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/cras
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/26.0.0/protos-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/26.0.1/protos-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/26.2.1/protos-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/26.3.1/protos-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/26.5.4/protos-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/27.1.0/protos-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/protos/30.0.4/protos-30.0.4.pom
@@ -220,6 +225,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/prot
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/26.0.0/shared-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/26.0.1/shared-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/26.2.1/shared-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/26.3.1/shared-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/26.5.4/shared-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/27.1.0/shared-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shared/30.0.4/shared-30.0.4.pom
@@ -229,6 +235,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/shar
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/26.0.0/tracker-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/26.0.1/tracker-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/26.2.1/tracker-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/26.3.1/tracker-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/26.5.4/tracker-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/27.1.0/tracker-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/tracker/30.0.4/tracker-30.0.4.pom
@@ -238,6 +245,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/analytics-library/trac
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/26.0.0/annotations-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/26.0.1/annotations-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/26.2.1/annotations-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/26.3.1/annotations-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/26.5.4/annotations-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/27.1.0/annotations-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/annotations/30.0.4/annotations-30.0.4.pom
@@ -263,6 +271,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/aaptcompiler/7.4
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/3.0.0/apksig-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/3.0.1/apksig-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/3.2.1/apksig-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/3.3.1/apksig-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/3.5.4/apksig-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/4.1.0/apksig-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/7.0.4/apksig-7.0.4.pom
@@ -270,6 +279,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/7.2.1/apk
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/7.3.1/apksig-7.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apksig/7.4.2/apksig-7.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apkzlib/3.2.1/apkzlib-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apkzlib/3.3.1/apkzlib-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apkzlib/3.5.4/apkzlib-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apkzlib/4.1.0/apkzlib-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/apkzlib/7.0.4/apkzlib-7.0.4.pom
@@ -279,6 +289,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/apkzlib/7.4.2/ap
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/3.0.0/builder-model-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/3.0.1/builder-model-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/3.2.1/builder-model-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/3.3.1/builder-model-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/3.5.4/builder-model-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/4.1.0/builder-model-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/7.0.4/builder-model-7.0.4.pom
@@ -288,6 +299,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-model/7.
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.0.0/builder-test-api-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.0.1/builder-test-api-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.2.1/builder-test-api-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.3.1/builder-test-api-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.5.4/builder-test-api-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/4.1.0/builder-test-api-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/7.0.4/builder-test-api-7.0.4.pom
@@ -297,6 +309,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.0.0/builder-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.0.1/builder-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.2.1/builder-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.3.1/builder-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.5.4/builder-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/4.1.0/builder-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/7.0.4/builder-7.0.4.pom
@@ -304,6 +317,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/7.2.1/bu
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/7.3.1/builder-7.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/7.4.2/builder-7.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/bundletool/0.5.0/bundletool-0.5.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/bundletool/0.6.0/bundletool-0.6.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/bundletool/0.9.0/bundletool-0.9.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/bundletool/0.14.0/bundletool-0.14.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/bundletool/1.6.0/bundletool-1.6.0.pom
@@ -313,6 +327,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/bundletool/1.11.
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/3.0.0/gradle-api-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/3.0.1/gradle-api-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/3.2.1/gradle-api-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/3.3.1/gradle-api-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/3.5.4/gradle-api-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/4.1.0/gradle-api-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-api/7.0.4/gradle-api-7.0.4.pom
@@ -325,6 +340,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle-settings-
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.0.0/gradle-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.0.1/gradle-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.2.1/gradle-3.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.3.1/gradle-3.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.5.4/gradle-3.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/4.1.0/gradle-4.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/7.0.4/gradle-7.0.4.pom
@@ -332,16 +348,19 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/7.2.1/gra
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/7.3.1/gradle-7.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/7.4.2/gradle-7.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-core/1.0.0-alpha10/jetifier-core-1.0.0-alpha10.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-core/1.0.0-beta02/jetifier-core-1.0.0-beta02.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-core/1.0.0-beta04/jetifier-core-1.0.0-beta04.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-core/1.0.0-beta09/jetifier-core-1.0.0-beta09.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-core/1.0.0-beta10/jetifier-core-1.0.0-beta10.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-processor/1.0.0-alpha10/jetifier-processor-1.0.0-alpha10.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-processor/1.0.0-beta02/jetifier-processor-1.0.0-beta02.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-processor/1.0.0-beta04/jetifier-processor-1.0.0-beta04.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-processor/1.0.0-beta09/jetifier-processor-1.0.0-beta09.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/jetifier/jetifier-processor/1.0.0-beta10/jetifier-processor-1.0.0-beta10.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/26.0.0/manifest-merger-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/26.0.1/manifest-merger-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/26.2.1/manifest-merger-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/26.3.1/manifest-merger-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/26.5.4/manifest-merger-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/27.1.0/manifest-merger-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/30.0.4/manifest-merger-30.0.4.pom
@@ -351,6 +370,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/build/manifest-merger/
https://dl.google.com/dl/android/maven2/com/android/tools/common/26.0.0/common-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/common/26.0.1/common-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/common/26.2.1/common-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/common/26.3.1/common-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/common/26.5.4/common-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/common/27.1.0/common-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/common/30.0.4/common-30.0.4.pom
@@ -360,6 +380,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/common/30.4.2/common-3
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/26.0.0/ddmlib-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/26.0.1/ddmlib-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/26.2.1/ddmlib-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/26.3.1/ddmlib-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/26.5.4/ddmlib-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/27.1.0/ddmlib-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/30.0.4/ddmlib-30.0.4.pom
@@ -369,6 +390,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/ddms/ddmlib/30.4.2/ddm
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/26.0.0/dvlib-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/26.0.1/dvlib-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/26.2.1/dvlib-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/26.3.1/dvlib-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/26.5.4/dvlib-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/27.1.0/dvlib-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/dvlib/30.0.4/dvlib-30.0.4.pom
@@ -385,6 +407,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/external/org-jetbrains
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/26.0.0/layoutlib-api-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/26.0.1/layoutlib-api-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/26.2.1/layoutlib-api-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/26.3.1/layoutlib-api-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/26.5.4/layoutlib-api-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/27.1.0/layoutlib-api-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/layoutlib/layoutlib-api/30.0.4/layoutlib-api-30.0.4.pom
@@ -398,6 +421,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-checks/26.0.
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-checks/26.0.1/lint-checks-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-checks/30.4.2/lint-checks-30.4.2.pom
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-gradle-api/26.2.1/lint-gradle-api-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-gradle-api/26.3.1/lint-gradle-api-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-gradle-api/26.5.4/lint-gradle-api-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-gradle-api/27.1.0/lint-gradle-api-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/lint/lint-gradle/30.4.2/lint-gradle-30.4.2.pom
@@ -416,6 +440,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/play-sdk-proto/30.4.2/
https://dl.google.com/dl/android/maven2/com/android/tools/repository/26.0.0/repository-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/repository/26.0.1/repository-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/repository/26.2.1/repository-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/repository/26.3.1/repository-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/repository/26.5.4/repository-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/repository/27.1.0/repository-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/repository/30.0.4/repository-30.0.4.pom
@@ -425,6 +450,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/repository/30.4.2/repo
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/26.0.0/sdklib-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/26.0.1/sdklib-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/26.2.1/sdklib-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/26.3.1/sdklib-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/26.5.4/sdklib-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/27.1.0/sdklib-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/30.0.4/sdklib-30.0.4.pom
@@ -434,6 +460,7 @@ https://dl.google.com/dl/android/maven2/com/android/tools/sdklib/30.4.2/sdklib-3
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/26.0.0/sdk-common-26.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/26.0.1/sdk-common-26.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/26.2.1/sdk-common-26.2.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/26.3.1/sdk-common-26.3.1.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/26.5.4/sdk-common-26.5.4.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/27.1.0/sdk-common-27.1.0.pom
https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/30.0.4/sdk-common-30.0.4.pom
@@ -688,6 +715,7 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/17.0/guava-pa
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/22.0/guava-parent-22.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/23.0/guava-parent-23.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/26.0-android/guava-parent-26.0-android.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/26.0-jre/guava-parent-26.0-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/27.0.1-jre/guava-parent-27.0.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/28.1-jre/guava-parent-28.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/29.0-jre/guava-parent-29.0-jre.pom
@@ -700,6 +728,7 @@ https://repo.maven.apache.org/maven2/com/google/guava/guava/17.0/guava-17.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/22.0/guava-22.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/23.0/guava-23.0.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/26.0-android/guava-26.0-android.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/26.0-jre/guava-26.0-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/27.0.1-jre/guava-27.0.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/28.1-jre/guava-28.1-jre.pom
https://repo.maven.apache.org/maven2/com/google/guava/guava/29.0-jre/guava-29.0-jre.pom
@@ -718,7 +747,7 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.7.1/prot
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.10.0/protobuf-bom-3.10.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.13.0/protobuf-bom-3.13.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/3.17.2/protobuf-bom-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/4.26.0-RC1/protobuf-bom-4.26.0-RC1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-bom/4.0.0-rc-2/protobuf-bom-4.0.0-rc-2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-javalite/3.17.2/protobuf-javalite-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java-util/3.4.0/protobuf-java-util-3.4.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java-util/3.10.0/protobuf-java-util-3.10.0.pom
@@ -730,7 +759,7 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.7.1/pro
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.10.0/protobuf-java-3.10.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.13.0/protobuf-java-3.13.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.17.2/protobuf-java-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/4.26.0-RC1/protobuf-java-4.26.0-RC1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/4.0.0-rc-2/protobuf-java-4.0.0-rc-2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-lite/3.0.1/protobuf-lite-3.0.1.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.0.0/protobuf-parent-3.0.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.4.0/protobuf-parent-3.4.0.pom
@@ -739,9 +768,9 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.7.1/p
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.10.0/protobuf-parent-3.10.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.13.0/protobuf-parent-3.13.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.17.2/protobuf-parent-3.17.2.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/4.26.0-RC1/protobuf-parent-4.26.0-RC1.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth-parent/1.4.0/truth-parent-1.4.0.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth/1.4.0/truth-1.4.0.pom
https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/4.0.0-rc-2/protobuf-parent-4.0.0-rc-2.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth-parent/1.2.0/truth-parent-1.2.0.pom
https://repo.maven.apache.org/maven2/com/google/truth/truth/1.2.0/truth-1.2.0.pom
https://repo.maven.apache.org/maven2/com/ibm/icu/icu4j/53.1/icu4j-53.1.pom
https://repo.maven.apache.org/maven2/com/intellij/annotations/12.0/annotations-12.0.pom
https://repo.maven.apache.org/maven2/com/parse/bolts/bolts-tasks/1.4.0/bolts-tasks-1.4.0.pom
@@ -884,13 +913,13 @@ https://repo.maven.apache.org/maven2/junit/junit/4.13.2/junit-4.13.2.pom
https://repo.maven.apache.org/maven2/me/zhanghai/android/materialprogressbar/library/1.4.2/library-1.4.2.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.11.13/byte-buddy-agent-1.11.13.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.11.19/byte-buddy-agent-1.11.19.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.14.11/byte-buddy-agent-1.14.11.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.14.10/byte-buddy-agent-1.14.10.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.11.13/byte-buddy-parent-1.11.13.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.11.19/byte-buddy-parent-1.11.19.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.14.11/byte-buddy-parent-1.14.11.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.14.10/byte-buddy-parent-1.14.10.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.11.13/byte-buddy-1.11.13.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.11.19/byte-buddy-1.11.19.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.14.11/byte-buddy-1.14.11.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.14.10/byte-buddy-1.14.10.pom
https://repo.maven.apache.org/maven2/net/java/dev/jna/jna-platform/5.6.0/jna-platform-5.6.0.pom
https://repo.maven.apache.org/maven2/net/java/dev/jna/jna/5.6.0/jna-5.6.0.pom
https://repo.maven.apache.org/maven2/net/java/jvnet-parent/1/jvnet-parent-1.pom
@@ -1138,6 +1167,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-project-model/1
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-project-model/1.9.0/kotlin-project-model-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.1.3-2/kotlin-reflect-1.1.3-2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.2.0/kotlin-reflect-1.2.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.3.20/kotlin-reflect-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.3.50/kotlin-reflect-1.3.50.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.3.72/kotlin-reflect-1.3.72.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.4.32/kotlin-reflect-1.4.32.pom
@@ -1146,7 +1176,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.10/
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.6.20/kotlin-reflect-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/1.7.22/kotlin-reflect-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/2.0.0-Beta3/kotlin-reflect-2.0.0-Beta3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-reflect/2.0.0-Beta2/kotlin-reflect-2.0.0-Beta2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.6.20/kotlin-scripting-common-1.6.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.7.22/kotlin-scripting-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-scripting-common/1.9.0/kotlin-scripting-common-1.9.0.pom
@@ -1164,6 +1194,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-script-runtime/1.9.0/kotlin-script-runtime-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.2.71/kotlin-stdlib-common-1.2.71.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.0/kotlin-stdlib-common-1.3.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.20/kotlin-stdlib-common-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.31/kotlin-stdlib-common-1.3.31.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.50/kotlin-stdlib-common-1.3.50.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.3.60/kotlin-stdlib-common-1.3.60.pom
@@ -1183,6 +1214,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.22/kotlin-stdlib-common-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-common/1.9.0/kotlin-stdlib-common-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.2.71/kotlin-stdlib-jdk7-1.2.71.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.20/kotlin-stdlib-jdk7-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.50/kotlin-stdlib-jdk7-1.3.50.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.3.72/kotlin-stdlib-jdk7-1.3.72.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.4.10/kotlin-stdlib-jdk7-1.4.10.pom
@@ -1195,6 +1227,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.22/kotlin-stdlib-jdk7-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.9.0/kotlin-stdlib-jdk7-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.2.71/kotlin-stdlib-jdk8-1.2.71.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.20/kotlin-stdlib-jdk8-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.50/kotlin-stdlib-jdk8-1.3.50.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.3.72/kotlin-stdlib-jdk8-1.3.72.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.4.10/kotlin-stdlib-jdk8-1.4.10.pom
@@ -1210,6 +1243,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.0/ko
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.20/kotlin-stdlib-1.2.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.2.71/kotlin-stdlib-1.2.71.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.0/kotlin-stdlib-1.3.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.20/kotlin-stdlib-1.3.20.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.31/kotlin-stdlib-1.3.31.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.50/kotlin-stdlib-1.3.50.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.60/kotlin-stdlib-1.3.60.pom
@@ -1229,7 +1263,7 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/k
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.22/kotlin-stdlib-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.0/kotlin-stdlib-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.9.21/kotlin-stdlib-1.9.21.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/2.0.0-Beta3/kotlin-stdlib-2.0.0-Beta3.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/2.0.0-Beta2/kotlin-stdlib-2.0.0-Beta2.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-core/1.7.22/kotlin-tooling-core-1.7.22.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-core/1.9.0/kotlin-tooling-core-1.9.0.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-tooling-metadata/1.6.20/kotlin-tooling-metadata-1.6.20.pom
@@ -1247,14 +1281,14 @@ https://repo.maven.apache.org/maven2/org/json/json/20231013/json-20231013.pom
https://repo.maven.apache.org/maven2/org/jsoup/jsoup/1.13.1/jsoup-1.13.1.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.9.2/junit-bom-5.9.2.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.9.3/junit-bom-5.9.3.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.10.2/junit-bom-5.10.2.pom
https://repo.maven.apache.org/maven2/org/junit/junit-bom/5.10.1/junit-bom-5.10.1.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.7.7/stax-ex-1.7.7.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8.1/stax-ex-1.8.1.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.8/stax-ex-1.8.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/2.1.0/stax-ex-2.1.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/3.12.4/mockito-core-3.12.4.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/4.0.0/mockito-core-4.0.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/5.10.0/mockito-core-5.10.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/5.8.0/mockito-core-5.8.0.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-inline/4.0.0/mockito-inline-4.0.0.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.2/objenesis-parent-3.2.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.3/objenesis-parent-3.3.pom
+1 -1
View File
@@ -19,4 +19,4 @@ trap show_gradle_log ERR
./gradlew projects --no-daemon --console plain 2>&1 \
| tee "${GRADLE_LOG_FILE}" \
| grep "Project ':" \
| sed -E "s;^.--- Project '\:([@_a-zA-Z0-9\-]+)'.*;\1;"
| sed -E "s;^.--- Project '\:([@_a-zA-Z0-9\-]+)';\1;"
+1 -1
View File
@@ -1,7 +1,6 @@
app
react-native-async-storage_async-storage
react-native-background-timer
react-native-biometrics
react-native-blob-util
react-native-blur
react-native-camera-kit
@@ -37,5 +36,6 @@ react-native-static-safe-area-insets
react-native-status
react-native-status-keycard
react-native-svg
react-native-touch-id
react-native-transparent-video
react-native-webview
+2 -2
View File
@@ -2,7 +2,7 @@
, jsbundle, status-go, androidPkgs, androidShell }:
rec {
build = callPackage ./build.nix {
release = callPackage ./release.nix {
inherit jsbundle status-go;
};
@@ -15,7 +15,7 @@ rec {
];
inputsFrom = [
(build {})
(release {})
androidShell
];
@@ -7,15 +7,15 @@
# Path to the file containing secret environment variables
secretsFile ? "",
# Build type (influences which .env file gets used for feature flags)
# TODO: pr or relase for default?
buildType ? lib.getEnvWithDefault "BUILD_TYPE" "release",
# Used for versionCode
versionCode ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_versionCode" 9999,
buildNumber ? lib.getEnvWithDefault "BUILD_NUMBER" 9999,
# Included in APK Manifest for easier identification.
commitHash ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_commitHash" "unknown",
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
hermesEnabled ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_hermesEnabled" "true",
buildUrl ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_buildUrl" null,
# TODO: or GIT_COMMIT from Jenkins?
commitHash ? lib.getEnvWithDefault "COMMIT_HASH" "unknown",
# Gradle options passed for Android builds
androidGradleOpts ? lib.getEnvWithDefault "ANDROID_GRADLE_OPTS" null,
statusGoSrcOverride ? lib.getEnvWithDefault "STATUS_GO_SRC_OVERRIDE" null,
# If APKs should be split based on architectures
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "false",
@@ -40,10 +40,8 @@ let
else if (elem buildType ["pr" "manual"]) then ".env.jenkins"
else ".env";
gradleBuildType =
if buildType == "pr" then "Pr"
else if buildType == "debug" then "Debug"
else "Release";
# There are only two types of Gradle build targets: pr and release
gradleBuildType = if buildType == "pr" then "Pr" else "Release";
apksPath = "./android/app/build/outputs/apk/${toLower gradleBuildType}";
@@ -81,12 +79,6 @@ in stdenv.mkDerivation rec {
STATUS_GO_SRC_OVERRIDE = statusGoSrcOverride;
ANDROID_ABI_SPLIT = androidAbiSplit;
ANDROID_ABI_INCLUDE = androidAbiInclude;
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
ORG_GRADLE_PROJECT_versionCode = versionCode;
ORG_GRADLE_PROJECT_commitHash = commitHash;
ORG_GRADLE_PROJECT_buildUrl = buildUrl;
ORG_GRADLE_PROJECT_hermesEnabled = hermesEnabled;
# Fix for ERR_OSSL_EVP_UNSUPPORTED error.
NODE_OPTIONS = "--openssl-legacy-provider";
@@ -121,6 +113,8 @@ in stdenv.mkDerivation rec {
# Symlink React Native entrypoint.
cp -Lr ${builtJsBundle} ./result
pwd
find -L result
# Copy android/ directory
mkdir -p ./android/build
@@ -147,6 +141,7 @@ in stdenv.mkDerivation rec {
"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${makeLibraryPath [ pkgs.zlib ]}";
gradleCommand = ''
${pkgs.gradle}/bin/gradle \
${toString androidGradleOpts} \
--console=plain \
--offline \
--no-daemon \
@@ -154,6 +149,8 @@ in stdenv.mkDerivation rec {
--no-watch-fs \
--no-build-cache \
-Dmaven.repo.local='${deps.gradle}' \
-PversionCode=${toString buildNumber} \
-PcommitHash=${commitHash} \
assemble${gradleBuildType}
'';
in
@@ -171,14 +168,12 @@ in stdenv.mkDerivation rec {
${adhocEnvVars} ${gradleCommand}
popd > /dev/null
'';
doCheck = buildType != "debug";
checkPhase = ''
doCheck = true;
checkPhase = ''
ls ${apksPath}/*.apk \
| xargs -n1 ${pkgs.unzip}/bin/unzip -qql \
| grep 'index.android.bundle'
'';
installPhase = ''
mkdir -p $out
cp ${apksPath}/*.apk $out/
+1 -1
View File
@@ -20,8 +20,8 @@ in {
buildInputs = with pkgs; [
xcodeWrapper watchman procps
flock # used in nix/scripts/node_modules.sh
ios-deploy # used in 'make run-ios-device'
xcbeautify # used in 'make run-ios'
libimobiledevice # used in `make run-ios-device`
];
# WARNING: Executes shellHook in reverse order.
+12 -1
View File
@@ -26,6 +26,18 @@ in {
react-native = callPackage ./deps/react-native { };
};
# Fix for missing libarclite_macosx.a in Xcode 14.3.
# https://github.com/ios-control/ios-deploy/issues/580
ios-deploy = super.darwin.ios-deploy.overrideAttrs (old: rec {
version = "1.12.2";
src = super.fetchFromGitHub {
owner = "ios-control";
repo = "ios-deploy";
rev = version;
sha256 = "sha256-TVGC+f+1ow3b93CK3PhIL70le5SZxxb2ug5OkIg8XCA";
};
});
# Clojure's linter receives frequent upgrades, and we want to take advantage
# of the latest available rules.
clj-kondo = super.clj-kondo.override rec {
@@ -85,5 +97,4 @@ in {
patchMavenSources = callPackage ./pkgs/patch-maven-srcs { };
goMavenResolver = callPackage ./pkgs/go-maven-resolver { };
xcbeautify = callPackage ./pkgs/xcbeautify { };
idb-companion = callPackage ./pkgs/idb-companion { };
}
-29
View File
@@ -1,29 +0,0 @@
{ stdenv, fetchurl, lib }:
stdenv.mkDerivation rec {
pname = "idb-companion";
version = "1.1.8";
src = fetchurl {
url = "https://github.com/facebook/idb/releases/download/v${version}/idb-companion.universal.tar.gz";
sha256 = "sha256-O3LMappbGiKhiCBahAkNOilDR6hGGA79dVzxo8hI4+c=";
};
buildInputs = [ ];
unpackPhase = ''
tar -xzf $src
'';
installPhase = ''
mkdir -p $out/bin
cp -r ./* $out/bin/
'';
meta = with lib; {
description = "A powerful command line tool for automating iOS simulators and devices";
homepage = "https://github.com/facebook/idb";
license = licenses.mit;
platforms = platforms.darwin;
};
}
+1 -1
View File
@@ -45,7 +45,7 @@ if [[ -z "${TARGET}" ]]; then
fi
# Hack fix for missing Android SDK for aarch64 on Darwin. See systemOverride in `nix/pkgs.nix`.
if [[ "${TARGET}" =~ ^(targets.status-go.mobile.android|targets.mobile.android.build)$ ]]; then
if [[ "${TARGET}" =~ ^(targets.status-go.mobile.android|targets.mobile.android.release)$ ]]; then
os=$(uname -s | tr '[:upper:]' '[:lower:]')
export NIXPKGS_SYSTEM_OVERRIDE="x86_64-${os}"
fi
+2 -2
View File
@@ -2,12 +2,12 @@
set -Ee
_NIX_GCROOTS="${_NIX_GCROOTS:-/nix/var/nix/gcroots/per-user/${USER}/status-mobile}"
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/nix/scripts/source.sh"
source "${GIT_ROOT}/scripts/colors.sh"
_NIX_GCROOTS="${_NIX_GCROOTS:-${GIT_ROOT}/.nix-gcroots}"
TARGET="${1}"
shift
if [[ -z "${TARGET}" ]]; then
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -Eeuo pipefail
# script to prompt user for terminating a process
pid="${1}"
read -p "Do you want to terminate this process? (y/n): " choice
if [[ "${choice}" == "y" ]]; then
sudo kill "${pid}"
echo "Process ${pid} terminated."
else
echo "Process not terminated. Please close it manually and retry."
exit 1
fi
+21 -11
View File
@@ -22,10 +22,12 @@ nix_purge_linux_multi_user_users() {
}
nix_purge_darwin_multi_user_service() {
sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist
sudo rm /Library/LaunchDaemons/org.nixos.nix-daemon.plist
sudo launchctl unload /Library/LaunchDaemons/org.nixos.darwin-store.plist
sudo rm /Library/LaunchDaemons/org.nixos.darwin-store.plist
cd /Library/LaunchDaemons
NIX_SERVICES=(org.nixos.darwin-store.plist org.nixos.nix-daemon.plist)
for NIX_SERVICE in "${NIX_SERVICES[@]}"; do
sudo launchctl unload "${NIX_SERVICE}" || true
sudo launchctl remove "${NIX_SERVICE}" || true
done
}
nix_purge_darwin_multi_user_users() {
@@ -46,10 +48,18 @@ nix_purge_darwin_multi_user_volumes() {
# Identify the process using the volume
local pid=$(lsof +D /nix | awk 'NR==2{print $2}')
if [[ -n "$pid" ]]; then
if [ -n "$pid" ]; then
echo "The volume /nix is in use by process ID $pid."
"${GIT_ROOT}/nix/scripts/kill_proc_prompt.sh" "${pid}" || return 1
# Ask the user whether to terminate the process
read -p "Do you want to terminate this process? (y/n): " choice
if [[ $choice == "y" ]]; then
sudo kill $pid
echo "Process $pid terminated."
else
echo "Process not terminated. Please close it manually and retry."
return 1
fi
else
echo "No process found using /nix. Manual intervention required."
return 1
@@ -61,9 +71,9 @@ nix_purge_darwin_multi_user_volumes() {
nix_purge_multi_user() {
if [[ $(uname -s) == "Darwin" ]]; then
nix_purge_darwin_multi_user_service
nix_purge_darwin_multi_user_users
nix_purge_darwin_multi_user_volumes
nix_purge_darwin_multi_user_service || true
nix_purge_darwin_multi_user_users || true
nix_purge_darwin_multi_user_volumes || true
else
nix_purge_linux_multi_user_service
nix_purge_linux_multi_user_users
@@ -107,7 +117,7 @@ if (return 0 2>/dev/null); then
return
fi
# Confirm user decision, unless --force is used.
# Confirm user decission, unless --force is used.
if [[ "${1}" != "--force" ]]; then
echo -e "${YLW}Are you sure you want to purge Nix?${RST}" >&2
read -p "[y/n]: " -n 1 -r
@@ -119,7 +129,7 @@ if [[ "${1}" != "--force" ]]; then
fi
NIX_INSTALL_TYPE=$(nix_install_type)
# Purging /nix on NixOS would be disastrous.
# Purging /nix on NixOS would be disasterous.
if [[ "${NIX_INSTALL_TYPE}" == "nixos" ]]; then
echo -e "${RED}You should not purge Nix files on NixOS!${RST}" >&2
exit
+5 -3
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
export NIX_VERSION="2.19.3"
export NIX_PACKAGE="nixVersions.nix_2_19"
# WARNING: Versions 2.14, 2.15, 2.16 have an issue creating gcroots:
# https://github.com/NixOS/nix/issues/8564
export NIX_VERSION="2.13.4"
export NIX_PACKAGE="nixVersions.nix_2_13"
export NIX_INSTALL_URL="https://nixos.org/releases/nix/nix-${NIX_VERSION}/install"
export NIX_INSTALL_SHA256="73d47b0ab783fddca1b2d44a03d52a74c97c28a1fc8ff5a29419079302ef9c3d"
export NIX_INSTALL_SHA256="a9908cc48f5886b4f22172bdd2f9657873276fd295e78c6ed97fb308c6d284d0"
export NIX_INSTALL_PATH="/tmp/nix-install-${NIX_VERSION}"
+2 -2
View File
@@ -23,9 +23,9 @@ in mkShell {
# build specific utilities
clojure maven watchman
# other nice to have stuff
yarn nodejs python310 maestro
yarn nodejs python310
] # and some special cases
++ lib.optionals stdenv.isDarwin ([ cocoapods clang tcl idb-companion ] ++ appleSDKFrameworks)
++ lib.optionals stdenv.isDarwin ([ cocoapods clang tcl ] ++ appleSDKFrameworks)
++ lib.optionals (!stdenv.isDarwin) [ gcc8 ]
);
+1 -1
View File
@@ -35,7 +35,6 @@
"react-dom": "18.0.0",
"react-native": "0.72.5",
"react-native-background-timer": "^2.1.1",
"react-native-biometrics": "^3.0.1",
"react-native-blob-util": "^0.13.18",
"react-native-camera-kit": "14.0.0-beta13",
"react-native-config": "^1.5.0",
@@ -66,6 +65,7 @@
"react-native-static-safe-area-insets": "^2.2.0",
"react-native-status-keycard": "git+https://github.com/status-im/react-native-status-keycard.git#refs/tags/v2.5.39",
"react-native-svg": "13.10.0",
"react-native-touch-id": "^4.4.1",
"react-native-transparent-video": "git+https://github.com/status-im/react-native-transparent-video.git#refs/tags/0.1.1",
"react-native-webview": "13.6.3",
"react-syntax-highlighter": "^15.5.0",
+43 -74
View File
@@ -1,7 +1,7 @@
{
"meta": {
"hostname": "node-01.do-ams3.sites.misc",
"timestamp": "2024-02-02T14:48:22.521541",
"timestamp": "2023-01-05T10:03:38.657813",
"warning": "DO NOT EDIT! Auto generated from Consul. Should only be used at build time."
},
"fleets": {
@@ -89,9 +89,9 @@
"node-01.ac-cn-hongkong-c.wakuv2.prod": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.prod.statusim.net/tcp/30303/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD"
},
"enr/p2p/waku": {
"node-01.do-ams3.wakuv2.prod": "enr:-P-4QJI8tS1WTdIQxq_yIrD05oIIW1Xg-tm_qfP0CHfJGnp9dfr6ttQJmHwTNxGEl4Le8Q7YHcmi-kXTtphxFysS11oBgmlkgnY0gmlwhLymh5GKbXVsdGlhZGRyc7hgAC02KG5vZGUtMDEuZG8tYW1zMy53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi5wcm9kLnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDbl1X_zJIw3EAJGtmHMVn4Z2xhpSoUaP5ElsHKCv7hlWDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.wakuv2.prod": "enr:-QERuEC0EGWTjg_gYdnuPypJ9LAbB3lml6M8GiRajGegL2iWEj1MJzUMV9X6jXw7mMAQQLozLCTLFT-zv-ELQLPwWdACAYJpZIJ2NIJpcIQieWRsim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdXYyLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhA_30kHgQqfXZRioa4J_u5asgXTJ5iw_8w3lEICH4TFu_g3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.wakuv2.prod": "enr:-QERuEDABor1lVmSa5ek8of5eBc8jZoxxdleJVLLdMl8UeZHNwhsVp64SFiCT4BRIIfcs7uxTPUCjmWxK_OA1s-FfIW7AYJpZIJ2NIJpcIQI0t7nim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdXYyLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhAo0C-VvfgHiXrxZi3umDiooXMGY9FvYj5_d1Q4EeS7eyg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
"node-01.do-ams3.wakuv2.prod": "enr:-M-4QLdAB-KyzT3QEsDoNa4LXT6RGH9BIylvTlDFLQhigWmxKEesulgc8AoKmVEUKj_4St6ThBKwyBc69tBfCe2hVTABgmlkgnY0gmlwhLymh5GKbXVsdGlhZGRyc7EALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi5wcm9kLnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDbl1X_zJIw3EAJGtmHMVn4Z2xhpSoUaP5ElsHKCv7hlWDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.wakuv2.prod": "enr:-Nm4QNgc2L6L-4nk6jgllNDE1QDcn6kv2922rTRYs1wM3My_OmSsTimkMCIMh8fat6enFdYfuJ23KjWdF5whBz3zXgUBgmlkgnY0gmlwhCJ5ZGyKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhA_30kHgQqfXZRioa4J_u5asgXTJ5iw_8w3lEICH4TFu_g3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.wakuv2.prod": "enr:-Nm4QOdTOKZJKTUUZ4O_W932CXIET-M9NamewDnL78P5u9DOGnZlK0JFZ4k0inkfe6iY-0JAaJVovZXc575VV3njeiABgmlkgnY0gmlwhAjS3ueKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy53YWt1djIucHJvZC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhAo0C-VvfgHiXrxZi3umDiooXMGY9FvYj5_d1Q4EeS7eyg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
},
"wss/p2p/waku": {
"node-01.do-ams3.wakuv2.prod": "/dns4/node-01.do-ams3.wakuv2.prod.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmL5okWopX7NqZWBUKVqW8iUxCEmd5GMHLVPwCgzYzQv3e",
@@ -106,9 +106,9 @@
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/30303/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm"
},
"enr/p2p/waku": {
"node-01.do-ams3.wakuv2.test": "enr:-P-4QPLMQ1zIYRAs4-F0mYmMxMihSySRtEIuGHJ_Qd_GL8XqUE78hpVUE97rgwlXnxPkzMJHkWyiNq7DT1fdZSy3QcgBgmlkgnY0gmlwhIbRi9KKbXVsdGlhZGRyc7hgAC02KG5vZGUtMDEuZG8tYW1zMy53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDnr03Tuo77930a7sYLikftxnuG3BbC3gCFhA4632ooDaDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.wakuv2.test": "enr:-QERuEDZcXS5tjppj4TIlOm-TLanjmqx3-uk2kGFvvAQR1NVrklUhiN1JCb5dWucEQ_oDADOb6nG_1mJ5goF5CHneZ-VAYJpZIJ2NIJpcIRomu-Aim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdXYyLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhA1giYsmWV9r2yJZYAiMGHJfjLlLeqAuTAokUGPN__pkxg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.wakuv2.test": "enr:-QERuEC2LyiXKURIKxNHa7Mj7frsM-lZiAGJ-2mopR3w8LMn2UhKmahZ9RHKV5ehBN1fXbRYqAeiXuOxD9t2igF4PIizAYJpZIJ2NIJpcIQv8tJJim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdXYyLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhAhAm-P4q6mWONKcGnbLPU8WXZJ4Qs3AxIbrycvc7PVKsg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
"node-01.do-ams3.wakuv2.test": "enr:-M-4QCtJKX2WDloRYDT4yjeMGKUCRRcMlsNiZP3cnPO0HZn6IdJ035RPCqsQ5NvTyjqHzKnTM6pc2LoKliV4CeV0WrgBgmlkgnY0gmlwhIbRi9KKbXVsdGlhZGRyc7EALzYobm9kZS0wMS5kby1hbXMzLndha3V2Mi50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DiXNlY3AyNTZrMaEDnr03Tuo77930a7sYLikftxnuG3BbC3gCFhA4632ooDaDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.wakuv2.test": "enr:-Nm4QLHYoJ5WYQoVzyqPR-pwIeQvi3ONWs-EPwk3uUiBiDseN9Dd7fYbCvkMdeXcuZ-8U9IYdGm38VxSDf_Oq3zZ0cEBgmlkgnY0gmlwhGia74CKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhA1giYsmWV9r2yJZYAiMGHJfjLlLeqAuTAokUGPN__pkxg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.wakuv2.test": "enr:-Nm4QC0_ClHzbsutYzgT3jJm7ZY1D4shylAdd6Ac-L4uwAUha1oHM0zwoEkTORVt94W5Cpa0IiyrTcXAYLgpRXpVNUsBgmlkgnY0gmlwhC_y0kmKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy53YWt1djIudGVzdC5zdGF0dXNpbS5uZXQGH0DeA4lzZWNwMjU2azGhAhAm-P4q6mWONKcGnbLPU8WXZJ4Qs3AxIbrycvc7PVKsg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
},
"wss/p2p/waku": {
"node-01.do-ams3.wakuv2.test": "/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ",
@@ -116,23 +116,6 @@
"node-01.ac-cn-hongkong-c.wakuv2.test": "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm"
}
},
"waku.test": {
"tcp/p2p/waku": {
"node-01.do-ams3.waku.test": "/dns4/node-01.do-ams3.waku.test.statusim.net/tcp/30303/p2p/16Uiu2HAkykgaECHswi3YKJ5dMLbq2kPVCo89fcyTd38UcQD6ej5W",
"node-01.gc-us-central1-a.waku.test": "/dns4/node-01.gc-us-central1-a.waku.test.statusim.net/tcp/30303/p2p/16Uiu2HAmDCp8XJ9z1ev18zuv8NHekAsjNyezAvmMfFEJkiharitG",
"node-01.ac-cn-hongkong-c.waku.test": "/dns4/node-01.ac-cn-hongkong-c.waku.test.statusim.net/tcp/30303/p2p/16Uiu2HAkzHaTP5JsUwfR9NR8Rj9HC24puS6ocaU8wze4QrXr9iXp"
},
"enr/p2p/waku": {
"node-01.do-ams3.waku.test": "enr:-QESuEC1p_s3xJzAC_XlOuuNrhVUETmfhbm1wxRGis0f7DlqGSw2FM-p2Ugl_r25UHQJ3f1rIRrpzxJXSMaJe4yk1XFSAYJpZIJ2NIJpcISygI2rim11bHRpYWRkcnO4XAArNiZub2RlLTAxLmRvLWFtczMud2FrdS50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAtNiZub2RlLTAxLmRvLWFtczMud2FrdS50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQJATXRSRSUyTw_QLB6H_U3oziVQgNRgrXpK7wp2AMyNxYN0Y3CCdl-DdWRwgiMohXdha3UyDw",
"node-01.gc-us-central1-a.waku.test": "enr:-QEkuECnZ3IbVAgkOzv-QLnKC4dRKAPRY80m1-R7G8jZ7yfT3ipEfBrhKN7ARcQgQ-vg-h40AQzyvAkPYlHPaFKk6u9uAYJpZIJ2NIJpcIQiEAFDim11bHRpYWRkcnO4bgA0Ni9ub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdS50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA2Ni9ub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEud2FrdS50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQMIJwesBVgUiBCi8yiXGx7RWylBQkYm1U9dvEy-neLG2YN0Y3CCdl-DdWRwgiMohXdha3UyDw",
"node-01.ac-cn-hongkong-c.waku.test": "enr:-QEkuEDzQyIAhs-CgBHIrJqtBv3EY1uP1Psrc-y8yJKsmxW7dh3DNcq2ergMUWSFVcJNlfcgBeVsFPkgd_QopRIiCV2pAYJpZIJ2NIJpcIQI2ttrim11bHRpYWRkcnO4bgA0Ni9ub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdS50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA2Ni9ub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMud2FrdS50ZXN0LnN0YXR1c2ltLm5ldAYfQN4DgnJzkwABCAAAAAEAAgADAAQABQAGAAeJc2VjcDI1NmsxoQJIN4qwz3v4r2Q8Bv8zZD0eqBcKw6bdLvdkV7-JLjqIj4N0Y3CCdl-DdWRwgiMohXdha3UyDw"
},
"wss/p2p/waku": {
"node-01.do-ams3.waku.test": "/dns4/node-01.do-ams3.waku.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAkykgaECHswi3YKJ5dMLbq2kPVCo89fcyTd38UcQD6ej5W",
"node-01.gc-us-central1-a.waku.test": "/dns4/node-01.gc-us-central1-a.waku.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAmDCp8XJ9z1ev18zuv8NHekAsjNyezAvmMfFEJkiharitG",
"node-01.ac-cn-hongkong-c.waku.test": "/dns4/node-01.ac-cn-hongkong-c.waku.test.statusim.net/tcp/8000/wss/p2p/16Uiu2HAkzHaTP5JsUwfR9NR8Rj9HC24puS6ocaU8wze4QrXr9iXp"
}
},
"status.prod": {
"tcp/p2p/waku": {
"node-01.do-ams3.status.prod": "/dns4/node-01.do-ams3.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAm6HZZr7aToTvEBPpiys4UxajCTU97zj5v7RNR2gbniy1D",
@@ -143,12 +126,12 @@
"node-02.ac-cn-hongkong-c.status.prod": "/dns4/node-02.ac-cn-hongkong-c.status.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmFy8BrJhCEmCYrUfBdSNkrPw6VHExtv4rRp1DSBnCPgx8"
},
"enr/p2p/waku": {
"node-01.do-ams3.status.prod": "enr:-P-4QGVNANzbhCI49du6Moyw98AjuMhKoOpE_Jges9JlCq-ICAVadktjfcNpuhQgT0g1cu86_S3nbM7eYkCsqDAQG7UBgmlkgnY0gmlwhI_G-a6KbXVsdGlhZGRyc7hgAC02KG5vZGUtMDEuZG8tYW1zMy5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMS5kby1hbXMzLnN0YXR1cy5wcm9kLnN0YXR1c2ltLm5ldAYBu94DiXNlY3AyNTZrMaECoVyonsTGEQvVioM562Q1fjzTb_vKD152PPIdsV7sM6SDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-02.do-ams3.status.prod": "enr:-P-4QMXNung2KVE9xLMzctM754vz4kbavb4Stai3RBPfN-5XMfuf2i0x8J5l8fkxkiZ3Vpd0IkN9Gg0PbbDh2BUyIF8BgmlkgnY0gmlwhKEj9HmKbXVsdGlhZGRyc7hgAC02KG5vZGUtMDIuZG8tYW1zMy5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMi5kby1hbXMzLnN0YXR1cy5wcm9kLnN0YXR1c2ltLm5ldAYBu94DiXNlY3AyNTZrMaED1AYI2Ox27DnSqf2qoih5M2fNpHFq-OzJ3thREEApdiiDdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.status.prod": "enr:-QERuEAFZ-rlajEo617uz0NDycgW4cPqqBumBvTOWywyFzIg4UOmbctTjYi6sfMArMgJEIDpphaXpLkCt5r12_gmtDQlAYJpZIJ2NIJpcIQjyjeZim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEuc3RhdHVzLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAhoqdPkAZNvNRuzEecDGwnt5UbF98qwM16PZG3JmW6kUg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-02.gc-us-central1-a.status.prod": "enr:-QERuEA_42Fh7Kq3drLxfIuRkqMfoJpfKpjwRcUXLv1PUQdUt1AAhIOUpun_kHKAMBmrREU9y2VoTKykl0dPBw02Fbh-AYJpZIJ2NIJpcIQihNXpim11bHRpYWRkcnO4cgA2NjFub2RlLTAyLmdjLXVzLWNlbnRyYWwxLWEuc3RhdHVzLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDIuZ2MtdXMtY2VudHJhbDEtYS5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAwtASPpiz5Gq3zuFuWF4MTviQVipi3HaQGytF-4wfbdvg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.status.prod": "enr:-QERuEAVmLHSKOsMq2Atya-0mhdvu718BAcynh40JAPBprvhpgcsTqkXV5kRrxaZbtzKa5-b0I4aO9U_O7-zHe24UDMAAYJpZIJ2NIJpcIQv8so7im11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMuc3RhdHVzLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAgwDLi50TMXqxWTCnR_rjQP3Eeznjs645ZNBoRh5B3jhg3RjcIJ2X4N1ZHCCIyiFd2FrdTIL",
"node-02.ac-cn-hongkong-c.status.prod": "enr:-QERuECscpffU15jE9GD77vwwKCeAWn8jBl7IXS9fMj8FcY6YzBPNNr17pXuOHPqhLbieZxM3zc0AMWDa5tWqpfbtzMKAYJpZIJ2NIJpcIQv84CGim11bHRpYWRkcnO4cgA2NjFub2RlLTAyLmFjLWNuLWhvbmdrb25nLWMuc3RhdHVzLnByb2Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDIuYWMtY24taG9uZ2tvbmctYy5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAzE4YIBrPK5oT_9MvYEeggmaDd205iU4Nn1MAhU5xqY5g3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
"node-01.do-ams3.status.prod": "enr:-M-4QLOTEs_ZFxCb09FgIezZd5KeTru5CWWyEtMWMN-yUABrerWxckU-pMIh3yO8VjxHpgZ4jU2WSXuK3goW4uYb6c4BgmlkgnY0gmlwhI_G-a6KbXVsdGlhZGRyc7EALzYobm9kZS0wMS5kby1hbXMzLnN0YXR1cy5wcm9kLnN0YXR1c2ltLm5ldAYBu94DiXNlY3AyNTZrMaECoVyonsTGEQvVioM562Q1fjzTb_vKD152PPIdsV7sM6SDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"node-02.do-ams3.status.prod": "enr:-M-4QIhQjPgSnoKXLsJAxbRzF8cZYYjOfdt1ysBkibcriCvXb9lWHDiRghIv11JQltK5KYFs2zrCKoQ-_ZoRXEs5FasBgmlkgnY0gmlwhKEj9HmKbXVsdGlhZGRyc7EALzYobm9kZS0wMi5kby1hbXMzLnN0YXR1cy5wcm9kLnN0YXR1c2ltLm5ldAYBu94DiXNlY3AyNTZrMaED1AYI2Ox27DnSqf2qoih5M2fNpHFq-OzJ3thREEApdiiDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"node-01.gc-us-central1-a.status.prod": "enr:-Nm4QPRAGqCjHCuu3DjbDVoLPqpE35Lfc3mjdCsmGTqdWmxjOF2NAbdYezEnukrz38TkTNXzEdslw_n_H5uUQ3hi-2EBgmlkgnY0gmlwhCPKN5mKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAhoqdPkAZNvNRuzEecDGwnt5UbF98qwM16PZG3JmW6kUg3RjcIJ2X4N1ZHCCIyiFd2FrdTID",
"node-02.gc-us-central1-a.status.prod": "enr:-Nm4QEdveBFdGPTVPCmYBikMKtGFlvLnzvXfYLOWDLPtTejBLcV_9e5Ry7dqx5K027rn5zedG-HnNiHP_GBcdCpGnq0BgmlkgnY0gmlwhCKE1emKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDIuZ2MtdXMtY2VudHJhbDEtYS5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAwtASPpiz5Gq3zuFuWF4MTviQVipi3HaQGytF-4wfbdvg3RjcIJ2X4N1ZHCCIyiFd2FrdTID",
"node-01.ac-cn-hongkong-c.status.prod": "enr:-Nm4QOxEmmi5LQo3EwmHCagXOzVXzsLDGDwPDTL6ECmUCoXPYV0ldWvzMVqPOEPzXMCtECdk7xpleiNN85oKQxFiGnYBgmlkgnY0gmlwhC_yyjuKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAgwDLi50TMXqxWTCnR_rjQP3Eeznjs645ZNBoRh5B3jhg3RjcIJ2X4N1ZHCCIyiFd2FrdTID",
"node-02.ac-cn-hongkong-c.status.prod": "enr:-Nm4QOqKQ4bi7sYE1ZXAqnryEGeJOnQxIzo9UK5xHY_GeP4healoFVspoG2FaUCSyIg8pa4X2P99BbC15iSh98NIgPYBgmlkgnY0gmlwhC_zgIaKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDIuYWMtY24taG9uZ2tvbmctYy5zdGF0dXMucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAzE4YIBrPK5oT_9MvYEeggmaDd205iU4Nn1MAhU5xqY5g3RjcIJ2X4N1ZHCCIyiFd2FrdTID"
},
"wss/p2p/waku": {
"node-01.do-ams3.status.prod": "/dns4/node-01.do-ams3.status.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAm6HZZr7aToTvEBPpiys4UxajCTU97zj5v7RNR2gbniy1D",
@@ -166,9 +149,9 @@
"node-01.ac-cn-hongkong-c.status.test": "/dns4/node-01.ac-cn-hongkong-c.status.test.statusim.net/tcp/30303/p2p/16Uiu2HAm2BjXxCp1sYFJQKpLLbPbwd5juxbsYofu3TsS3auvT9Yi"
},
"enr/p2p/waku": {
"node-01.do-ams3.status.test": "enr:-P-4QOg_CbInUakb3TEQBeCICyC-QDPeWK-CGtV9-nWp1W5DOKE2va63re3nPw-_hgvJfJkvshTaV0VmditigxKxT_kBgmlkgnY0gmlwhEDhUe2KbXVsdGlhZGRyc7hgAC02KG5vZGUtMDEuZG8tYW1zMy5zdGF0dXMudGVzdC5zdGF0dXNpbS5uZXQGdl8ALzYobm9kZS0wMS5kby1hbXMzLnN0YXR1cy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DiXNlY3AyNTZrMaECBNx5Erw5Jdsw-uI9pBjB_V2R6brvuVWE-MJwYCQKVv6DdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.status.test": "enr:-QERuED3i2Oj7jWVR6QyPE_R0WO4Kec4CuUf8Pf6YrEXB6mvFwW_Y2wyHExqajqKR-ke-129TwAwovz2QjErTUga6rM8AYJpZIJ2NIJpcIQievx2im11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmdjLXVzLWNlbnRyYWwxLWEuc3RhdHVzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS5zdGF0dXMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAzToWxPoQnnubNH_CIu7YHPV0RHadQVIKlpfMJxxC2eFg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.status.test": "enr:-QERuEDoxPEax-hctqp6vg2cmvd2UNPjgdf6iWmgvShX2-hL_Wj2JHpjVua9buZTYLsLD-Or5e71hwlgZlFaceEfopnzAYJpZIJ2NIJpcIQv8ukkim11bHRpYWRkcnO4cgA2NjFub2RlLTAxLmFjLWNuLWhvbmdrb25nLWMuc3RhdHVzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy5zdGF0dXMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAmRvsjqPlfX7OOJ4x4F3GAOpBa4y4NQSoNHjX2XIo1lvg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
"node-01.do-ams3.status.test": "enr:-M-4QI1qCnM3DMuZR2Y86FygFXPtm9fIRc4rFdUaDj0NbEA3Jl4In8mXAjUWgoei7W9Grc7oqtgibmIo-HIHHg7wrhMBgmlkgnY0gmlwhEDhUe2KbXVsdGlhZGRyc7EALzYobm9kZS0wMS5kby1hbXMzLnN0YXR1cy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DiXNlY3AyNTZrMaECBNx5Erw5Jdsw-uI9pBjB_V2R6brvuVWE-MJwYCQKVv6DdGNwgnZfg3VkcIIjKIV3YWt1Mg8",
"node-01.gc-us-central1-a.status.test": "enr:-Nm4QFxGf89g3MGnCLYBxBgpXejyB44mvXvJSpNzjlRwNXO6BIn7hl66OJpESPWdH7ipHNemmz0e04wtJHe_wVV5woABgmlkgnY0gmlwhCJ6_HaKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS5zdGF0dXMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAzToWxPoQnnubNH_CIu7YHPV0RHadQVIKlpfMJxxC2eFg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.ac-cn-hongkong-c.status.test": "enr:-Nm4QCF2zwCuAZzxTtjjjbo5hn6vx0ICcEJBGRBMdDCfpoX5BGiApbfhEljEjpI4ePhYra_k0o5uI8eTTGYHkr6208gBgmlkgnY0gmlwhC_y6SSKbXVsdGlhZGRyc7g6ADg2MW5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy5zdGF0dXMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAmRvsjqPlfX7OOJ4x4F3GAOpBa4y4NQSoNHjX2XIo1lvg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP"
},
"wss/p2p/waku": {
"node-01.do-ams3.status.test": "/dns4/node-01.do-ams3.status.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkukebeXjTQ9QDBeNDWuGfbaSg79wkkhK4vPocLgR6QFDf",
@@ -176,52 +159,38 @@
"node-01.ac-cn-hongkong-c.status.test": "/dns4/node-01.ac-cn-hongkong-c.status.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm2BjXxCp1sYFJQKpLLbPbwd5juxbsYofu3TsS3auvT9Yi"
}
},
"shards.test": {
"tcp/p2p/waku/boot": {
"boot-01.do-ams3.shards.test": "/dns4/boot-01.do-ams3.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAmAR24Mbb6VuzoyUiGx42UenDkshENVDj4qnmmbabLvo31",
"boot-01.gc-us-central1-a.shards.test": "/dns4/boot-01.gc-us-central1-a.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAm8mUZ18tBWPXDQsaF7PbCKYA35z7WB2xNZH2EVq1qS8LJ",
"boot-01.ac-cn-hongkong-c.shards.test": "/dns4/boot-01.ac-cn-hongkong-c.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAmGwcE8v7gmJNEWFtZtojYpPMTHy2jBLL6xRk33qgDxFWX"
"go-waku.prod": {
"tcp/p2p/waku": {
"node-01.do-ams3.go-waku.prod": "/dns4/node-01.do-ams3.go-waku.prod.statusim.net/tcp/30303/p2p/16Uiu2HAkyScd7DiwgMwzfw8CFFhznH3wRzciqEUfjDzn7vyimR8c",
"node-01.gc-us-central1-a.go-waku.prod": "/dns4/node-01.gc-us-central1-a.go-waku.prod.statusim.net/tcp/30303/p2p/16Uiu2HAmKTYnoPKebjWy63e1zPKiYRCQvm25W5mNSnCFE8EmzLga",
"node-01.ac-cn-hongkong-c.go-waku.prod": "/dns4/node-01.ac-cn-hongkong-c.go-waku.prod.statusim.net/tcp/30303/p2p/16Uiu2HAkwUKwy66nhcSFeW7y5qijNqXC4ZD3TaMMqnoEbh3wK2xU"
},
"enr/p2p/waku/boot": {
"boot-01.do-ams3.shards.test": "enr:-QEOuEAuAK49evunDoidpHqcmeVqZz73wt4jwHnHJlmCVBFj6EdIbZ9uH5BnCYKOEPJTns2QJKUR2XLtWyzIspPAfJF9AYJpZIJ2NIJpcISnYxMvim11bHRpYWRkcnO4YAAtNihib290LTAxLmRvLWFtczMuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfAC82KGJvb3QtMDEuZG8tYW1zMy5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc4sAEAQAIABAAIABAIlzZWNwMjU2azGhAt60bRUEoHNuLlnsM12sU2PIQwBwfLIJ8a_ZPEY2-Rnkg3RjcIJ2X4N1ZHCCIyiFd2FrdTIN",
"boot-01.gc-us-central1-a.shards.test": "enr:-QEguEC3wjzOk7U5rIqiX32CCD-0_J1cYYGK_YwKSah5di2NTxJUaKQ9B7NMiEQ_-YGm-Eus4SzHtxN_fXEuVaNHql9aAYJpZIJ2NIJpcIQihw1Xim11bHRpYWRkcnO4cgA2NjFib290LTAxLmdjLXVzLWNlbnRyYWwxLWEuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MWJvb3QtMDEuZ2MtdXMtY2VudHJhbDEtYS5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc4sAEAQAIABAAIABAIlzZWNwMjU2azGhAsY6oA0NFskUjopWFN9gwOZP1zZQ4rN5tVXV5CvcTOpDg3RjcIJ2X4N1ZHCCIyiFd2FrdTIN",
"boot-01.ac-cn-hongkong-c.shards.test": "enr:-QEguEBb4rlxsdYCIZ8NcAlcjnb2zp4C9JbDsz-01Ix2sKNdWzI79KRFnhlakX-4F8gRYcviDvQL5eEZDOxHTupUW7VXAYJpZIJ2NIJpcIQI2hdMim11bHRpYWRkcnO4cgA2NjFib290LTAxLmFjLWNuLWhvbmdrb25nLWMuc2hhcmRzLnRlc3Quc3RhdHVzaW0ubmV0BnZfADg2MWJvb3QtMDEuYWMtY24taG9uZ2tvbmctYy5zaGFyZHMudGVzdC5zdGF0dXNpbS5uZXQGAbveA4Jyc4sAEAQAIABAAIABAIlzZWNwMjU2azGhAz-wm0ZPmCicDhRTOGfZ3stBj3O1jyWgsBpKTUcpWu5gg3RjcIJ2X4N1ZHCCIyiFd2FrdTIN"
"enr/p2p/waku": {
"node-01.do-ams3.go-waku.prod": "enr:-NC4QGRYrus1rbuI183CZmxjb1wL4_wdNMcJDKaxaTaRs-RUTXP6KQ0VxL8zGaPNNxLT45ItXS8dmQvcyBWUlTwqXfYBgmlkgnY0gmlwhIbRh8OKbXVsdGlhZGRyc7IAMDYpbm9kZS0wMS5kby1hbXMzLmdvLXdha3UucHJvZC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAjusiHwKZa-rftTSq-KnDnirfCBW-q5ClJf4YEw9N8_Jg3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.gc-us-central1-a.go-waku.prod": "enr:-Nq4QJuKC3qwV704_zzThJiIaV2Jb1YLLjRzSalpgrgAUV7vU0_fMYTQUshz6hcqds0lR3lHFzhCDEdrT6TmP1rBF1IBgmlkgnY0gmlwhCJ6XvOKbXVsdGlhZGRyc7g7ADk2Mm5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS5nby13YWt1LnByb2Quc3RhdHVzaW0ubmV0BgG73gOJc2VjcDI1NmsxoQNlE4TEM5FmqnyDaMQ4viBkHpx2FZb9SPVl_XsVCrn5q4N0Y3CCdl-DdWRwgiMohXdha3UyDw",
"node-01.ac-cn-hongkong-c.go-waku.prod": "enr:-Nq4QFd-E6Ej3RuGF_-zZWYLfIb4vpfhKNi6RiLWrt30O90oNuJnbhUo8rMvuX_sO95X6QoyHa9RaUYx9N7cywA4WWkBgmlkgnY0gmlwhAjSBH6KbXVsdGlhZGRyc7g7ADk2Mm5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy5nby13YWt1LnByb2Quc3RhdHVzaW0ubmV0BgG73gOJc2VjcDI1NmsxoQIeZXd0MFV5YU9q0pWt05cUEc0RnptCtJarNlnxV7OpJYN0Y3CCdl-DdWRwgiMohXdha3UyDw"
},
"wss/p2p/waku/boot": {
"boot-01.do-ams3.shards.test": "/dns4/boot-01.do-ams3.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmAR24Mbb6VuzoyUiGx42UenDkshENVDj4qnmmbabLvo31",
"boot-01.gc-us-central1-a.shards.test": "/dns4/boot-01.gc-us-central1-a.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm8mUZ18tBWPXDQsaF7PbCKYA35z7WB2xNZH2EVq1qS8LJ",
"boot-01.ac-cn-hongkong-c.shards.test": "/dns4/boot-01.ac-cn-hongkong-c.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmGwcE8v7gmJNEWFtZtojYpPMTHy2jBLL6xRk33qgDxFWX"
},
"tcp/p2p/waku/store": {
"store-01.do-ams3.shards.test": "/dns4/store-01.do-ams3.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAmAUdrQ3uwzuE4Gy4D56hX6uLKEeerJAnhKEHZ3DxF1EfT",
"store-02.do-ams3.shards.test": "/dns4/store-02.do-ams3.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAm9aDJPkhGxc2SFcEACTFdZ91Q5TJjp76qZEhq9iF59x7R",
"store-01.gc-us-central1-a.shards.test": "/dns4/store-01.gc-us-central1-a.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAmMELCo218hncCtTvC2Dwbej3rbyHQcR8erXNnKGei7WPZ",
"store-02.gc-us-central1-a.shards.test": "/dns4/store-02.gc-us-central1-a.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAmJnVR7ZzFaYvciPVafUXuYGLHPzSUigqAmeNw9nJUVGeM",
"store-01.ac-cn-hongkong-c.shards.test": "/dns4/store-01.ac-cn-hongkong-c.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAm2M7xs7cLPc3jamawkEqbr7cUJX11uvY7LxQ6WFUdUKUT",
"store-02.ac-cn-hongkong-c.shards.test": "/dns4/store-02.ac-cn-hongkong-c.shards.test.statusim.net/tcp/30303/p2p/16Uiu2HAm9CQhsuwPR54q27kNj9iaQVfyRzTGKrhFmr94oD8ujU6P"
},
"enr/p2p/waku/store": {
"store-01.do-ams3.shards.test": "enr:-QEQuEDom7vBcLEP3ZCvRGPyBVTUJUO5YIyXvxcibag_iq6s5Ux6Zd1_nnqEXqynppYMNOTaTzSetRhmV9IH83j72umYAYJpZIJ2NIJpcISf3_Jeim11bHRpYWRkcnO4YgAuNilzdG9yZS0wMS5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAwNilzdG9yZS0wMS5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEC36GkB96EmFufcsRAX3gGW5bZlJwuAc2JB6nq9lUDE8qDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-02.do-ams3.shards.test": "enr:-QEQuEAmPituRLmZuwA6z0AT_Vl-KWbb7kpyX7qcWwbjygv_Oxrdu_0kmpShNtauWxhRmaOMOYddv9IwiIS8HujxHvpbAYJpZIJ2NIJpcISf3_Kaim11bHRpYWRkcnO4YgAuNilzdG9yZS0wMi5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwAwNilzdG9yZS0wMi5kby1hbXMzLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEC0jOth5qhqWd_NmDOAsiPjAiJZMTD-2WzsKsET75PcLCDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-01.gc-us-central1-a.shards.test": "enr:-QEiuEBW0x-NQAwfFIgwrwtMRbPpWYRbWzsQ6nMDQK5K8vT8uAph5mlAw-TaeIxw9K2Vc0QuEYzf8-MnOESVyQ-C6ywcAYJpZIJ2NIJpcIQiqsAnim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMS5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMS5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEDf2gcTbDga3Hgy8gu-bwRUbs7_7Vn2hxudCXPQ0M7cJCDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-02.gc-us-central1-a.shards.test": "enr:-QEiuEDjbS1EbRmNA7Gl1F3z_NsTHloyfZp4h0tm5cQmTvo5SlFGIBPPpmB6oycGnVGCHFPmqV_XbJJRO5pObWa5dOHgAYJpZIJ2NIJpcIQiqpoCim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMi5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMi5nYy11cy1jZW50cmFsMS1hLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaEDWxINW5DCQgYg-U43t2f9dUfpHfZrp2RdL-IomGWtY4KDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-01.ac-cn-hongkong-c.shards.test": "enr:-QEiuEDkMIJT5pVMmtzHD5RATLyU0kAG0tKcC3AE3BQe0O6S9R6OsA7PEVaaUg52fA4_I2pwjoW2GroE6uR9a-7Vdfy-AYJpZIJ2NIJpcIQI2kpJim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMS5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMS5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaECZtdI3Wq88fYXHYUShn7AMktB3OaVo98ock70-RSMChiDdGNwgnZfg3VkcIIjKIV3YWt1MgM",
"store-02.ac-cn-hongkong-c.shards.test": "enr:-QEiuEBzOdkswwOBobEe-nUvdtALMP8sjV9b_v9rQS4E0QOv2TVdrXRKKrBzOgk8TIXFtdry3RrowN5pTH7vBWl8TPKUAYJpZIJ2NIJpcIQI2nnoim11bHRpYWRkcnO4dAA3NjJzdG9yZS0wMi5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAZ2XwA5NjJzdG9yZS0wMi5hYy1jbi1ob25na29uZy1jLnNoYXJkcy50ZXN0LnN0YXR1c2ltLm5ldAYBu94DgnJziwAQBAAgAEAAgAEAiXNlY3AyNTZrMaECzJ3LruqSdw0Ec2FKpAdT22kcWVyBiYvMGim2wRWzkjSDdGNwgnZfg3VkcIIjKIV3YWt1MgM"
},
"wss/p2p/waku/store": {
"store-01.do-ams3.shards.test": "/dns4/store-01.do-ams3.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmAUdrQ3uwzuE4Gy4D56hX6uLKEeerJAnhKEHZ3DxF1EfT",
"store-02.do-ams3.shards.test": "/dns4/store-02.do-ams3.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm9aDJPkhGxc2SFcEACTFdZ91Q5TJjp76qZEhq9iF59x7R",
"store-01.gc-us-central1-a.shards.test": "/dns4/store-01.gc-us-central1-a.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmMELCo218hncCtTvC2Dwbej3rbyHQcR8erXNnKGei7WPZ",
"store-02.gc-us-central1-a.shards.test": "/dns4/store-02.gc-us-central1-a.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmJnVR7ZzFaYvciPVafUXuYGLHPzSUigqAmeNw9nJUVGeM",
"store-01.ac-cn-hongkong-c.shards.test": "/dns4/store-01.ac-cn-hongkong-c.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm2M7xs7cLPc3jamawkEqbr7cUJX11uvY7LxQ6WFUdUKUT",
"store-02.ac-cn-hongkong-c.shards.test": "/dns4/store-02.ac-cn-hongkong-c.shards.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm9CQhsuwPR54q27kNj9iaQVfyRzTGKrhFmr94oD8ujU6P"
"wss/p2p/waku": {
"node-01.do-ams3.go-waku.prod": "/dns4/node-01.do-ams3.go-waku.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAkyScd7DiwgMwzfw8CFFhznH3wRzciqEUfjDzn7vyimR8c",
"node-01.gc-us-central1-a.go-waku.prod": "/dns4/node-01.gc-us-central1-a.go-waku.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAmKTYnoPKebjWy63e1zPKiYRCQvm25W5mNSnCFE8EmzLga",
"node-01.ac-cn-hongkong-c.go-waku.prod": "/dns4/node-01.ac-cn-hongkong-c.go-waku.prod.statusim.net/tcp/443/wss/p2p/16Uiu2HAkwUKwy66nhcSFeW7y5qijNqXC4ZD3TaMMqnoEbh3wK2xU"
}
},
"notify.prod": {
"go-waku.test": {
"tcp/p2p/waku": {
"node-01.do-ams3.notify.prod": "enode://401ba5eda402678dc78a0a40fd0795f4ea8b1e34972c4d15cf33ac01292341c89f0cbc637fa9f7a3ffe0b9dfe90e9cdae7a14925500ab01b6a91c67bae42a97a@178.128.139.80:1443",
"node-01.gc-us-central1-a.notify.prod": "enode://181141b1d111908aaf05f4788e6778ec07073a1d4e1ce43c73815c40ee4e7345a1cbf5a90a45f601bf3763f12be63b01624ba1f36eeb9572455e7034b8f9f2c4@34.71.141.140:1443",
"node-01.ac-cn-hongkong-c.notify.prod": "enode://5ffc34d5ffda180d94cd3974d9ed2bb082ede68f342babdbe801ceffb7da902087d43f9aa961c7b85029358874c08ef04ecad9f1d95a1f0e448cbdd5d04350c7@47.242.88.117:1443"
"node-01.do-ams3.go-waku.test": "/dns4/node-01.do-ams3.go-waku.test.statusim.net/tcp/30303/p2p/16Uiu2HAm9vnvCQgCDrynDK1h7GJoEZVGvnuzq84RyDQ3DEdXmcX7",
"node-01.gc-us-central1-a.go-waku.test": "/dns4/node-01.gc-us-central1-a.go-waku.test.statusim.net/tcp/30303/p2p/16Uiu2HAmPz63Xc6AuVkDeujz7YeZta18rcdau3Y1BzaxKAfDrBqz",
"node-01.ac-cn-hongkong-c.go-waku.test": "/dns4/node-01.ac-cn-hongkong-c.go-waku.test.statusim.net/tcp/30303/p2p/16Uiu2HAmBDbMWFiG9ki8sDw6fYtraSxo4oHU9HbuN43S2HVyq1FD"
},
"enr/p2p/waku": {
"node-01.do-ams3.go-waku.test": "enr:-NC4QKYOHGKa69sKLLKbRlcR890mmPRIboV0MUSMQtvjiwd7SISpBYqVibOpmTuS0kRlU6KmBQs_MXA9LPOBgMbRB7UBgmlkgnY0gmlwhIbRhj-KbXVsdGlhZGRyc7IAMDYpbm9kZS0wMS5kby1hbXMzLmdvLXdha3UudGVzdC5zdGF0dXNpbS5uZXQGAbveA4lzZWNwMjU2azGhAtd5TiUZInW1nFF7nZtkXrw0iuqOLyV31_f7EhuM_Fs-g3RjcIJ2X4N1ZHCCIyiFd2FrdTIP",
"node-01.gc-us-central1-a.go-waku.test": "enr:-Nq4QEb3btlua6_4EdC1SAF0wTl0JqI8Du34Bm7raZoYOAbHPmRzVt4rq-0ItCM3L4MkOpCFn_X26aTq-Q2YEK8DuGEBgmlkgnY0gmlwhCPft1uKbXVsdGlhZGRyc7g7ADk2Mm5vZGUtMDEuZ2MtdXMtY2VudHJhbDEtYS5nby13YWt1LnRlc3Quc3RhdHVzaW0ubmV0BgG73gOJc2VjcDI1NmsxoQOoVQePH5eRqlcCf-0XwZsoJPeZp1Mq59un_jYM9hUc6YN0Y3CCdl-DdWRwgiMohXdha3UyDw",
"node-01.ac-cn-hongkong-c.go-waku.test": "enr:-Nq4QCWN6qBpeK_1GiqE_F45k3MmBDxaOJ7X9fAOKO0qu_6xCPAkjOVz6Th_vn8n-CLdEizO5oJ6YOivuAiRHDdJ3q4BgmlkgnY0gmlwhAjaAm6KbXVsdGlhZGRyc7g7ADk2Mm5vZGUtMDEuYWMtY24taG9uZ2tvbmctYy5nby13YWt1LnRlc3Quc3RhdHVzaW0ubmV0BgG73gOJc2VjcDI1NmsxoQLqosp15CMf5c4k-z9MGM7_aiR0DGdmSrpjQ_xWnmsTOIN0Y3CCdl-DdWRwgiMohXdha3UyDw"
},
"wss/p2p/waku": {
"node-01.do-ams3.go-waku.test": "/dns4/node-01.do-ams3.go-waku.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAm9vnvCQgCDrynDK1h7GJoEZVGvnuzq84RyDQ3DEdXmcX7",
"node-01.gc-us-central1-a.go-waku.test": "/dns4/node-01.gc-us-central1-a.go-waku.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPz63Xc6AuVkDeujz7YeZta18rcdau3Y1BzaxKAfDrBqz",
"node-01.ac-cn-hongkong-c.go-waku.test": "/dns4/node-01.ac-cn-hongkong-c.go-waku.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmBDbMWFiG9ki8sDw6fYtraSxo4oHU9HbuN43S2HVyq1FD"
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

+3 -8
View File
@@ -21,6 +21,8 @@ function append_env_export() {
VAR_VALUE=$(must_get_env "${VAR_NAME}")
echo "export ${VAR_NAME}=\"${VAR_VALUE}\";" >> "${SECRETS_FILE_PATH}"
}
export COMMIT_HASH="$(git rev-parse --verify HEAD)"
nixOpts=()
# We create if now so the trap knows its location
@@ -31,17 +33,10 @@ trap "rm -vf ${SECRETS_FILE_PATH}" EXIT ERR INT QUIT
# Names of variables containing secrets to save in env file.
SECRETS_ENV_VARS=(
'ALCHEMY_ETHEREUM_MAINNET_TOKEN'
'ALCHEMY_ETHEREUM_GOERLI_TOKEN'
'ALCHEMY_ETHEREUM_SEPOLIA_TOKEN'
'ALCHEMY_ARBITRUM_GOERLI_TOKEN'
'ALCHEMY_ARBITRUM_MAINNET_TOKEN'
'ALCHEMY_ARBITRUM_SEPOLIA_TOKEN'
'ALCHEMY_OPTIMISM_GOERLI_TOKEN'
'ALCHEMY_OPTIMISM_MAINNET_TOKEN'
'ALCHEMY_OPTIMISM_SEPOLIA_TOKEN'
'RARIBLE_MAINNET_API_KEY'
'RARIBLE_TESTNET_API_KEY'
'INFURA_TOKEN'
'INFURA_TOKEN_SECRET'
'OPENSEA_API_KEY'
@@ -71,4 +66,4 @@ else
fi
"${GIT_ROOT}/nix/scripts/build.sh" targets.mobile.android.build "${nixOpts[@]}"
"${GIT_ROOT}/nix/scripts/build.sh" targets.mobile.android.release "${nixOpts[@]}"
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
ADB_INSTALL_LOG_FILE="${GIT_ROOT}/logs/adb_install.log"
ADB_SHELL_MONKEY_LOG_FILE="${GIT_ROOT}/logs/adb_shell_monkey.log"
# Generate android debug build.
export ANDROID_ABI_INCLUDE=$("${GIT_ROOT}/scripts/adb_devices_abis.sh")
export BUILD_ENV=debug
export BUILD_TYPE=debug
"${GIT_ROOT}/scripts/build-android.sh"
# Install the APK on running emulator or android device.
installAndLaunchApp() {
adb install -r ./result/app-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
"${GIT_ROOT}/scripts/wait-for-metro-port.sh" 2>&1
# connected android devices need this port to be exposed for metro
adb reverse "tcp:${RCT_METRO_PORT}" "tcp:${RCT_METRO_PORT}"
adb shell monkey -p im.status.ethereum.debug 1 > "${ADB_SHELL_MONKEY_LOG_FILE}" 2>&1
}
showAdbLogs() {
cat "${ADB_INSTALL_LOG_FILE}" >&2;
cat "${ADB_SHELL_MONKEY_LOG_FILE}" >&2;
}
trap showAdbLogs EXIT ERR INT QUIT
installAndLaunchApp &
exec "${GIT_ROOT}/scripts/run-metro.sh" 2>&1
-55
View File
@@ -1,55 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
set -m # needed to access jobs
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
XCRUN_DEVICE_INSTALL_LOG_DIR="${GIT_ROOT}/logs/xcrun_device_install.log"
XCRUN_DEVICE_PROCESS_LAUNCH_LOG_DIR="${GIT_ROOT}/logs/xcrun_device_process_launch.log"
XCRUN_DEVICE_PROCESS_RESUME_LOG_DIR="${GIT_ROOT}/logs/xcrun_device_process_resume.log"
# Install on the connected device
installAndLaunchApp() {
xcrun devicectl device install app --device "${DEVICE_UUID}" "${APP_PATH}" --json-output "${XCRUN_DEVICE_INSTALL_LOG_DIR}" 2>&1
# Extract installationURL
INSTALLATION_URL=$(jq -r '.result.installedApplications[0].installationURL' "${XCRUN_DEVICE_INSTALL_LOG_DIR}")
# launch the app and put it in background
xcrun devicectl device process launch --no-activate --verbose --device "${DEVICE_UUID}" "${INSTALLATION_URL}" --json-output "${XCRUN_DEVICE_PROCESS_LAUNCH_LOG_DIR}"
# Extract background PID of status app
STATUS_PID=$(jq -r '.result.process.processIdentifier' "${XCRUN_DEVICE_PROCESS_LAUNCH_LOG_DIR}")
"${GIT_ROOT}/scripts/wait-for-metro-port.sh" 2>&1
# now that metro is ready, resume the app from background
xcrun devicectl device process resume --device "${DEVICE_UUID}" --pid "${STATUS_PID}" > "${XCRUN_DEVICE_PROCESS_RESUME_LOG_DIR}" 2>&1
}
showXcrunLogs() {
cat "${XCRUN_DEVICE_INSTALL_LOG_DIR}" >&2;
cat "${XCRUN_DEVICE_PROCESS_LAUNCH_LOG_DIR}" >&2;
cat "${XCRUN_DEVICE_PROCESS_RESUME_LOG_DIR}" >&2;
}
# find the first connected iPhone's UUID
DEVICE_UUID=$(idevice_id -l)
# Check if any device is connected
if [ -z "${DEVICE_UUID}" ]; then
echo "No connected iPhone device detected."
exit 1
else
echo "Connected iPhone UDID: ${DEVICE_UUID}"
fi
BUILD_DIR="${GIT_ROOT}/build"
#iOS build of debug scheme
xcodebuild -workspace "ios/StatusIm.xcworkspace" -configuration Debug -scheme StatusIm -destination id="${DEVICE_UUID}" -derivedDataPath "${BUILD_DIR}" -verbose | xcbeautify
APP_PATH="${BUILD_DIR}/Build/Products/Debug-iphoneos/StatusIm.app"
trap showXcrunLogs EXIT ERR INT QUIT
installAndLaunchApp &
exec "${GIT_ROOT}/scripts/run-metro.sh" 2>&1
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
set -m # needed to access jobs
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
XCRUN_INSTALL_LOG_FILE="${GIT_ROOT}/logs/xcrun_install.log"
XCRUN_LAUNCH_LOG_FILE="${GIT_ROOT}/logs/xcrun_launch.log"
XCRUN_SIMULATOR_JSON_FILE="${GIT_ROOT}/logs/ios_simulators_list.log"
# Install on the simulator
installAndLaunchApp() {
xcrun simctl install "$UDID" "$APP_PATH" > "${XCRUN_INSTALL_LOG_FILE}" 2>&1
"${GIT_ROOT}/scripts/wait-for-metro-port.sh" 2>&1
xcrun simctl launch "$UDID" im.status.ethereum.debug > "${XCRUN_LAUNCH_LOG_FILE}" 2>&1
}
showXcrunLogs() {
cat "${XCRUN_INSTALL_LOG_FILE}" >&2;
cat "${XCRUN_LAUNCH_LOG_FILE}" >&2;
}
# Check if the first argument is provided
if [ -z "${1-}" ]; then
echo "Error: No simulator name provided." >&2
exit 1
fi
# fetch available iOS Simulators
xcrun simctl list devices -j > "${XCRUN_SIMULATOR_JSON_FILE}"
SIMULATOR=${1}
# get the first available UDID for Simulators that match the name
read -r UDID SIMULATOR_STATE IS_AVAILABLE < <(jq --raw-output --arg simulator "${SIMULATOR}" '
[ .devices[] | .[] | select(.name == $simulator) ] |
map(select(.isAvailable)) + map(select(.isAvailable | not)) |
first |
"\(.udid) \(.state) \(.isAvailable)"
' "${XCRUN_SIMULATOR_JSON_FILE}")
if [ "${IS_AVAILABLE}" == false ] || [ "${UDID}" == null ]; then
echo "Error: Simulator ${SIMULATOR} is not available, Please find and install them."
echo "For help please refer"
echo "https://developer.apple.com/documentation/safari-developer-tools/adding-additional-simulators#Add-and-remove-Simulators " >&2
exit 1
fi
# sometimes a simulator is already running, shut it down to avoid errors
if [ "${SIMULATOR_STATE}" != "Shutdown" ]; then
xcrun simctl shutdown "${UDID}"
fi
# boot up iOS for simulator
xcrun simctl boot "${UDID}"
# start the simulator
open -a Simulator --args -CurrentDeviceUDID "${UDID}"
BUILD_DIR="${GIT_ROOT}/build"
#iOS build of debug scheme
xcodebuild -workspace "ios/StatusIm.xcworkspace" -configuration Debug -scheme StatusIm -destination id="${UDID}" -derivedDataPath "${BUILD_DIR}" -verbose | xcbeautify
APP_PATH="${BUILD_DIR}/Build/Products/Debug-iphonesimulator/StatusIm.app"
trap showXcrunLogs EXIT ERR INT QUIT
installAndLaunchApp &
exec "${GIT_ROOT}/scripts/run-metro.sh" 2>&1
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env bash
pkill -f 'react-native start'
react-native start --reset-cache
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)
source "${GIT_ROOT}/scripts/colors.sh"
METRO_PORT=8081
METRO_PID="$(lsof -i :${METRO_PORT} | awk 'NR!=1 {print $2}' | sort -u | tr '\r\n' ' ')"
if [ ! -z "$METRO_PID" ]; then
echo -e "${YLW}TCP port ${METRO_PORT} is required by the Metro packager.\nThe following processes currently have the port open, preventing Metro from starting:${RST}"
ps -fp $METRO_PID
echo -e "${YLW}Do you want to terminate them (y/n)?${RST}"
read -n 1 term
[[ $term == 'y' ]] && kill $METRO_PID
fi
react-native start --reset-cache
-14
View File
@@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
TIMEOUT=10 # Metro should not take this long to start.
while [ "${TIMEOUT}" -gt 0 ]; do
if ! lsof -i:8081 &> /dev/null; then
echo "."
sleep 1
((TIMEOUT--))
else
break
fi
done
+7 -27
View File
@@ -63,17 +63,10 @@
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
:compiler-options {:output-feature-set :es5
;; We disable `:fn-deprecated` warnings because we
;; are managing deprecation via clj-kondo and we
@@ -97,17 +90,10 @@
{status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
:compiler-options {:output-feature-set :es6
;;disable for android build as there
;;is an intermittent warning with deftype
@@ -137,17 +123,10 @@
status-im.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
status-im.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
status-im.config/OPENSEA_API_KEY #shadow/env "OPENSEA_API_KEY"
status-im.config/RARIBLE_MAINNET_API_KEY #shadow/env "RARIBLE_MAINNET_API_KEY"
status-im.config/RARIBLE_TESTNET_API_KEY #shadow/env "RARIBLE_TESTNET_API_KEY"
status-im.config/ALCHEMY_ETHEREUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ETHEREUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ETHEREUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ETHEREUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ETHEREUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_GOERLI_TOKEN #shadow/env "ALCHEMY_ARBITRUM_GOERLI_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_ARBITRUM_SEPOLIA_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_GOERLI_TOKEN #shadow/env "ALCHEMY_OPTIMISM_GOERLI_TOKEN"
status-im.config/ALCHEMY_OPTIMISM_SEPOLIA_TOKEN #shadow/env "ALCHEMY_OPTIMISM_SEPOLIA_TOKEN"}
status-im.config/ALCHEMY_OPTIMISM_MAINNET_TOKEN #shadow/env "ALCHEMY_OPTIMISM_MAINNET_TOKEN"
status-im.config/ALCHEMY_ARBITRUM_MAINNET_TOKEN #shadow/env "ALCHEMY_ARBITRUM_MAINNET_TOKEN"}
:compiler-options
{;; needed because we override require and it
;; messes with source-map which reports callstack
@@ -176,6 +155,7 @@
;; option setupFilesAfterEnv.
test-helpers.component-tests-preload
status-im.setup.schema-preload
quo.core-spec
status-im.core-spec]
:ns-regexp "component-spec$"
@@ -28,10 +28,10 @@
[:f>
(fn []
(rn/use-mount (fn []
(rn/hw-back-add-listener dismiss-bottom-sheet-callback)
(fn []
(rn/hw-back-remove-listener dismiss-bottom-sheet-callback))))
(rn/use-effect (fn []
(rn/hw-back-add-listener dismiss-bottom-sheet-callback)
(fn []
(rn/hw-back-remove-listener dismiss-bottom-sheet-callback))))
[theme/provider {:theme (or page-theme (theme/get-theme))}
[bottom-sheet/bottom-sheet opts
(when content
@@ -16,14 +16,12 @@
:align-self :center})
(def backdrop
{:position :absolute
:left 0
:right 0
:bottom 0
:top 0})
(def backdrop-color
{:background-color colors/neutral-100})
{:position :absolute
:left 0
:right 0
:bottom 0
:top 0
:background-color colors/neutral-100})
(def container
{:position :absolute
+2 -4
View File
@@ -207,13 +207,11 @@
[@show-bottom-sheet? @expanded? @gesture-running?])
[:<>
[rn/pressable
{:on-press (when backdrop-dismiss? close-bottom-sheet)
:style styles/backdrop}
[rn/touchable-without-feedback {:on-press (when backdrop-dismiss? close-bottom-sheet)}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity bg-opacity}
styles/backdrop-color)}]]
styles/backdrop)}]]
(cond->> [reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
+3 -1
View File
@@ -1,6 +1,7 @@
(ns legacy.status-im.currency.core
(:require
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.wallet.prices :as prices]
[utils.re-frame :as rf]))
(defn get-currency
@@ -15,4 +16,5 @@
:currency
currency
;; on changing currency, we should fetch tokens prices again
{:on-success #(rf/dispatch [:wallet/get-wallet-token])})))
{:on-success #(rf/dispatch [:wallet/get-wallet-token])})
(prices/update-prices)))

Some files were not shown because too many files have changed in this diff Show More