Compare commits

..
Author SHA1 Message Date
Siddarth Kumar 64dba60029 first draft 2023-07-13 17:33:11 +05:30
4361 changed files with 140838 additions and 176025 deletions
+236
View File
@@ -0,0 +1,236 @@
status-im.utils.build/warning-handler
status-im.utils.build/get-current-sha
status-im2.constants/spacing-char
status-im2.constants/arg-wrapping-char
status-im.ios.core/init
status-im.ui.components.camera/aspects
status-im.ui.components.camera/capture-targets
status-im.ui.components.camera/set-torch
status-im.ui.components.camera/request-access-ios
status-im.chat.models.message-content/stylings
status-im.chat.models.message-content/actions
status-im.chat.models.message-content/blank-string
status-im.chat.models.message-content/sorted-ranges
status-im.ethereum.mnemonic/words->passphrase
native-module.core/listener
native-module.core/multiaccount-reset
native-module.core/extract-group-membership-signatures
native-module.core/sign-group-membership
native-module.core/update-mailservers
status-im.ethereum.abi-spec/bytes-to-hex
status-im.android.core/init
status-im.chat.models.message/transport-keys
status-im.utils.datetime/week
status-im.utils.datetime/time-ago
status-im.utils.datetime/format-date
status-im.utils.datetime/get-ordinal-date
reagent.dom/render
reagent.dom/unmount-component-at-node
reagent.dom/dom-node
reagent.dom/force-update-all
status-im.multiaccounts.create.core/get-new-key-code
status-im.ethereum.decode/string
status-im.ui.screens.network.views/mainnet?
status-im.data-store.chats/event->string
status-im.mailserver.constants/seven-days
status-im.mailserver.constants/connection-timeout
status-im.hardwallet.card/install-applet
status-im.hardwallet.card/install-cash-applet
status-im.multiaccount.login.data-test/all-contacts
status-im.multiaccount.login.data-test/multiaccounts
status-im.multiaccount.login.data-test/get-chats
status-im.multiaccount.login.data-test/transport
status-im.multiaccount.login.data-test/topics
status-im.utils.utils/clear-timeout
status-im.utils.handlers/logged-in
status-im.multiaccounts.model/credentials
status-im.multiaccounts.login.core/contract-fleet?
status-im.multiaccounts.login.core/fetch-nodes
status-im2.config/rpc-networks-only?
status-im2.config/waku-enabled?
status-im.utils.pairing/has-paired-installations?
status-im.tribute-to-talk.core-test/user-cofx
quo.gesture-handler/tap-gesture-handler
quo.gesture-handler/pan-gesture-handler
quo.gesture-handler/long-press-gesture-handler
quo.gesture-handler/pure-native-button
quo.gesture-handler/createNativeWrapper
quo.gesture-handler/animated-raw-button
quo.gesture-handler/states
mocks.js-dependencies/action-button
mocks.js-dependencies/camera
mocks.js-dependencies/dismiss-keyboard
mocks.js-dependencies/emoji-picker
mocks.js-dependencies/i18n
mocks.js-dependencies/qr-code
mocks.js-dependencies/svg
mocks.js-dependencies/icons
mocks.js-dependencies/webview
mocks.js-dependencies/desktop-linking
mocks.js-dependencies/desktop-shortcuts
mocks.js-dependencies/snoopy
mocks.js-dependencies/snoopy-filter
mocks.js-dependencies/snoopy-bars
mocks.js-dependencies/snoopy-buffer
mocks.js-dependencies/desktop-menu
mocks.js-dependencies/desktop-config
mocks.js-dependencies/react-native-navigation-twopane
mocks.js-dependencies/react-native-screens
mocks.js-dependencies/react-native-shake
mocks.js-dependencies/back-handler
mocks.js-dependencies/react
mocks.js-dependencies/react-navigation-native
mocks.js-dependencies/react-navigation-stack
mocks.js-dependencies/react-navigation-bottom-tabs
mocks.js-dependencies/react-native-haptic-feedback
mocks.js-dependencies/mock
quo.previews.main/init
status-im.chat.models.message-list-test/descending-range
status-im.chat.models.message-list-test/random-range
status-im.ethereum.eip165/supports?
status-im.utils.hex/valid-hex?
status-im.multiaccounts.core/chat-send?
status-im.hardwallet.simulated-keycard/install-cash-applet
status-im.hardwallet.simulated-keycard/sign-typed-data
status-im.utils.core/safe-read-message-content
status-im.ui.components.react/native-modules
status-im.ui.components.react/progress-bar
status-im.utils.fs/move-file
status-im.utils.fs/read-dir
status-im.utils.fs/mkdir
status-im.utils.fs/unlink
status-im.utils.fs/file-exists?
quo.animated/code
quo.animated/eq
quo.animated/neq
quo.animated/greater-or-eq
quo.animated/not*
quo.animated/or*
quo.animated/and*
quo.animated/add
quo.animated/sub
quo.animated/multiply
quo.animated/abs
quo.animated/min*
quo.animated/max*
quo.animated/set
quo.animated/start-clock
quo.animated/stop-clock
quo.animated/bezier
quo.animated/linear
quo.animated/set-value
quo.animated/clock
quo.animated/debug
quo.animated/log
quo.animated/event
quo.animated/on-change
quo.animated/cond*
quo.animated/block
quo.animated/call*
quo.animated/timing
quo.animated/spring
quo.animated/clamp
quo.animated/with-spring
quo.animated/with-timing
quo.animated/re-timing
quo.design-system.colors/white
quo.design-system.colors/black
status-im.transport.core-test/messages
status-im.ethereum.core/sidechain?
status-im.ethereum.core/network-with-upstream-rpc?
status-im.ethereum.core/current-address
status-im.ethereum.core/network->network-name
status-im.ethereum.core/estimate-gas
quo.core/animated-header
quo.core/safe-area-provider
quo.core/safe-area-consumer
quo.core/safe-area-view
status-im.utils.universal-links.core/open!
status-im.transport.filters.core-test/member-2
status-im.ui.screens.chat.ttt/one-to-one-chat-description-container
status-im.ethereum.ens/ttl
status-im.ethereum.ens/addr-hash
status-im.ethereum.ens/name-hash
status-im.ethereum.ens/ABI-hash
status-im.ethereum.ens/pubkey-hash
status-im.network.core/get-network
status-im2.constants/desktop-content-types
status-im2.constants/blocks-per-hour
status-im2.constants/one-earth-day
status-im2.constants/left-pane-min-width
status-im2.constants/system
status-im2.constants/contact-discovery
status-im2.constants/send-transaction-failed-parse-response
status-im2.constants/send-transaction-failed-parse-params
status-im2.constants/send-transaction-no-account-selected
status-im2.constants/send-transaction-invalid-tx-sender
status-im2.constants/web3-get-logs
status-im2.constants/web3-transaction-receipt
status-im2.constants/web3-new-filter
status-im2.constants/web3-new-pending-transaction-filter
status-im2.constants/web3-new-block-filter
status-im2.constants/web3-uninstall-filter
status-im2.constants/web3-get-filter-changes
status-im2.constants/web3-shh-post
status-im2.constants/web3-shh-new-identity
status-im2.constants/web3-shh-has-identity
status-im2.constants/web3-shh-new-group
status-im2.constants/web3-shh-add-to-group
status-im2.constants/web3-shh-new-filter
status-im2.constants/web3-shh-uninstall-filter
status-im2.constants/web3-shh-get-filter-changes
status-im2.constants/web3-shh-get-messages
status-im2.constants/status-create-address
status-im2.constants/event-transfer-hash
status-im2.constants/regx-rtl-characters
status-im2.constants/desktop-msg-chars-hard-limit
status-im2.constants/debug-metrics
status-im2.constants/scan-qr-code
status-im2.constants/ipfs-proto-code
status-im2.constants/swarm-proto-code
status-im.multiaccounts.update.publisher/publish-update!
status-im.utils.async/task-queue
status-im.utils.async/async-periodic-run!
status-im.desktop.core/app-root
status-im.desktop.core/init
status-im.chat.models-test/test-db
quo.design-system.spacing/padding-vertical
status-im.utils.money/percent-change
status-im.utils.platform/isMacOs?
status-im.utils.platform/isNix?
status-im.utils.platform/isWin?
status-im.utils.platform/android-version>=
utils.debounce/clear-all
status-im.transport.db/create-chat
status-im.utils.priority-map/priority-map
status-im.utils.priority-map/priority-map-by
status-im.utils.priority-map/priority-map-keyfn
status-im.utils.priority-map/empty-message-map
status-im.wallet.choose-recipient.core/use-default-eth-gas
status-im.ui.components.animation/decay
status-im.ui.components.animation/remove-all-listeners
status-im.ui.components.animation/stop-animation
status-im.ui.components.animation/animated
status-im.ui.components.animation/add
status-im.ui.components.animation/subtract
status-im.ui.components.animation/get-layout
status-im.wallet.transactions-test/uri-query-data
quo.react-native/touchable-highlight
status-im.utils.name/shortened-name
status-im.ui.components.button.haptic/trigger
status-im.contact.db/filter-dapps
status-im.contact.db/filter-group-contacts
status-im.contact.db/legacy-pending?
status-im.utils.transducers-test/preview-call-1
status-im.utils.transducers-test/preview-call-2
status-im.utils.types/to-string
status-im.chat.db/datemark?
status-im.chat.db/gap?
status-im.chat.db/map->sorted-seq
status-im.utils.snoopy/status-module-filter
status-im.utils.snoopy/websocket-filter
status-im.utils.snoopy/touches-filter
status-im.utils.snoopy/native-animation-filter
status-im.utils.snoopy/keyboard-observer-filter
status-im.utils.multihash/hex
status-im.utils.multihash/decode-array
-1
View File
@@ -1 +0,0 @@
{:lint-as {babashka.fs/with-temp-dir clojure.core/let}}
-1
View File
@@ -1 +0,0 @@
{:hooks {:macroexpand {sci.core/copy-ns sci.core/copy-ns}}}
-9
View File
@@ -1,9 +0,0 @@
(ns sci.core)
(defmacro copy-ns
([ns-sym sci-ns]
`(copy-ns ~ns-sym ~sci-ns nil))
([ns-sym sci-ns opts]
`[(quote ~ns-sym)
~sci-ns
(quote ~opts)]))
+27 -110
View File
@@ -1,113 +1,30 @@
{:config-paths ["status-im"]
:output {:exclude-files ["src/user.cljs" "src/dev/user.cljs"]}
:lint-as {legacy.status-im.utils.views/defview clojure.core/defn
legacy.status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
legacy.status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clojure.core/defn
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
legacy.status-im.utils.styles/def clojure.core/def
legacy.status-im.utils.styles/defn clojure.core/defn
test-helpers.unit/deftest-sub clojure.core/defn
test-helpers.unit/deftest-event clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
:linters {:clojure-lsp/unused-public-var {:exclude-when-defined-by #{utils.re-frame/defn}
:exclude #{
;; even if we are not
;; using color now, we
;; will need it later
quo.foundations.colors
;; same for funcs from
;; native-module
native-module.core
;; some funcs used
;; temporarily during
;; development
test-helpers.component
test-helpers.unit
;; not sure if unused
;; functions here should
;; be removed:
keycard.keycard
react-native.fs}}
:case-duplicate-test {:level :error}
:case-quoted-test {:level :error}
:case-symbol-test {:level :error}
:clj-kondo-config {:level :error}
:cond-else {:level :error}
:condition-always-true {:level :error}
:conflicting-alias {: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
promesa.core promesa
schema.core schema
status-im.feature-flags ff
taoensso.timbre log}}
:deprecated-namespace {:level :warning}
:docstring-blank {:level :error}
:equals-true {:level :error}
:inline-def {:level :error}
:invalid-arity {:skip-args [legacy.status-im.utils.fx/defn
utils.re-frame/defn
utils.re-frame/merge]}
:loop-without-recur {:level :error}
:minus-one {:level :error}
:misplaced-docstring {:level :error}
:missing-body-in-when {:level :error}
:missing-clause-in-try {:level :error}
:missing-else-branch {:level :error}
:multiple-async-in-deftest {:level :error}
:not-empty? {:level :error}
:plus-one {:level :error}
:redundant-do {:level :error}
:redundant-let {:level :error}
:refer-all {:level :error}
;; ignore error in config itself saying that `:shadowed-fn-param` is unknown
#_{:clj-kondo/ignore [:clj-kondo-config]}
:shadowed-fn-param {:level :error}
:shadowed-var {:level :error
;; We temporarily use :include to define an
;; allowlist of core Clojure vars. In the
;; future, as we progressively fix shadowed
;; vars, we should be able to delete this
;; option and lint all vars.
:exclude [type name]}
:self-requiring-namespace {:level :error}
:single-operand-comparison {:level :error}
:syntax {:level :error}
:unbound-destructuring-default {:level :error}
:underscore-in-namespace {:level :error}
:uninitialized-var {:level :error}
:unknown-require-option {:level :error}
:unreachable-code {:level :error}
:unresolved-namespace {:level :error}
{:lint-as {status-im.utils.views/defview clojure.core/defn
status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
status-im.utils.styles/def clojure.core/def
status-im.utils.styles/defn clojure.core/defn
test-helpers.unit/deftest-sub clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
:linters {:consistent-alias {:level :error
:aliases {clojure.string string
clojure.set set
clojure.walk walk
taoensso.timbre log}}
:shadowed-var {:level :error
;; We temporarily use :include to define an
;; allowlist of core Clojure vars. In the
;; future, as we progressively fix shadowed
;; vars, we should be able to delete this
;; option and lint all vars.
:include [count iter key time]}
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
;; TODO remove number when this is fixed
;; https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number
legacy.status-im.test-helpers/restore-app-db
(cljs.test/is [match-strict?])]}
:unresolved-var {:level :error}
:unsorted-required-namespaces {:level :error}
:unused-alias {:level :warning}
:unused-binding {:level :error}
:unused-import {:level :error}
:unused-namespace {:level :error}
:unused-private-var {:level :error}
:unused-referred-var {:level :error}
:use {:level :error}}
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number
status-im.test-helpers/restore-app-db]}}
:config-in-ns {mocks.js-dependencies {:linters {:clojure-lsp/unused-public-var {:level :off}}}}}
-9
View File
@@ -1,9 +0,0 @@
{:lint-as {promesa.core/-> clojure.core/->
promesa.core/->> clojure.core/->>
promesa.core/as-> clojure.core/as->
promesa.core/let clojure.core/let
promesa.core/plet clojure.core/let
promesa.core/loop clojure.core/loop
promesa.core/recur clojure.core/recur
promesa.core/with-redefs clojure.core/with-redefs
promesa.core/doseq clojure.core/doseq}}
-2
View File
@@ -1,2 +0,0 @@
{:lint-as {malli.experimental/defn schema.core/defn}
:linters {:unresolved-symbol {:exclude [(malli.core/=>)]}}}
@@ -1,4 +0,0 @@
{:linters
{:unresolved-symbol
{:exclude [(cljs.test/is [match? thrown-match?])
(clojure.test/is [match? thrown-match?])]}}}
@@ -1,5 +0,0 @@
{:lint-as
{rewrite-clj.zip/subedit-> clojure.core/->
rewrite-clj.zip/subedit->> clojure.core/->>
rewrite-clj.zip/edit-> clojure.core/->
rewrite-clj.zip/edit->> clojure.core/->>}}
-21
View File
@@ -1,21 +0,0 @@
(ns cljs.test
(:require [clj-kondo.hooks-api :as hooks]))
(defn deftest
"Verify test name passed to `cljs.test/deftest` is suffixed with -test and not
prefixed with test-."
[{:keys [node]}]
(let [[_ test-name-node & _] (:children node)
test-name (str (hooks/sexpr test-name-node))]
(when (and (hooks/token-node? test-name-node)
(or (not (re-find #"^.*-test$" test-name))
(re-find #"^test-.*$" test-name)))
(hooks/reg-finding! (assoc (meta test-name-node)
:message "Test name should be suffixed with -test"
:type :status-im.linter/inconsistent-test-name)))))
(comment
;; Invalid
(deftest {:node (hooks/parse-string "(deftest foo-tes (println :hello))")})
(deftest {:node (hooks/parse-string "(deftest test-foo-test (println :hello))")})
)
-11
View File
@@ -1,11 +0,0 @@
{:hooks
{:analyze-call
{utils.i18n/label utils.i18n/label
test-helpers.component/get-all-by-translation-text utils.i18n/label
test-helpers.component/get-by-translation-text utils.i18n/label
test-helpers.component/query-all-by-translation-text utils.i18n/label
test-helpers.component/query-by-translation-text utils.i18n/label
cljs.test/deftest cljs.test/deftest}}
:linters {:status-im.linter/invalid-translation-keyword {:level :error}
:status-im.linter/inconsistent-test-name {:level :error}}}
-26
View File
@@ -1,26 +0,0 @@
(ns utils.i18n
(:require [clj-kondo.hooks-api :as hooks]))
(defn label
"Verify call to `utils.i18n/label` pass the translation keyword qualified with `t`."
[{:keys [node]}]
(let [[_ translation-key-node & _] (:children node)]
(when (and (hooks/keyword-node? translation-key-node)
(not= "t" (-> translation-key-node hooks/sexpr namespace)))
(hooks/reg-finding! (assoc (meta translation-key-node)
:message "Translation keyword should be qualified with \"t\""
:type :status-im.linter/invalid-translation-keyword)))))
(comment
;; Valid
(label {:node (hooks/parse-string "(i18n/label :t/foo {:var \"hello\"})")
:cljc false
:lang :cljs
:filename ""
:config {}
:ns ""
:context nil})
;; Invalid
(label {:node (hooks/parse-string "(i18n/label :foo)")})
)
-1
View File
@@ -1 +0,0 @@
{:hooks {:analyze-call {taoensso.encore/defalias taoensso.encore/defalias}}}
@@ -1,16 +0,0 @@
(ns taoensso.encore
(:require
[clj-kondo.hooks-api :as hooks]))
(defn defalias [{:keys [node]}]
(let [[sym-raw src-raw] (rest (:children node))
src (if src-raw src-raw sym-raw)
sym (if src-raw
sym-raw
(symbol (name (hooks/sexpr src))))]
{:node (with-meta
(hooks/list-node
[(hooks/token-node 'def)
(hooks/token-node (hooks/sexpr sym))
(hooks/token-node (hooks/sexpr src))])
(meta src))}))
+4 -9
View File
@@ -1,8 +1,10 @@
CACHED_WEBVIEWS_ENABLED=1
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=mainnet_rpc
DEV_BUILD=1
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=info
MAILSERVER_CONFIRMATIONS_ENABLED=1
@@ -20,21 +22,14 @@ KEYCARD_TEST_MENU=0
QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=1
ENABLE_QUO_PREVIEW=1
MAX_IMAGES_BATCH=5
APN_TOPIC=im.status.ethereum.pr
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1
DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1
COMMANDS_ENABLED=1
TWO_MINUTES_SYNCING=1
SWAP_ENABLED=1
STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1
TEST_STATEOFUS=1
FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
SHOW_NOT_IMPLEMENTED_FEATURES=0
ENABLE_ALERT_BANNER=0
FLAG_WALLET_CONNECT_ENABLED=1
API_LOGGING_ENABLED=1
SENTRY_ENABLED=0
SENTRY_ENVIRONMENT=ci-main
+5 -14
View File
@@ -1,7 +1,8 @@
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.staging
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=0
@@ -20,9 +21,10 @@ COMMANDS_ENABLED=1
KEYCARD_TEST_MENU=1
QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=0
MAX_IMAGES_BATCH=5
APN_TOPIC=im.status.ethereum.pr
VERIFY_TRANSACTION_CHAIN_ID=11155111
VERIFY_ENS_CHAIN_ID=11155111
VERIFY_TRANSACTION_CHAIN_ID=5
VERIFY_ENS_CHAIN_ID=5
TEST_STATEOFUS=1
DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1
@@ -31,14 +33,3 @@ DELETE_MESSAGE_ENABLED=1
TWO_MINUTES_SYNCING=1
STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
SHOW_NOT_IMPLEMENTED_FEATURES=1
DELETE_MESSAGE_FOR_ME_UNDO_TIME_LIMIT=10000
DELETE_MESSAGE_UNDO_TIME_LIMIT=10000
ENABLE_ALERT_BANNER=0
FLAG_WALLET_CONNECT_ENABLED=1
MOBILE_DATA_SYNCING_TOGGLE_ENABLE=0
API_LOGGING_ENABLED=1
SENTRY_ENABLED=0
SENTRY_ENVIRONMENT=ci-main
+5 -9
View File
@@ -1,7 +1,9 @@
CACHED_WEBVIEWS_ENABLED=1
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=goerli_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
MAILSERVER_CONFIRMATIONS_ENABLED=1
@@ -20,10 +22,11 @@ KEYCARD_TEST_MENU=0
ENABLE_ROOT_ALERT=1
DISABLE_WALLET_ON_MOBILE_NETWORK=1
APN_TOPIC=im.status.ethereum.pr
VERIFY_TRANSACTION_CHAIN_ID=11155111
VERIFY_ENS_CHAIN_ID=11155111
VERIFY_TRANSACTION_CHAIN_ID=5
VERIFY_ENS_CHAIN_ID=5
TEST_STATEOFUS=1
BLANK_PREVIEW=0
MAX_IMAGES_BATCH=5
DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1
@@ -32,10 +35,3 @@ TWO_MINUTES_SYNCING=1
ENABLE_QUO_PREVIEW=1
STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
ENABLE_ALERT_BANNER=1
FLAG_WALLET_CONNECT_ENABLED=1
API_LOGGING_ENABLED=1
SENTRY_ENABLED=0
SENTRY_ENVIRONMENT=ci-main
+4 -8
View File
@@ -1,8 +1,10 @@
DEBUG_WEBVIEW=1
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=1
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=debug
LOG_LEVEL=info
MAILSERVER_CONFIRMATIONS_ENABLED=1
MAINNET_WARNING_ENABLED=1
PFS_ENCRYPTION_ENABLED=1
@@ -15,14 +17,8 @@ RPC_NETWORKS_ONLY=0
PARTITIONED_TOPIC=0
CONTRACT_NODES=1
ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=5
BLANK_PREVIEW=0
COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1
DELETE_MESSAGE_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
ENABLE_ALERT_BANNER=1
FLAG_WALLET_CONNECT_ENABLED=1
API_LOGGING_ENABLED=1
SENTRY_ENABLED=1
SENTRY_ENVIRONMENT=ci-nightly
+4 -8
View File
@@ -1,8 +1,10 @@
DEBUG_WEBVIEW=0
DEFAULT_NETWORK=mainnet_rpc
ETHEREUM_DEV_CLUSTER=0
EXTENSIONS=0
FLEET=status.prod
GROUP_CHATS_ENABLED=1
LOG_LEVEL=error
LOG_LEVEL=
MAILSERVER_CONFIRMATIONS_ENABLED=1
MAINNET_WARNING_ENABLED=1
PFS_ENCRYPTION_ENABLED=1
@@ -16,10 +18,4 @@ PARTITIONED_TOPIC=0
ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=1
DELETE_MESSAGE_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
STATUS_PROXY_STAGE_NAME=prod
FLAG_WALLET_CONNECT_ENABLED=1
API_LOGGING_ENABLED=0
SENTRY_ENABLED=1
SENTRY_ENVIRONMENT=production
COLLECTIBLES_ENABLED=1
+1 -1
View File
@@ -1,4 +1,4 @@
module.exports = {
root: true,
extends: '@react-native',
extends: '@react-native-community',
};
+3 -2
View File
@@ -2,7 +2,7 @@
name: Bug Report
about: Bug Report
title: ''
type: 'Bug'
labels: bug
assignees: ''
---
@@ -22,7 +22,8 @@ assignees: ''
### Reproduction
1.
1) Open Status
2)
### Additional Information
-30
View File
@@ -1,30 +0,0 @@
---
name: Wont fix Report
about: to facilitate future handling, identify and address non-urgent issues that won't be prioritized in the near future
title: ''
labels: likely_wont_fix
assignees: ''
---
## Problem
#### Expected behavior
#### Actual behavior
### Reproduction
1.
### Additional Information
- Status version: release
- Operating System: Android, iOS
[comment]: # (Please, add logs/notes if necessary)
+28 -32
View File
@@ -1,26 +1,39 @@
[comment]: # (Please replace ... with your information. Remove < and >)
[comment]: # (To auto-close issue on merge, please insert the related issue number after # i.e fixes #566)
If you submit PR for issue with bounty then write here Fixes #NN where NN is issue number
*otherwise*
fixes #...
## Summary
### Summary
[comment]: # (Summarise the problem and how the pull request solves it)
...
## Review notes
[comment]: # (Optional. Specify if something in particular should be looked at, or ignored, during review)
<!-- (Optional, remove if no changes to documentation) -->
Documentation change PR (review please): https://github.com/status-im/status.im/pull/xxx
## Testing notes
[comment]: # (Optional)
### Review notes
<!-- (Optional. Specify if something in particular should be looked at, or ignored, during review) -->
### Platforms
[comment]: # (Optional. Specify which platforms should be tested)
### Testing notes
<!-- (Optional) -->
#### Platforms
<!-- (Optional. Specify which platforms should be tested) -->
- Android
- iOS
- macOS
- Linux
- Windows
### Areas that may be impacted
[comment]: # (Optional. Specify if some specific areas need to be tested, such as 1-1 chats)
#### Areas that maybe impacted
<!-- (Optional. Specify if some specific areas has to be tested, for example 1-1 chats) -->
#### Functional
##### Functional
- 1-1 chats
- public chats
@@ -35,36 +48,19 @@ fixes #...
- fleet
- bootnodes
#### Non-functional
##### Non-functional
- battery performance
- CPU performance / speed of the app
- network consumption
## Steps to test
[comment]: # (Specify exact steps to test if there are such)
### Steps to test
<!-- (Specify exact steps to test if there are such) -->
- Open Status
- ...
- Step 3, etc.
<!-- (PRs will only be accepted if squashed into single commit.) -->
[comment]: # (Can be ready or wip)
status: ready
<!-- Uncomment this section for status-go upgrade/dogfooding pull requests
- Specify potentially impacted user flows in _Areas that may be impacted*.
- Ensure that _Steps to test_ is filled in.
### Risk
Described potential risks and worst case scenarios.
Tick **one**:
- [ ] Low risk: 2 devs MUST perform testing as specified above and attach their results as comments to this PR **before** merging.
- [ ] High risk: QA team MUST perform additional testing in the specified affected areas **before** merging.
-->
status: ready <!-- Can be ready or wip -->
-12
View File
@@ -36,10 +36,6 @@ project.xcworkspace
**/android/.project
**/android/.settings/org.eclipse.buildship.core.prefs
local.properties
*.hprof
.cxx/
*.keystore
!debug.keystore
# Atom
.tags*
@@ -83,9 +79,6 @@ shim.js
figwheel_server.log
.nrepl-port
# FlowStorm (Clojure debugger)
repl-client-debug
# Lein
#
.lein-failures
@@ -130,8 +123,6 @@ fastlane/README.md
# Clj
.cpcache/
src/user.cljs
src/dev/user.cljs
# emacs
.dir-locals.el
@@ -199,6 +190,3 @@ test/appium/tests/users.py
## git hooks
lefthook.yml
## build time logs
/logs/*.log
-3
View File
@@ -1,3 +0,0 @@
[submodule "legal-docs"]
path = legal-docs
url = https://github.com/status-im/status-software-legal-documents.git
-1
View File
@@ -1 +0,0 @@
{:clean {:ns-inner-blocks-indentation :keep}}
+4 -4
View File
@@ -1,10 +1,10 @@
{
"include": [
"target/test/legacy/status_im/**"
"target/test/status_im/**"
],
"exclude": [
"target/test/legacy/status_im/test/**",
"target/test/legacy/status_im/ui/**"
"target/test/status_im/test/**",
"target/test/status_im/ui/**"
],
"report-dir": "./coverage-report",
"all": true,
@@ -14,4 +14,4 @@
"exclude-after-remap": false,
"extension": [".js"],
"reporter": ["lcovonly"]
}
}
+8 -14
View File
@@ -1,15 +1,9 @@
/*
# Format top-level js files.
*
!*.js
# Ignore all except src/js/**/*.js
!/src/
/src/*
!/src/js
!/src/js/**/*.js
# Ignore all except translations/en.json
!/translations/
/translations/*
!/translations/en.json
!*/
*.clj-kondo
*.shadow-cljs
modules
result
target
component-spec
-4
View File
@@ -6,8 +6,4 @@ module.exports = {
tabWidth: 2,
trailingComma: 'all',
useTabs: false,
// JSON sorting
jsonSortOrder: '{ "/.*/": "caseInsensitiveLexical" } ',
plugins: ['prettier-plugin-sort-json'],
};
-12
View File
@@ -1,12 +0,0 @@
{
"editor.formatOnSave": true,
"clojure.format.enable": false,
"[clojure]": {
"editor.defaultFormatter": "rflagreca.vscode-clj-zprint"
},
"vscode-clj-zprint.IgnoreExternalFiles": false,
"vscode-clj-zprint.CommunityFormatting": false,
"vscode-clj-zprint.OptionsMap": "",
"vscode-clj-zprint.width": "",
"vscode-clj-zprint.Styles.UseOnlyTheseStyles": false
}
+1 -3
View File
@@ -1,8 +1,6 @@
{
"ignore_dirs": [
"android/build",
"target",
".clj-kondo",
".shadow-cljs"
"target"
]
}
+39 -50
View File
@@ -1,62 +1,51 @@
;; -*- mode: clojure -*-
;; vi: ft=clojure
{:width 105
:remove {:fn-force-nl #{:noarg1-body}}
{:width 105
:style [;; community style
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community
:community
:style
[;; community style https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community
:community
;; no comma in map
:no-comma
;; no comma in map
:no-comma
:custom-justify
:custom-justify
;; respect all newlines
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-nl
:respect-nl
;; respect all newlines https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-nl
:respect-nl
;; respect blank line https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
:respect-bl
;; hang multiline left-hand-thing https://github.com/kkinnear/zprint/issues/273
:multi-lhs-hang]
;; respect blank line
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
:respect-bl
;; hang multiline left-hand-thing
;; https://github.com/kkinnear/zprint/issues/273
:multi-lhs-hang]
:fn-map
{"reg-sub" :arg1-pair
"h/describe" :arg1-body
"h/describe-skip" :arg1-body
"h/describe-only" :arg1-body
"h/test" :arg1-body
"h/test-skip" :arg1-body
"h/test-only" :arg1-body
"test/async" :arg1-body
"test/use-fixtures" :arg1-body
"global.describe" :arg1-body
"global.test" :arg1-body
"list-comp" :binding
"defview" :arg1-body
"letsubs" :binding
"with-let" "let"
"reg-event-fx" :arg1-pair
"reg-fx" :arg1-pair
"testing" :arg1-body
"deftest-sub" :arg1-body
"deftest-event" :arg1-body
"test-async" :arg1-body
"wait-for" :arg1-body
"with-deps-check" :arg1-body
"schema/=>" :arg1-body
"->" [:noarg1-body
{:list {:constant-pair? false :force-nl? false}
:next-inner-restore [[:list :constant-pair?]]}]
"set!" "reset!"
"assoc-when" "assoc"
"assoc-some" "assoc"
"conj-when" "conj"
"conj-some" "conj"}
{"reg-sub" :arg1-pair
"h/describe" :arg1-body
"h/test" :arg1-body
"global.describe" :arg1-body
"global.test" :arg1-body
"list-comp" :binding
"defview" :arg1-body
"letsubs" :binding
"with-let" "let"
"testing" :arg1-body
"deftest-sub" :arg1-body
"wait-for" :arg1-body
"with-deps-check" :arg1-body
"->" [:noarg1-body
{:list {:constant-pair? false :force-nl? false}
:next-inner-restore [[:list :constant-pair?]]}]
"set!" "reset!"
"assoc-when" "assoc"
"assoc-some" "assoc"
"conj-when" "conj"
"conj-some" "conj"}
:remove {:fn-force-nl #{:noarg1-body}}
:style-map
{:no-comma {:map {:comma? false}}
{:no-comma {:map {:comma? false}}
:custom-justify
{:doc "Justify everything using pre-1.1.2 approach"
:binding {:justify? true :justify {:max-variance 1000}}
+75 -175
View File
@@ -32,28 +32,31 @@ ifndef BUILD_TAG
export BUILD_TAG := $(shell git rev-parse --short HEAD)
endif
# We don't want to use /run/user/$UID because it runs out of space too easily.
# We don't want to use /run/user/$UID because it runs out of space too easilly.
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.
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,\
ANDROID_GRADLE_OPTS,ANDROID_ABI_SPLIT,ANDROID_ABI_INCLUDE,\
STATUS_GO_SRC_OVERRIDE,STATUS_GO_IPFS_GATEWAY_URL
export _NIX_KEEP ?= TMPDIR,BUILD_ENV,STATUS_GO_SRC_OVERRIDE
# 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
#----------------
@@ -95,8 +98,6 @@ nix-purge: ##@nix Completely remove Nix setup, including /nix directory
nix/scripts/purge.sh
nix-update-gradle: export TARGET := gradle
nix-update-gradle: export ORG_GRADLE_PROJECT_hermesEnabled := false
nix-update-gradle: export ORG_GRADLE_PROJECT_universalApk := false
nix-update-gradle: ##@nix Update maven nix expressions based on current gradle setup
nix/deps/gradle/generate.sh
@@ -104,7 +105,7 @@ nix-update-clojure: export TARGET := clojure
nix-update-clojure: ##@nix Update maven Nix expressions based on current clojure setup
nix/deps/clojure/generate.sh
nix-update-gems: export TARGET := fastlane
nix-update-gems: export TARGET := default
nix-update-gems: ##@nix Update Ruby gems in fastlane/Gemfile.lock and fastlane/gemset.nix
fastlane/update.sh
@@ -139,7 +140,7 @@ _install-hooks: ##@prepare Create prepare-commit-msg git hook symlink
# Remove directories and ignored files
clean: SHELL := /bin/sh
clean: _fix-node-perms _tmpdir-rm ios-clean android-clean ##@prepare Remove all output folders
clean: _fix-node-perms _tmpdir-rm ##@prepare Remove all output folders
git clean -dXf
# Remove directories, ignored and non-ignored files
@@ -156,12 +157,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):
@@ -196,10 +195,6 @@ xcode-clean: XCODE_HOME := $(HOME)/Library/Developer/Xcode
xcode-clean: ##@prepare Clean XCode derived data and archives
rm -fr $(XCODE_HOME)/DerivedData/StatusIm-* $(XCODE_HOME)/Archives/*/StatusIm*
ios-simulator-cache-clean: SHELL := /bin/sh
ios-simulator-cache-clean: ##@prepare Clean iOS Simulator Caches
rm -rf ~/Library/Developer/CoreSimulator/Cache
#----------------
# Release builds
#----------------
@@ -214,17 +209,18 @@ 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
@scripts/build-android.sh
release-android: export TARGET := keytool
release-android: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
release-android: keystore build-android ##@build Build signed Android APK
@scripts/sign-android.sh result/app-arm64-v8a-release-unsigned.apk
@scripts/sign-android.sh result/app-release-unsigned.apk
release-ios: export TARGET := ios
release-ios: export IOS_STATUS_GO_TARGETS := ios/arm64
release-ios: export BUILD_ENV ?= prod
release-ios: watchman-clean ios-clean jsbundle ##@build Build release for iOS release
xcodebuild \
@@ -265,38 +261,36 @@ 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
export RE_FRISK_PORT ?= 4567
@scripts/start-react-native.sh
run-re-frisk: export TARGET := clojure
run-re-frisk: ##@run Start re-frisk server
yarn shadow-cljs run re-frisk-remote.core/start ${RE_FRISK_PORT}
yarn shadow-cljs run re-frisk-remote.core/start
# 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
run-android: export ORG_GRADLE_PROJECT_universalApk := false
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
SIMULATOR=iPhone 11 Pro
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: ##@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: export TARGET := ios
show-ios-devices: ##@other shows connected ios device and its name
xcrun xctrace list devices
# 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
@@ -304,21 +298,17 @@ run-ios-device: ##@run iOS app and start it on the first connected iPhone
# Get all clojure files, including untracked, excluding removed
define find_all_clojure_files
$$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep -E '((\.clj-kondo\/status-im)|(src).*\.clj[sc]?$$)|((\.clj-kondo\/(status-im|config))|(src).*\.edn$$)|shadow-cljs\.edn')
$$(comm -23 <(sort <(git ls-files --cached --others --exclude-standard)) <(sort <(git ls-files --deleted)) | grep -e \.clj$$ -e \.cljs$$ -e \.cljc$$ -e \.edn)
endef
lint: export TARGET := clojure
lint: export CLJ_LINTER_PRINT_WARNINGS ?= false
lint: ##@test Run code style checks
@sh scripts/lint/re-frame-in-quo-components.sh && \
sh scripts/lint/direct-require-component-outside-quo.sh && \
sh scripts/lint/require-i18n-resource-first.sh && \
clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src $(if $(filter $(CLJ_LINTER_PRINT_WARNINGS),true),,| grep -v ': warning: ') && \
@sh scripts/lint-re-frame-in-quo-components.sh && \
clj-kondo --config .clj-kondo/config.edn --cache false --lint src && \
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
scripts/lint/translations.clj && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint/trailing-newline.sh && \
node_modules/.bin/prettier --check .
sh scripts/lint-trailing-newline.sh && \
yarn prettier
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
lint-fix: export TARGET := clojure
@@ -326,96 +316,48 @@ lint-fix: ##@test Run code style checks and fix issues
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \
clojure-lsp --ns-exclude-regex ".*/\.clj-kondo/.*|.*/src/status_im/core\.cljs|.*/src/test_helpers/component_tests_preload\.cljs$$" clean-ns && \
sh scripts/lint/trailing-newline.sh --fix && \
node_modules/.bin/prettier --write .
sh scripts/lint-trailing-newline.sh --fix && \
yarn prettier
shadow-server: export TARGET := clojure
shadow-server:##@ Start shadow-cljs in server mode for watching
yarn shadow-cljs server
_test-clojure: export TARGET := clojure
_test-clojure: export WATCH ?= false
_test-clojure: status-go-library
_test-clojure:
ifeq ($(WATCH), true)
yarn node-pre-gyp rebuild && \
yarn shadow-cljs compile mocks && \
nodemon --exec "yarn shadow-cljs compile test && node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO" -e cljs
else
yarn node-pre-gyp rebuild && \
test-watch: export TARGET := clojure
test-watch: ##@ Watch tests and re-run no changes to cljs files
yarn install
nodemon --exec 'yarn shadow-cljs compile mocks && yarn shadow-cljs compile test && node --require ./test-resources/override.js target/test/test.js' -e cljs
test-watch-for-repl: export TARGET := clojure
test-watch-for-repl: ##@ Watch tests and support REPL connections
yarn install
rm -f target/test/test.js
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
'yarn shadow-cljs compile mocks && yarn shadow-cljs watch test --verbose' \
'until [ -f ./target/test/test.js ] ; do sleep 1 ; done ; node --require ./test-resources/override.js ./target/test/test.js --repl'
test: export TARGET := clojure
test: ##@test Run tests once in NodeJS
# Here we create the gyp bindings for nodejs
yarn install
yarn shadow-cljs compile mocks && \
yarn shadow-cljs compile test && \
node --require ./test-resources/override.js "$$SHADOW_OUTPUT_TO"
endif
node --require ./test-resources/override.js target/test/test.js
test: export SHADOW_OUTPUT_TO := target/test/test.js
test: export SHADOW_NS_REGEXP := .*-test$$
test: ##@test Run all Clojure tests
test: _test-clojure
component-test-watch: export TARGET := clojure
component-test-watch: export COMPONENT_TEST := true
component-test-watch: export BABEL_ENV := test
component-test-watch: ##@ Watch tests and re-run no changes to cljs files
yarn install
nodemon --exec 'yarn shadow-cljs compile component-test && jest --config=test/jest/jest.config.js' -e cljs
# Note: we need to override the :output-to and :ns-regexp options because
# shadow-cljs has a bug where it will not read from the env vars to expand the
# configuration when the shadow-cljs mobile target is already running.
test-watch-for-repl: export TARGET := default
test-watch-for-repl: export SHADOW_OUTPUT_TO := target/test/test.js
test-watch-for-repl: export SHADOW_NS_REGEXP := .*-test$$
test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connections
rm -f "$$SHADOW_OUTPUT_TO" && \
yarn install && shadow-cljs compile mocks && \
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
"yarn shadow-cljs watch test --verbose --config-merge '{:output-to \"$(SHADOW_OUTPUT_TO)\" :ns-regexp \"$(SHADOW_NS_REGEXP)\"}'" \
"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: ##@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: ##@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
test-android: jsbundle
test-android: export TARGET := android
test-android: ##@test Android Gradle test
cd android && ./gradlew test
test-component-watch: export TARGET := clojure
test-component-watch: export COMPONENT_TEST := true
test-component-watch: export BABEL_ENV := test
test-component-watch: export JEST_USE_SILENT_REPORTER := false
test-component-watch: ##@ Watch tests and re-run no changes to cljs files
@scripts/check-metro-shadow-process.sh
rm -rf ./component-spec
nodemon --exec 'yarn shadow-cljs compile component-test && jest --config=test/jest/jest.config.js --testEnvironment node ' -e cljs
test-component: export TARGET := clojure
test-component: export COMPONENT_TEST := true
test-component: export BABEL_ENV := test
test-component: export JEST_USE_SILENT_REPORTER := false
test-component: ##@test Run component tests once in NodeJS
@scripts/check-metro-shadow-process.sh
rm -rf ./component-spec
component-test: export TARGET := clojure
component-test: export COMPONENT_TEST := true
component-test: export BABEL_ENV := test
component-test: ##@test Run component tests once in NodeJS
yarn install
yarn shadow-cljs compile component-test && \
jest --clearCache && jest --config=test/jest/jest.config.js --testEnvironment node
# Reference: https://flow-storm.github.io/flow-storm-debugger/user_guide.html#_debugging_react_native_applications
run-flow-storm: export SHADOW_CLJS_BUILD_ID := :mobile
run-flow-storm: export TARGET := clojure
run-flow-storm: export GDK_DPI_SCALE := 1.0
run-flow-storm: ##@run Start FlowStorm debugger
clj -Sforce -Sdeps '{:deps {com.github.jpmonettas/flow-storm-dbg {:mvn/version "3.7.5"}}}' \
-X flow-storm.debugger.main/start-debugger \
:port 7888 \
:repl-type :shadow \
:build-id $(SHADOW_CLJS_BUILD_ID)
jest --config=test/jest/jest.config.js
#--------------
# Other
@@ -427,48 +369,25 @@ geth-connect: ##@other Connect to Geth on the device
build/bin/geth attach http://localhost:8545
ios-clean: SHELL := /bin/sh
ios-clean: ios-simulator-cache-clean
ios-clean: ##@prepare Clean iOS build artifacts
git clean -dxf -f target/ios
android-clean: SHELL := /bin/sh
android-clean: export TARGET := gradle
android-clean: ##@prepare Clean Gradle state
git clean -dxf -f ./android/app/build; \
rm -rf android/.gradle \
rm -rf android/build \
rm -rf ~/.gradle
[[ -d android/.gradle ]] && cd android && ./gradlew clean
android-ports: export FLOWSTORM_PORT ?= 7722
android-ports: export TARGET := android-sdk
android-ports: export RCT_METRO_PORT ?= 8081
android-ports: ##@other Add proxies to Android Device/Simulator
adb reverse tcp:$(RCT_METRO_PORT) tcp:$(RCT_METRO_PORT) && \
adb reverse tcp:8081 tcp:8081 && \
adb reverse tcp:3449 tcp:3449 && \
adb reverse tcp:$(RE_FRISK_PORT) tcp:$(RE_FRISK_PORT) && \
adb reverse tcp:$(FLOWSTORM_PORT) tcp:$(FLOWSTORM_PORT) && \
adb reverse tcp:4567 tcp:4567 && \
adb forward tcp:5561 tcp:5561
android-devices: export TARGET := android-sdk
android-devices: ##@other Invoke adb devices
adb devices
android-pull-geth: export TARGET := android-sdk
android-pull-geth: export VERSION ?= debug
android-pull-geth:
adb pull "/storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log"
android-tail-geth: export TARGET := android-sdk
android-tail-geth: export VERSION ?= debug
android-tail-geth:
adb shell 'while true; do cat; sleep 1; done < /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-clean-geth: export TARGET := android-sdk
android-clean-geth: export VERSION ?= debug
android-clean-geth:
adb shell 'rm /storage/emulated/0/Android/data/im.status.ethereum$$( [ "$(VERSION)" = "release" ] || echo ".$(VERSION)" )/files/Download/geth.log'
android-logcat: export TARGET := android-sdk
android-logcat: ##@other Read status-mobile logs from Android phone using adb
adb logcat | grep -e RNBootstrap -e ReactNativeJS -e ReactNative -e StatusModule -e StatusNativeLogs -e 'F DEBUG :' -e 'Go :' -e 'GoLog :' -e 'libc :'
@@ -482,10 +401,6 @@ _list: SHELL := /bin/sh
_list:
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
patch-file: export TARGET := default
patch-file: ##@other Generates patch file for npm deps
@scripts/patch-npm-lib.sh
#--------------
# REPLs
#--------------
@@ -495,18 +410,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)"
+24 -19
View File
@@ -2,11 +2,9 @@
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" alt="Get it on Google Play" height="80"/>](https://play.google.com/store/apps/details?id=im.status.ethereum)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="80"/>](https://f-droid.org/packages/im.status.ethereum/)
[<img src="doc/github_badge.png" alt="Get it on Github" height="80"/>](https://github.com/status-im/status-mobile/releases)
[Get it on Github](https://github.com/status-im/status-mobile/releases)
Join us in creating a browser, messenger, and gateway to a decentralized world. Status is a free (libre) open source mobile client targeting Android & iOS built entirely on [Ethereum](https://ethereum.org/) technologies. That's right, no middlemen and `go-ethereum` running directly on your device.
Join us in creating a browser, messenger, and gateway to a decentralized world. Status is a free (libre) open source mobile client targeting Android & iOS built entirely on [Ethereum](https://ethereum.org/) technologies. That's right, no middle men and `go-ethereum` running directly on your device.
[![Getting started with Status](https://i.imgur.com/C0aZZEL.jpg)](https://www.youtube.com/watch?v=oDCSEmS9c3o "Getting started with Status")
@@ -14,49 +12,52 @@ Join us in creating a browser, messenger, and gateway to a decentralized world.
We believe in a medium of pure free trade, economies with fair, permission-less access and a world without intermediaries. We want to create policies that can exist between friends or scale globally, we want to communicate securely and be uninhibited by legacy systems.
We want to take responsibility for our data, and the way we conduct ourselves privately and promote this way of life to a mass audience.
We want to take responsibility for our data, the way we conduct ourselves privately and promote this way of life to a mass audience.
We want deep insights into our own economies so we can make informed, data-driven decisions on how to make our lives better. The Ethereum blockchain, Smart Contracts, Swarm and Whisper provide us with a path forward.
We want deep insights into our own economies so we can make informed, data-driven decisions on how to make our lives better. The Ethereum blockchain, Smart Contracts, Swarm and Whisper provides us a path forward.
If this interests you, **help us make Status a reality** - anyone can contribute and we need everyone at any skill level to participate.
## How to Contribute?
Go straight to the [docs](doc/) and choose what interests you:
Go straight to the [docs](https://status.im/docs) or [join our chat](https://join.status.im/chat/public/status) and choose what interests you:
- **Developer** Developers are the heart of software and to keep Status beating
we need all the help we can get! If you're looking to code in ClojureScript or
Golang then Status is the project for you! We use React Native and there is even
some Java/Objective-C too! Want to learn more about it? Start by reading our
[Developer Introduction](doc/starting-guide.md) which guides you
[Developer Introduction](https://status.im/developer_tools/) which guides you
through the technology stack and start browsing [beginner
issues](https://github.com/status-im/status-mobile/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22good%20first%20issue%22%20).
Then you can read how to [Build
Status](doc/starting-guide.md), which talks about managing
project dependencies, coding guidelines and testing procedures.
Check out our [coding guidelines](doc/new-guidelines.md).
Status](https://status.im/technical/build_status/), which talks about managing
project dependencies, coding guidelines and testing procedures. The [doc/](doc/)
directory also has valuable information for contributors.
- **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 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.
John Dewey once said "Education is not preparation for life; education is life *itself* ". Developers & Designers need guidance and it all starts from documentation and specifications. Our software is only as good as its documentation, head over to our [docs](https://status.im/docs) and see how you can improve what we have.
- **Blog Writing**
Content is King, keeping our blog up to date and informing the community of news helps keep everyone on the same page.
Content is King, keeping our blog up to date and informing the community of news helps keep everyone on the same page. [Jump into our chat](https://join.status.im/chat/public/status) and discuss with the team how you can contribute!
- **Testers**
It's bug-hunting season! Status is currently under active development and there is sure to be a bunch of learning, [build status from scratch](doc/starting-guide.md) or if an android user checks out our [nightly builds](https://status.im/nightly). You can shake your phone to submit bug reports, or start browsing our [Github Issues](https://github.com/status-im/status-mobile/issues). Every bug you find brings Status closer to stable, usable software for everyone to enjoy!
It's bug hunting season! Status is currently under active development and there is sure to be a bunch of learning, [build status from scratch](https://status.im/technical/build_status/) or if an android user check out our [nightly builds](https://status.im/nightly). You can shake your phone to submit bug reports, or start browsing our [Github Issues](https://github.com/status-im/status-mobile/issues). Every bug you find brings Status closer to stable, usable software for everyone to enjoy!
- **Security**
Status is a visual interface to make permanent changes on the Blockchain, it handles crypto-tokens that have real value and allows 3rd party code execution. Security is paramount to its success. You are given permission to break Status as hard as you can, as long as you share your findings with the community!
- **Evangelism**
Help us spread the word! Tell a friend *right now*, in fact, tell **everyone** - yell from a mountain if you have to, every person counts! If you've got a great story to tell or have some interesting way you've spread the word about Status let us know about it in our [chat](https://join.status.im/chat/public/status)
Help us spread the word! Tell a friend *right now*, in fact tell **everyone** - yell from a mountain if you have to, every person counts! If you've got a great story to tell or have some interesting way you've spread the word about Status let us know about it in our [chat](https://join.status.im/chat/public/status)
## Status API
View our [API Docs](https://status.im/developer_tools/status_web_api.html) and learn how to integrate your DApp into Status. You can read more about how to add your DApp to Status [here](https://status.im/developer_tools/add_your_dapp.html).
## 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
@@ -67,8 +68,12 @@ Without the dedication of these outstanding individuals, Status would not exist.
## Contact us
Feel free to email us at [support@status.im](mailto:support@status.im).
Feel free to email us at [support@status.im](mailto:support@status.im) or better yet, [join our chat](https://join.status.im/chat/public/status).
## License
Licensed under the [Mozilla Public License v2.0](https://github.com/status-im/status-mobile/blob/develop/LICENSE.md)
## Testing Supported by
[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=SFBWQ3k5R2tnT2t6UGsxU1h1U0g3VFlCNnoxVTRHYWNoTDhsb1laaTJZWT0tLUZMUm5sSVFBSU9qSWM1RUJvK1I3Z3c9PQ==--ad15ae7992b432b33743749d40318952415bd98f)](https://www.browserstack.com/automate/public-build/SFBWQ3k5R2tnT2t6UGsxU1h1U0g3VFlCNnoxVTRHYWNoTDhsb1laaTJZWT0tLUZMUm5sSVFBSU9qSWM1RUJvK1I3Z3c9PQ==--ad15ae7992b432b33743749d40318952415bd98f)
+1 -1
View File
@@ -25,7 +25,7 @@
### Redesign
* quo, Switcher Navigation by @Parveshdhull in https://github.com/status-im/status-mobile/pull/13167
* Quo2, Switcher Navigation by @Parveshdhull in https://github.com/status-im/status-mobile/pull/13167
* Switcher and Bottom Tabs Animations and UI Performance Improvements by @Parveshdhull in https://github.com/status-im/status-mobile/pull/13470
* feat: add token tag component (#13599) by @J-Son89 in https://github.com/status-im/status-mobile/pull/13644
* [13565] icon-avatar component by @ibrkhalil in https://github.com/status-im/status-mobile/pull/13692
+1 -1
View File
@@ -1 +1 @@
2.32.0
1.23.0
+228 -94
View File
@@ -1,75 +1,128 @@
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
import com.android.build.OutputFile
import com.sun.org.apache.xalan.internal.xsltc.compiler.Copy
/**
* The react.gradle file registers a task for each build variant:
* - bundlePrJsAndAssets
* - bundleDebugJsAndAssets
* - bundleReleaseJsAndAssets
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* entryFile: "index.js",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node", "--max-old-space-size=8192"],
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
/*
* This is the configuration block to customize your React Native Android app.
* By default you don't need to apply any configuration, just uncomment the lines you need.
Enabling Hermes on x86 devices is crashing the app after a few reloads,
this flag can be used to disable Hermes while building app.
https://github.com/status-im/status-mobile/issues/14031
*/
react {
/* Folders */
// The root of your project, i.e. where "package.json" lives. Default is '..'
// root = file("../")
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
// reactNativeDir = file("../node_modules/react-native")
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
// codegenDir = file("../node_modules/@react-native/codegen")
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
// cliFile = file("../node_modules/react-native/cli.js")
/* Variants */
// The list of variants to that are debuggable. For those we're going to
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
// debuggableVariants = ["liteDebug", "prodDebug"]
def disableHermes = System.getenv('DISABLE_HERMES') == 'true'
/* Bundling */
// A list containing the node command and its flags. Default is just 'node'.
nodeExecutableAndArgs = ["node", "--max-old-space-size=16384" ]
//
// The command to run when bundling. By default is 'bundle'
// bundleCommand = "ram-bundle"
//
// The path to the CLI configuration file. Default is empty.
// bundleConfig = file(../rn-cli.config.js)
//
// The name of the generated asset file containing your JS bundle
// bundleAssetName = "MyApplication.android.bundle"
//
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
// entryFile = file("../js/MyApplication.android.js")
//
// A list of extra flags to pass to the 'bundle' commands.
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
// extraPackagerArgs = []
project.ext.react = [
nodeExecutableAndArgs: ["node", "--max-old-space-size=16384"],
entryFile: "index.js",
/* NOTE: Hermes engine is required for Android 64-bit builds running on 64 devices,
* to guard against a hang in the UI thread after invoking status-go.
* Also a clean and rebuild is required when changing this. */
enableHermes: !disableHermes,
/* Disable 'The first definition was here.' warnings */
hermesFlagsRelease: ["-w"],
/* FIXME: Workaround for crash caused by missing libhermes-executor-release.so.
* https://github.com/facebook/react-native/issues/32928 */
deleteDebugFilesForVariant: { false },
enableVmCleanup: false,
bundleInPr: true,
inputExcludes: ["android/**", "ios/**", "react-native/**", "src/**", "test/**"]
]
/* Hermes Commands */
// The hermes compiler command to run. By default it is 'hermesc'
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
//
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
// hermesFlags = ["-O", "-output-source-map"]
}
// NOTE: Uncomment if building RN from a fork
// configurations.all {
// exclude group: 'com.facebook.react', module: 'react-native'
// }
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = true
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore (JSC)
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
@@ -81,7 +134,15 @@ def jscFlavor = 'org.webkit:android-jsc:+'
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = hermesEnabled.toBoolean();
def enableHermes = project.ext.react.get("enableHermes", false);
/**
* Architectures to build native code for.
*/
def reactNativeArchitectures() {
def value = project.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}
def getCommitHash = { ->
if (project.hasProperty("commitHash")) {
@@ -107,7 +168,6 @@ def getVersionCode = { ->
def getVersionName = { ->
new ByteArrayOutputStream().withStream { stdOut ->
// TODO: probably not used, cleanup
if (project.hasProperty("releaseVersion")) {
return project.releaseVersion
}
@@ -137,31 +197,13 @@ def getEnvOrConfig = { varName ->
android {
ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
}
// Disable default lint checks to remove redundant lintVitalReportRelease task
lintOptions {
checkReleaseBuilds false
}
// https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
externalNativeBuild {
cmake {
// This version must match cmakeVersions inside nix/pkgs/android-sdk/compose.nix
version "3.22.1"
}
}
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
namespace "im.status.ethereum"
defaultConfig {
applicationId "im.status.ethereum"
minSdkVersion rootProject.ext.minSdkVersion
@@ -177,8 +219,70 @@ android {
abiFilters getEnvOrConfig('ANDROID_ABI_INCLUDE').split(";")
}
}
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
if (isNewArchitectureEnabled()) {
// We configure the NDK build only if you decide to opt-in for the New Architecture.
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-21",
"APP_STL=c++_shared",
"NDK_TOOLCHAIN_VERSION=clang",
"GENERATED_SRC_DIR=$buildDir/generated/source",
"PROJECT_BUILD_DIR=$buildDir",
"REACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
"REACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
"NODE_MODULES_DIR=$rootDir/../node_modules"
cFlags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
cppFlags "-std=c++17"
// Make sure this target name is the same you specify inside the
// src/main/jni/Android.mk file for the `LOCAL_MODULE` variable.
targets "rndiffapp_appmodules"
}
}
}
}
if (isNewArchitectureEnabled()) {
// We configure the NDK build only if you decide to opt-in for the New Architecture.
externalNativeBuild {
ndkBuild {
path "$projectDir/src/main/jni/Android.mk"
}
}
def reactAndroidProjectDir = project(':ReactAndroid').projectDir
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
into("$buildDir/react-ndk/exported")
}
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
into("$buildDir/react-ndk/exported")
}
afterEvaluate {
// If you wish to add a custom TurboModule or component locally,
// you should uncomment this line.
// preBuild.dependsOn("generateCodegenArtifactsFromSchema")
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
// Due to a bug inside AGP, we have to explicitly set a dependency
// between configureNdkBuild* tasks and the preBuild tasks.
// This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
configureNdkBuildRelease.dependsOn(preReleaseBuild)
configureNdkBuildDebug.dependsOn(preDebugBuild)
reactNativeArchitectures().each { architecture ->
tasks.findByName("configureNdkBuildDebug[${architecture}]")?.configure {
dependsOn("preDebugBuild")
}
tasks.findByName("configureNdkBuildRelease[${architecture}]")?.configure {
dependsOn("preReleaseBuild")
}
}
}
}
/**
* Arbitrary project metadata
* https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
@@ -210,12 +314,16 @@ android {
doNotStrip '*/mips/*.so'
doNotStrip '*/mips64/*.so'
}
dexOptions {
jumboMode true
javaMaxHeapSize "8g"
}
splits {
abi {
reset()
enable getEnvOrConfig('ANDROID_ABI_SPLIT').toBoolean()
include getEnvOrConfig('ANDROID_ABI_INCLUDE').split(";")
universalApk getEnvOrConfig('ORG_GRADLE_PROJECT_universalApk').toBoolean()
universalApk true
}
}
signingConfigs {
@@ -236,7 +344,6 @@ android {
}
release {
minifyEnabled enableProguardInReleaseBuilds
shrinkResources enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
signingConfig null
}
@@ -244,13 +351,12 @@ android {
initWith release
applicationIdSuffix ".pr"
versionNameSuffix ".pr"
debuggable false
debuggable false
matchingFallbacks = ["release"]
// necessary to make react-native-config's code generation work
resValue "string", "build_config_package", "im.status.ethereum"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
@@ -266,7 +372,6 @@ android {
}
}
aaptOptions {
// disable PNG optimization as for some reason it cannot be trusted to provide deterministic output (see https://f-droid.org/en/docs/Reproducible_Builds/)
cruncherEnabled = false
@@ -278,33 +383,54 @@ 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")
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+" // From node_modules
implementation 'com.facebook.soloader:soloader:0.10.3+'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation "androidx.core:core-splashscreen:1.0.0"
if (enableHermes) {
implementation("com.facebook.react:hermes-android")
} else {
// https://github.com/status-im/status-mobile/issues/18493
// we don't use hermes for debug builds because it crashes too often
implementation(jscFlavor)
//noinspection GradleDynamicVersion
implementation("com.facebook.react:hermes-engine:+") { // From node_modules
exclude group: 'com.facebook.fbjni' }
} 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' // only needed if minSdkVersion is less than 21 (https://developer.android.com/studio/build/multidex)
implementation project(':react-native-dialogs')
implementation project(':react-native-blur')
// Force using exact RN version instead of relying on gradle dependency resolution
// https://docs.gradle.org/current/userguide/introduction_dependency_management.html#sec:dependency_resolution
// NOTE: Uncomment if building RN from a fork
//compile ("com.facebook.react:react-native:0.55.4") { force = true } // From node_modules
implementation project(':react-native-status')
implementation project(':react-native-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.11.0")
implementation("com.google.prefab:cli:2.0.0")
implementation("com.android.tools.build:aapt2:8.1.1-10154469")
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"
}
if (isNewArchitectureEnabled()) {
// If new architecture is enabled, we let you build RN from source
// Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
// This will be applied to all the imported transtitive dependency.
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("com.facebook.react:react-native"))
.using(project(":ReactAndroid"))
.because("On New Architecture we're building React Native from source")
substitute(module("com.facebook.react:hermes-engine"))
.using(project(":ReactAndroid:hermes-engine"))
.because("On New Architecture we're building Hermes from source")
}
}
}
def getLocalNDKDir = { ->
def rootDir = project.rootDir
@@ -339,3 +465,11 @@ task hemroidBuild(type: Exec) {
preBuild.dependsOn hemroidBuild
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
def isNewArchitectureEnabled() {
// To opt-in for the New Architecture, you can either:
// - Set `newArchEnabled` to true inside the `gradle.properties` file
// - Invoke gradle with `-newArchEnabled=true`
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}
+1 -13
View File
@@ -58,9 +58,6 @@
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# to fix : java.security.KeyStoreException: BKS not found
-keep class org.bouncycastle.** { *; }
# okio
-keep class sun.misc.Unsafe { *; }
@@ -78,13 +75,4 @@
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# react-native-config
# https://github.com/lugg/react-native-config?tab=readme-ov-file#problems-with-proguard
-keep class im.status.ethereum.BuildConfig {*;}
# react-native-navigation
# to fix : java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
# at com.reactnativenavigation.views.element.animators.PropertyAnimatorCreator.getChildClass(Unknown Source:13)
-keep class com.reactnativenavigation.** {*;}
}
+4 -2
View File
@@ -3,9 +3,11 @@
xmlns:tools="http://schemas.android.com/tools">
<!-- These are added by React Native for debug mode, but actually aren't needed in release mode -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<!-- Remove licensing permission since we don't license our app and it blocks F-Droid submissions. -->
<uses-permission tools:node="remove" android:name="com.android.vending.CHECK_LICENSE"/>
<application tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" android:usesCleartextTraffic="true" />
<application tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" android:usesCleartextTraffic="true" >
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false" />
</application>
</manifest>
+10 -47
View File
@@ -1,17 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
<queries>
<intent>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<data android:mimeType="*/*" />
</intent>
</queries>
android:installLocation="auto"
package="im.status.ethereum">
<!-- non-dangerous permissions -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -24,11 +17,11 @@
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
@@ -36,13 +29,11 @@
android:allowBackup="false"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.AppSplash"
android:name=".MainApplication"
android:largeHeap="true"
android:usesCleartextTraffic="true"
android:extractNativeLibs="true"
android:requestLegacyExternalStorage="true">
android:extractNativeLibs="true">
<!-- After upgrading Android Gradle Plugin to 4.2.0 and above we must get rid of `extractNativeLibs="true"`
and use`useLegacyPackaging` flag in our app's `build.gradle`-->
<meta-data android:name="commitHash" android:value="${commitHash}"/>
@@ -71,47 +62,19 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Handles http and https URLs for status.app -->
<data android:scheme="http" android:host="status.app" />
<data android:scheme="https" android:host="status.app" />
<!-- Community paths -->
<data android:pathPattern="/c/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/c/.*" android:host="status.app" android:scheme="https" />
<!-- Community channel paths -->
<data android:pathPattern="/cc/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/cc/.*" android:host="status.app" android:scheme="https" />
<!-- User paths -->
<data android:pathPattern="/u/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/u/.*" android:host="status.app" android:scheme="https" />
<!-- Private chat paths -->
<data android:pathPattern="/p/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/p/.*" android:host="status.app" android:scheme="https" />
<!-- Community request paths -->
<data android:pathPattern="/cr/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/cr/.*" android:host="status.app" android:scheme="https" />
<!-- Group chat paths -->
<data android:pathPattern="/g/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/g/.*" android:host="status.app" android:scheme="https" />
<!-- Wallet paths -->
<data android:pathPattern="/wallet/.*" android:host="status.app" android:scheme="http" />
<data android:pathPattern="/wallet/.*" android:host="status.app" android:scheme="https" />
<data android:scheme="http" android:host="join.status.im" />
<data android:scheme="https" android:host="join.status.im" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="status-app" />
<data android:scheme="status-im" />
<data android:scheme="ethereum" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
<service
android:name="im.status.ethereum.pushnotifications.ForegroundService"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="local notifications"/>
</service>
<service android:name="im.status.ethereum.pushnotifications.ForegroundService"></service>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
@@ -0,0 +1,260 @@
package im.status.ethereum;
import android.content.Context;
import android.annotation.TargetApi;
import androidx.annotation.Nullable;
import android.app.AlertDialog;
import android.app.ActivityManager;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Looper;
import android.preference.PreferenceManager;
import androidx.core.app.ActivityCompat;
import android.util.Log;
import android.view.WindowManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.provider.Settings;
import android.os.Bundle;
import android.os.Handler;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
import com.reactnativenavigation.NavigationActivity;
import com.facebook.react.modules.core.PermissionListener;
import androidx.core.splashscreen.SplashScreen;
import com.facebook.react.ReactActivity;
import java.util.Properties;
import im.status.ethereum.module.StatusThreadPoolExecutor;
import im.status.ethereum.MainApplication;
public class MainActivity extends NavigationActivity
implements ActivityCompat.OnRequestPermissionsResultCallback{
@Nullable private PermissionListener mPermissionListener;
private boolean keepSplash = true;
private final int SPLASH_DELAY = 3200;
private static void registerUncaughtExceptionHandler(final Context context) {
final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, final Throwable t) {
// High priority, so don't use StatusThreadPoolExecutor
new Thread() {
@Override
public void run() {
Looper.prepare();
new AlertDialog.Builder(context)
.setTitle("Error")
.setMessage(t.toString())
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int id) {
dialog.dismiss();
defaultUncaughtExceptionHandler.uncaughtException(thread, t);
}
}).show();
Looper.loop();
}
}.start();
}
});
}
private ActivityManager getActivityManager() {
return (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
}
private ActivityManager.MemoryInfo getAvailableMemory(final ActivityManager activityManager) {
final ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
protected void configureStatus() {
// Required because of crazy APN settings redirecting localhost (found in GB)
Properties properties = System.getProperties();
properties.setProperty("http.nonProxyHosts", "localhost|127.0.0.1");
properties.setProperty("https.nonProxyHosts", "localhost|127.0.0.1");
}
private Intent createNotificationSettingsIntent() {
final Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
} else {
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
}
return intent;
}
private void tryToEmit(String eventName, WritableMap event) {
try {
((MainApplication) getApplication()).getReactNativeHost()
.getReactInstanceManager()
.getCurrentReactContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("url", event);
} catch(Exception e) {/* we expect NPE on first start, which is OK because we have a fallback */}
}
@Override
public void onNewIntent(final Intent intent) {
super.onNewIntent(intent);
if (intent.getDataString() != null && intent.getData().getScheme().startsWith("app-settings")) {
startActivity(createNotificationSettingsIntent());
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
setTheme(R.style.DarkTheme);
// Make sure we get an Alert for every uncaught exceptions
registerUncaughtExceptionHandler(MainActivity.this);
// Report memory details for this application
final ActivityManager activityManager = getActivityManager();
Log.v("RNBootstrap", "Available system memory "+getAvailableMemory(activityManager).availMem + ", maximum usable application memory " + activityManager.getLargeMemoryClass()+"M");
setSecureFlag();
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
super.onCreate(null);
if (!shouldShowRootedNotification()) {
configureStatus();
} else {
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
.setMessage(getResources().getString(R.string.root_warning))
.setPositiveButton(getResources().getString(R.string.root_okay), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
rejectRootedNotification();
dialog.dismiss();
configureStatus();
}
})
.setNegativeButton(getResources().getString(R.string.root_cancel), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
MainActivity.this.finishAffinity();
}
})
.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
dialog.dismiss();
MainActivity.this.finishAffinity();
}
})
.create();
dialog.show();
}
Runnable r = new Runnable() {
@Override
public void run() {
System.loadLibrary("status-logs");
// when app is started but the Activity has been destroyed, the deep linking url event is
// not emitted when coming back to foreground. This is a workaround. If the problem is
// resolved in react-native this code should be removed
if (getIntent().getData() != null) {
WritableMap event = Arguments.createMap();
event.putString("url", getIntent().getDataString());
// on first start emit will (silently) fail, but the regular deep linking handler will work
tryToEmit("url", event);
}
}
};
splashScreen.setKeepOnScreenCondition(() -> keepSplash);
Handler handler = new Handler();
handler.postDelayed(() -> keepSplash = false, SPLASH_DELAY);
StatusThreadPoolExecutor.getInstance().execute(r);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
this.sendBroadcast(intent);
}
private static final String REJECTED_ROOTED_NOTIFICATION = "rejectedRootedNotification";
private static final Integer FREQUENCY_OF_REMINDER_IN_PERCENT = 5;
private boolean shouldShowRootedNotification() {
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
if (userRejectedRootedNotification()) {
return ((Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT);
} else return true;
} else {
return false;
}
}
private boolean userRejectedRootedNotification() {
SharedPreferences preferences = getPreferences(0);
return preferences.getBoolean(REJECTED_ROOTED_NOTIFICATION, false);
}
private void rejectRootedNotification() {
SharedPreferences preferences = getPreferences(0);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(REJECTED_ROOTED_NOTIFICATION, true);
editor.commit();
}
private void setSecureFlag() {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
final boolean setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
@TargetApi(Build.VERSION_CODES.M)
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
mPermissionListener = listener;
requestPermissions(permissions, requestCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null;
}
}
}
@@ -1,236 +0,0 @@
package im.status.ethereum
import android.annotation.TargetApi
import android.app.ActivityManager
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.preference.PreferenceManager
import android.provider.Settings
import android.util.Log
import android.view.WindowManager
import androidx.annotation.Nullable
import androidx.core.app.ActivityCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
import com.facebook.react.defaults.DefaultReactActivityDelegate
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.facebook.react.modules.core.PermissionListener
import com.reactnativenavigation.NavigationActivity
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView
import im.status.ethereum.MainApplication
import im.status.ethereum.module.StatusThreadPoolExecutor
import java.util.Properties
class MainActivity : NavigationActivity(), ActivityCompat.OnRequestPermissionsResultCallback {
@Nullable
private var mPermissionListener: PermissionListener? = null
private var keepSplash = true
private val SPLASH_DELAY = 3200
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
protected fun getMainComponentName(): String {
return "StatusIm"
}
private fun registerUncaughtExceptionHandler(context: Context) {
val defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
// High priority, so don't use StatusThreadPoolExecutor
Thread.setDefaultUncaughtExceptionHandler { thread, t ->
Thread {
Looper.prepare()
AlertDialog.Builder(context)
.setTitle("Error")
.setMessage(t.toString())
.setNegativeButton("Exit") { dialog, id ->
dialog.dismiss()
defaultUncaughtExceptionHandler.uncaughtException(thread, t)
}.show()
Looper.loop()
}.start()
}
}
private fun getActivityManager(): ActivityManager {
return getSystemService(ACTIVITY_SERVICE) as ActivityManager
}
private fun getAvailableMemory(activityManager: ActivityManager): ActivityManager.MemoryInfo {
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
return memoryInfo
}
protected fun configureStatus() {
// Required because of crazy APN settings redirecting localhost (found in GB)
val properties = System.getProperties()
properties.setProperty("http.nonProxyHosts", "localhost|127.0.0.1")
properties.setProperty("https.nonProxyHosts", "localhost|127.0.0.1")
}
private fun createNotificationSettingsIntent(): Intent {
val intent = Intent()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
} else {
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.data = Uri.parse("package:$packageName")
}
return intent
}
private fun tryToEmit(eventName: String, event: WritableMap) {
try {
(getApplication() as MainApplication).reactNativeHost
.getReactInstanceManager()
.getCurrentReactContext()
?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
?.emit("url", event)
} catch (e: Exception) { // we expect NPE on first start, which is OK because we have a fallback
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
if (intent.dataString != null && intent.data!!.scheme!!.startsWith("app-settings")) {
startActivity(createNotificationSettingsIntent())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen();
setTheme(R.style.DarkTheme)
// Make sure we get an Alert for every uncaught exceptions
registerUncaughtExceptionHandler(this)
// Report memory details for this application
val activityManager = getActivityManager()
Log.v("RNBootstrap", "Available system memory " + getAvailableMemory(activityManager).availMem + ", maximum usable application memory " + activityManager.largeMemoryClass + "M")
setSecureFlag()
// NOTE: Try to not restore the state https://github.com/software-mansion/react-native-screens/issues/17
super.onCreate(null)
if (!shouldShowRootedNotification()) {
configureStatus()
} else {
val dialog = AlertDialog.Builder(this)
.setMessage(resources.getString(R.string.root_warning))
.setPositiveButton(resources.getString(R.string.root_okay)) { dialog, which ->
rejectRootedNotification()
dialog.dismiss()
configureStatus()
}
.setNegativeButton(resources.getString(R.string.root_cancel)) { dialog, which ->
dialog.dismiss()
finishAffinity()
}
.setOnCancelListener {
it.dismiss()
finishAffinity()
}
.create()
dialog.show()
}
val r = Runnable {
System.loadLibrary("status-logs")
// when app is started but the Activity has been destroyed, the deep linking url event is
// not emitted when coming back to foreground. This is a workaround. If the problem is
// resolved in react-native this code should be removed
if (intent.data != null) {
val event = Arguments.createMap()
event.putString("url", intent.dataString)
// on first start emit will (silently) fail, but the regular deep linking handler will work
tryToEmit("url", event)
}
}
splashScreen.setKeepOnScreenCondition { keepSplash }
val handler = Handler()
handler.postDelayed({ keepSplash = false }, SPLASH_DELAY.toLong())
StatusThreadPoolExecutor.getInstance().execute(r)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val intent = Intent("onConfigurationChanged")
intent.putExtra("newConfig", newConfig)
sendBroadcast(intent)
}
private val REJECTED_ROOTED_NOTIFICATION = "rejectedRootedNotification"
private val FREQUENCY_OF_REMINDER_IN_PERCENT = 5
private fun shouldShowRootedNotification(): Boolean {
if (RootUtil.isDeviceRooted() && BuildConfig.ENABLE_ROOT_ALERT == "1") {
return if (userRejectedRootedNotification()) {
(Math.random() * 100) < FREQUENCY_OF_REMINDER_IN_PERCENT
} else true
} else {
return false
}
}
private fun userRejectedRootedNotification(): Boolean {
val preferences = getPreferences(0)
return preferences.getBoolean(REJECTED_ROOTED_NOTIFICATION, false)
}
private fun rejectRootedNotification() {
val preferences = getPreferences(0)
val editor = preferences.edit()
editor.putBoolean(REJECTED_ROOTED_NOTIFICATION, true)
editor.commit()
}
private fun setSecureFlag() {
val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this)
val setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && setSecure) {
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
}
@TargetApi(Build.VERSION_CODES.M)
override fun requestPermissions(permissions: Array<String>, requestCode: Int, listener: PermissionListener) {
mPermissionListener = listener
super.requestPermissions(permissions, requestCode)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (mPermissionListener != null && mPermissionListener!!.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
mPermissionListener = null
}
}
}
@@ -0,0 +1,87 @@
package im.status.ethereum;
import androidx.multidex.MultiDexApplication;
import android.content.Context;
import android.webkit.WebView;
import im.status.ethereum.newarchitecture.MainApplicationReactNativeHost;
import java.lang.reflect.InvocationTargetException;
import com.facebook.react.PackageList;
import com.aakashns.reactnativedialogs.ReactNativeDialogsPackage;
import com.facebook.react.ReactApplication;
import cl.json.RNSharePackage;
import com.facebook.react.ReactNativeHost;
import com.reactnativenavigation.NavigationApplication;
import com.reactnativenavigation.react.NavigationReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.modules.network.OkHttpClientProvider;
import com.reactnativecommunity.blurview.BlurViewPackage;
import java.util.List;
import im.status.ethereum.keycard.RNStatusKeycardPackage;
import im.status.ethereum.module.StatusPackage;
import im.status.ethereum.pushnotifications.PushNotificationPackage;
import im.status.ethereum.StatusOkHttpClientFactory;
import com.facebook.react.bridge.JSIModulePackage;
import com.swmansion.reanimated.ReanimatedJSIModulePackage;
public class MainApplication extends NavigationApplication {
private final ReactNativeHost mReactNativeHost = new NavigationReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
StatusPackage statusPackage = new StatusPackage(RootUtil.isDeviceRooted());
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(statusPackage);
packages.add(new ReactNativeDialogsPackage());
packages.add(new RNStatusKeycardPackage());
packages.add(new PushNotificationPackage());
packages.add(new BlurViewPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new ReanimatedJSIModulePackage();
}
};
private final ReactNativeHost mNewArchitectureNativeHost = new MainApplicationReactNativeHost(this);
@Override
public ReactNativeHost getReactNativeHost() {
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
return mNewArchitectureNativeHost;
} else {
return mReactNativeHost;
}
}
@Override
public void onCreate() {
super.onCreate();
// If you opted-in for the New Architecture, we enable the TurboModule system
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
OkHttpClientProvider.setOkHttpClientFactory(new StatusOkHttpClientFactory());
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG_WEBVIEW == "1");
}
}
@@ -1,59 +0,0 @@
package im.status.ethereum
import android.webkit.WebView
import androidx.multidex.MultiDexApplication
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.JSIModulePackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
import com.facebook.react.modules.network.OkHttpClientProvider
import com.reactnativenavigation.NavigationApplication
import com.reactnativenavigation.react.NavigationReactNativeHost
import cl.json.RNSharePackage
import com.reactnativecommunity.blurview.BlurViewPackage
import im.status.ethereum.keycard.RNStatusKeycardPackage
import im.status.ethereum.module.StatusPackage
import im.status.ethereum.pushnotifications.PushNotificationPackage
import im.status.ethereum.StatusOkHttpClientFactory
class MainApplication : NavigationApplication() {
private val mReactNativeHost = object : NavigationReactNativeHost(this) {
override fun getUseDeveloperSupport(): Boolean {
return BuildConfig.DEBUG
}
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here
add(StatusPackage(RootUtil.isDeviceRooted()))
add(RNStatusKeycardPackage())
add(PushNotificationPackage())
add(BlurViewPackage())
}
override fun getJSMainModuleName(): String = "index"
override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
}
override val reactNativeHost: ReactNativeHost
get() = mReactNativeHost
override fun onCreate() {
super.onCreate()
OkHttpClientProvider.setOkHttpClientFactory(StatusOkHttpClientFactory())
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG_WEBVIEW == "1")
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
DefaultNewArchitectureEntryPoint.load()
}
}
}
@@ -0,0 +1,40 @@
package im.status.ethereum;
import java.io.File;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/** @author Kevin Kowalewski */
public class RootUtil {
public static boolean isDeviceRooted() {
return checkRootMethod1() || checkRootMethod2() || checkRootMethod3();
}
private static boolean checkRootMethod1() {
String buildTags = android.os.Build.TAGS;
return buildTags != null && buildTags.contains("test-keys");
}
private static boolean checkRootMethod2() {
String[] paths = { "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su",
"/system/bin/failsafe/su", "/data/local/su" };
for (String path : paths) {
if (new File(path).exists()) return true;
}
return false;
}
private static boolean checkRootMethod3() {
Process process = null;
try {
process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
return in.readLine() != null;
} catch (Throwable t) {
return false;
} finally {
if (process != null) process.destroy();
}
}
}
@@ -1,42 +0,0 @@
package im.status.ethereum
import android.os.Build
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
object RootUtil {
fun isDeviceRooted(): Boolean =
checkRootMethod1() || checkRootMethod2() || checkRootMethod3()
private fun checkRootMethod1(): Boolean =
Build.TAGS?.contains("test-keys") ?: false
private fun checkRootMethod2(): Boolean {
val paths = arrayOf(
"/system/app/Superuser.apk",
"/sbin/su",
"/system/bin/su",
"/system/xbin/su",
"/data/local/xbin/su",
"/data/local/bin/su",
"/system/sd/xbin/su",
"/system/bin/failsafe/su",
"/data/local/su"
)
return paths.any { File(it).exists() }
}
private fun checkRootMethod3(): Boolean {
var process: Process? = null
return try {
process = Runtime.getRuntime().exec(arrayOf("/system/xbin/which", "su"))
BufferedReader(InputStreamReader(process.inputStream)).readLine() != null
} catch (t: Throwable) {
false
} finally {
process?.destroy()
}
}
}
@@ -1,88 +0,0 @@
package im.status.ethereum
import android.util.Log
import com.facebook.react.modules.network.OkHttpClientFactory
import com.facebook.react.modules.network.OkHttpClientProvider
import okhttp3.OkHttpClient
import okhttp3.tls.HandshakeCertificates
import java.io.ByteArrayInputStream
import java.lang.RuntimeException
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.security.cert.CertificateFactory
import java.security.cert.X509Certificate
import im.status.ethereum.module.StatusPackage
class StatusOkHttpClientFactory : OkHttpClientFactory {
companion object {
private const val TAG = "StatusOkHttpClientFactory"
private const val SLEEP_DURATION = 500L // milliseconds
}
override fun createNewNetworkModuleClient(): OkHttpClient? {
val certPem = getCertificatePem().takeIf { it.isNotEmpty() }
?: return logAndReturnNull("Certificate is empty, cannot create OkHttpClient without a valid certificate")
val cert = try {
induceSleep()
// Convert PEM certificate string to X509Certificate object
CertificateFactory.getInstance("X.509")
.generateCertificate(ByteArrayInputStream(certPem.toByteArray())) as? X509Certificate
?: return logAndReturnNull("Certificate could not be parsed as non-null")
} catch (e: Exception) {
return logAndReturnNull("Could not parse certificate", e)
}
val clientCertificates = try {
induceSleep()
// Create HandshakeCertificates object with our certificate
HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.addTrustedCertificate(cert)
.build()
} catch (e: Exception) {
return logAndReturnNull("Could not build HandshakeCertificates", e)
}
return try {
OkHttpClientProvider.createClientBuilder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
.build()
} catch (e: Exception) {
logAndReturnNull("Could not create OkHttpClient", e)
}
}
private fun getCertificatePem(): String {
return try {
// Create OkHttpClient with custom SSL socket factory and trust manager
StatusPackage.getImageTLSCert().takeIf { !it.isNullOrBlank() }
?: logAndReturnEmpty("Certificate PEM string is null or empty")
} catch (e: Exception) {
logAndReturnEmpty("Could not getImageTLSCert", e)
}
}
private fun induceSleep() {
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices with
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(SLEEP_DURATION)
} catch (e: InterruptedException) {
Log.e(TAG, "Sleep interrupted", e)
}
}
private fun logAndReturnNull(message: String, e: Exception? = null): Nothing? {
Log.e(TAG, message, e)
return null
}
private fun logAndReturnEmpty(message: String, e: Exception? = null): String {
Log.e(TAG, message, e)
return ""
}
}
@@ -0,0 +1,77 @@
package im.status.ethereum;
import android.util.Log;
import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientProvider;
import okhttp3.OkHttpClient;
import okhttp3.Interceptor;
import okhttp3.tls.HandshakeCertificates;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.RuntimeException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import im.status.ethereum.module.StatusPackage;
class StatusOkHttpClientFactory implements OkHttpClientFactory {
private static final String TAG = "StatusOkHttpClientFactory";
public OkHttpClient createNewNetworkModuleClient() {
X509Certificate cert = null;
HandshakeCertificates clientCertificates;
String certPem = "";
// Get TLS PEM certificate from status-go
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices with
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(500);
certPem = StatusPackage.getImageTLSCert();
} catch(Exception e) {
Log.e(TAG, "Could not getImageTLSCert",e);
}
// Convert PEM certificate string to X509Certificate object
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(500);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certPem.getBytes()));
} catch(Exception e) {
Log.e(TAG, "Could not parse certificate",e);
}
// Create HandshakeCertificates object with our certificate
try {
// induce half second sleep because sometimes a cert is not immediately available
// TODO : remove sleep if App no longer crashes on Android 10 devices
// java.lang.RuntimeException: Could not invoke WebSocketModule.connect
Thread.sleep(500);
clientCertificates = new HandshakeCertificates.Builder()
.addPlatformTrustedCertificates()
.addTrustedCertificate(cert)
.build();
} catch(Exception e) {
Log.e(TAG, "Could not build HandshakeCertificates", e);
return null;
}
// Create OkHttpClient with custom SSL socket factory and trust manager
try {
return OkHttpClientProvider.createClientBuilder()
.sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager())
.build();
} catch(Exception e) {
Log.e(TAG, "Could not create OkHttpClient", e);
return null;
}
}
}
@@ -0,0 +1,103 @@
package im.status.ethereum.newarchitecture;
import android.app.Application;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.JSIModulePackage;
import com.facebook.react.bridge.JSIModuleProvider;
import com.facebook.react.bridge.JSIModuleSpec;
import com.facebook.react.bridge.JSIModuleType;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.react.fabric.CoreComponentsRegistry;
import com.facebook.react.fabric.FabricJSIModuleProvider;
import com.facebook.react.fabric.ReactNativeConfig;
import com.facebook.react.uimanager.ViewManagerRegistry;
import im.status.ethereum.BuildConfig;
import im.status.ethereum.newarchitecture.components.MainComponentsRegistry;
import im.status.ethereum.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
* TurboModule delegates and the Fabric Renderer.
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
public class MainApplicationReactNativeHost extends ReactNativeHost {
public MainApplicationReactNativeHost(Application application) {
super(application);
}
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
// packages.add(new TurboReactPackage() { ... });
// If you have custom Fabric Components, their ViewManagers should also be loaded here
// inside a ReactPackage.
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
@NonNull
@Override
protected ReactPackageTurboModuleManagerDelegate.Builder
getReactPackageTurboModuleManagerDelegateBuilder() {
// Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
// for the new architecture and to use TurboModules correctly.
return new MainApplicationTurboModuleManagerDelegate.Builder();
}
@Override
protected JSIModulePackage getJSIModulePackage() {
return new JSIModulePackage() {
@Override
public List<JSIModuleSpec> getJSIModules(
final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) {
final List<JSIModuleSpec> specs = new ArrayList<>();
// Here we provide a new JSIModuleSpec that will be responsible of providing the
// custom Fabric Components.
specs.add(
new JSIModuleSpec() {
@Override
public JSIModuleType getJSIModuleType() {
return JSIModuleType.UIManager;
}
@Override
public JSIModuleProvider<UIManager> getJSIModuleProvider() {
final ComponentFactory componentFactory = new ComponentFactory();
CoreComponentsRegistry.register(componentFactory);
// Here we register a Components Registry.
// The one that is generated with the template contains no components
// and just provides you the one from React Native core.
MainComponentsRegistry.register(componentFactory);
final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
ViewManagerRegistry viewManagerRegistry =
new ViewManagerRegistry(
reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
return new FabricJSIModuleProvider(
reactApplicationContext,
componentFactory,
ReactNativeConfig.DEFAULT_CONFIG,
viewManagerRegistry);
}
});
return specs;
}
};
}
}
@@ -0,0 +1,30 @@
package im.status.ethereum.newarchitecture.components;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.soloader.SoLoader;
/**
* Class responsible to load the custom Fabric Components. This class has native methods and needs a
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
* folder for you).
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
@DoNotStrip
public class MainComponentsRegistry {
static {
SoLoader.loadLibrary("fabricjni");
}
@DoNotStrip private final HybridData mHybridData;
@DoNotStrip
private native HybridData initHybrid(ComponentFactory componentFactory);
@DoNotStrip
private MainComponentsRegistry(ComponentFactory componentFactory) {
mHybridData = initHybrid(componentFactory);
}
@DoNotStrip
public static MainComponentsRegistry register(ComponentFactory componentFactory) {
return new MainComponentsRegistry(componentFactory);
}
}
@@ -0,0 +1,40 @@
package im.status.ethereum.newarchitecture.modules;
import com.facebook.jni.HybridData;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.soloader.SoLoader;
import java.util.List;
/**
* Class responsible to load the TurboModules. This class has native methods and needs a
* corresponding C++ implementation/header file to work correctly (already placed inside the jni/
* folder for you).
*
* <p>Please note that this class is used ONLY if you opt-in for the New Architecture (see the
* `newArchEnabled` property). Is ignored otherwise.
*/
public class MainApplicationTurboModuleManagerDelegate
extends ReactPackageTurboModuleManagerDelegate {
private static volatile boolean sIsSoLibraryLoaded;
protected MainApplicationTurboModuleManagerDelegate(
ReactApplicationContext reactApplicationContext, List<ReactPackage> packages) {
super(reactApplicationContext, packages);
}
protected native HybridData initHybrid();
native boolean canCreateTurboModule(String moduleName);
public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
protected MainApplicationTurboModuleManagerDelegate build(
ReactApplicationContext context, List<ReactPackage> packages) {
return new MainApplicationTurboModuleManagerDelegate(context, packages);
}
}
@Override
protected synchronized void maybeLoadOtherSoLibraries() {
if (!sIsSoLibraryLoaded) {
// If you change the name of your application .so file in the Android.mk file,
// make sure you update the name here as well.
SoLoader.loadLibrary("status-im_appmodules");
sIsSoLibraryLoaded = true;
}
}
}
+39
View File
@@ -0,0 +1,39 @@
THIS_DIR := $(call my-dir)
include $(REACT_ANDROID_DIR)/Android-prebuilt.mk
# If you wish to add a custom TurboModule or Fabric component in your app you
# will have to include the following autogenerated makefile.
# include $(GENERATED_SRC_DIR)/codegen/jni/Android.mk
include $(CLEAR_VARS)
LOCAL_PATH := $(THIS_DIR)
# You can customize the name of your application .so file here.
LOCAL_MODULE := rndiffapp_appmodules
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
# If you wish to add a custom TurboModule or Fabric component in your app you
# will have to uncomment those lines to include the generated source
# files from the codegen (placed in $(GENERATED_SRC_DIR)/codegen/jni)
#
# LOCAL_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
# LOCAL_SRC_FILES += $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
# LOCAL_EXPORT_C_INCLUDES += $(GENERATED_SRC_DIR)/codegen/jni
# Here you should add any native library you wish to depend on.
LOCAL_SHARED_LIBRARIES := \
libfabricjni \
libfbjni \
libfolly_runtime \
libglog \
libjsi \
libreact_codegen_rncore \
libreact_debug \
libreact_nativemodule_core \
libreact_render_componentregistry \
libreact_render_core \
libreact_render_debug \
libreact_render_graphics \
librrc_view \
libruntimeexecutor \
libturbomodulejsijni \
libyoga
LOCAL_CFLAGS := -DLOG_TAG=\"ReactNative\" -fexceptions -frtti -std=c++17 -Wall
include $(BUILD_SHARED_LIBRARY)
@@ -0,0 +1,20 @@
#include "MainApplicationModuleProvider.h"
#include <rncore.h>
namespace facebook {
namespace react {
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
const std::string moduleName,
const JavaTurboModule::InitParams &params) {
// Here you can provide your own module provider for TurboModules coming from
// either your application or from external libraries. The approach to follow
// is similar to the following (for a library called `samplelibrary`:
//
// auto module = samplelibrary_ModuleProvider(moduleName, params);
// if (module != nullptr) {
// return module;
// }
// return rncore_ModuleProvider(moduleName, params);
return rncore_ModuleProvider(moduleName, params);
}
} // namespace react
} // namespace facebook
@@ -0,0 +1,11 @@
#pragma once
#include <memory>
#include <string>
#include <ReactCommon/JavaTurboModule.h>
namespace facebook {
namespace react {
std::shared_ptr<TurboModule> MainApplicationModuleProvider(
const std::string moduleName,
const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
@@ -0,0 +1,38 @@
#include "MainApplicationTurboModuleManagerDelegate.h"
#include "MainApplicationModuleProvider.h"
namespace facebook {
namespace react {
jni::local_ref<MainApplicationTurboModuleManagerDelegate::jhybriddata>
MainApplicationTurboModuleManagerDelegate::initHybrid(
jni::alias_ref<jhybridobject>) {
return makeCxxInstance();
}
void MainApplicationTurboModuleManagerDelegate::registerNatives() {
registerHybrid({
makeNativeMethod(
"initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
makeNativeMethod(
"canCreateTurboModule",
MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
});
}
std::shared_ptr<TurboModule>
MainApplicationTurboModuleManagerDelegate::getTurboModule(
const std::string name,
const std::shared_ptr<CallInvoker> jsInvoker) {
// Not implemented yet: provide pure-C++ NativeModules here.
return nullptr;
}
std::shared_ptr<TurboModule>
MainApplicationTurboModuleManagerDelegate::getTurboModule(
const std::string name,
const JavaTurboModule::InitParams &params) {
return MainApplicationModuleProvider(name, params);
}
bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
std::string name) {
return getTurboModule(name, nullptr) != nullptr ||
getTurboModule(name, {.moduleName = name}) != nullptr;
}
} // namespace react
} // namespace facebook
@@ -0,0 +1,30 @@
#include <memory>
#include <string>
#include <ReactCommon/TurboModuleManagerDelegate.h>
#include <fbjni/fbjni.h>
namespace facebook {
namespace react {
class MainApplicationTurboModuleManagerDelegate
: public jni::HybridClass<
MainApplicationTurboModuleManagerDelegate,
TurboModuleManagerDelegate> {
public:
// Adapt it to the package you used for your Java class.
static constexpr auto kJavaDescriptor =
"Lcom/rndiffapp/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;";
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject>);
static void registerNatives();
std::shared_ptr<TurboModule> getTurboModule(
const std::string name,
const std::shared_ptr<CallInvoker> jsInvoker) override;
std::shared_ptr<TurboModule> getTurboModule(
const std::string name,
const JavaTurboModule::InitParams &params) override;
/**
* Test-only method. Allows user to verify whether a TurboModule can be
* created by instances of this class.
*/
bool canCreateTurboModule(std::string name);
};
} // namespace react
} // namespace facebook
@@ -0,0 +1,48 @@
#include "MainComponentsRegistry.h"
#include <CoreComponentsRegistry.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/rncore/ComponentDescriptors.h>
namespace facebook {
namespace react {
MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
std::shared_ptr<ComponentDescriptorProviderRegistry const>
MainComponentsRegistry::sharedProviderRegistry() {
auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
// Custom Fabric Components go here. You can register custom
// components coming from your App or from 3rd party libraries here.
//
// providerRegistry->add(concreteComponentDescriptorProvider<
// AocViewerComponentDescriptor>());
return providerRegistry;
}
jni::local_ref<MainComponentsRegistry::jhybriddata>
MainComponentsRegistry::initHybrid(
jni::alias_ref<jclass>,
ComponentFactory *delegate) {
auto instance = makeCxxInstance(delegate);
auto buildRegistryFunction =
[](EventDispatcher::Weak const &eventDispatcher,
ContextContainer::Shared const &contextContainer)
-> ComponentDescriptorRegistry::Shared {
auto registry = MainComponentsRegistry::sharedProviderRegistry()
->createComponentDescriptorRegistry(
{eventDispatcher, contextContainer});
auto mutableRegistry =
std::const_pointer_cast<ComponentDescriptorRegistry>(registry);
mutableRegistry->setFallbackComponentDescriptor(
std::make_shared<UnimplementedNativeViewComponentDescriptor>(
ComponentDescriptorParameters{
eventDispatcher, contextContainer, nullptr}));
return registry;
};
delegate->buildRegistryFunction = buildRegistryFunction;
return instance;
}
void MainComponentsRegistry::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
});
}
} // namespace react
} // namespace facebook
@@ -0,0 +1,24 @@
#pragma once
#include <ComponentFactory.h>
#include <fbjni/fbjni.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
namespace facebook {
namespace react {
class MainComponentsRegistry
: public facebook::jni::HybridClass<MainComponentsRegistry> {
public:
// Adapt it to the package you used for your Java class.
constexpr static auto kJavaDescriptor =
"Lcom/rndiffapp/newarchitecture/components/MainComponentsRegistry;";
static void registerNatives();
MainComponentsRegistry(ComponentFactory *delegate);
private:
static std::shared_ptr<ComponentDescriptorProviderRegistry const>
sharedProviderRegistry();
static jni::local_ref<jhybriddata> initHybrid(
jni::alias_ref<jclass>,
ComponentFactory *delegate);
};
} // namespace react
} // namespace facebook
+10
View File
@@ -0,0 +1,10 @@
#include <fbjni/fbjni.h>
#include "MainApplicationTurboModuleManagerDelegate.h"
#include "MainComponentsRegistry.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return facebook::jni::initialize(vm, [] {
facebook::react::MainApplicationTurboModuleManagerDelegate::
registerNatives();
facebook::react::MainComponentsRegistry::registerNatives();
});
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 940 B

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 B

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 972 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 B

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 824 B

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 69 KiB

@@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_background"/>
<foreground android:drawable="@mipmap/ic_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon>
</adaptive-icon>
@@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_background"/>
<foreground android:drawable="@mipmap/ic_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
</adaptive-icon>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

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