Compare commits

..
Author SHA1 Message Date
Andrea Maria Piana 1e3b207c3b test 2023-11-20 15:55:27 +00:00
John Ngei f03671097b enable biometric when user signs in with syncing (#17627) 2023-11-17 15:23:36 +00:00
frank 1db63a9fa1 local pair: check netIPs if empty before find server cert 2023-11-17 11:26:54 +00:00
Lungu CristianandIbrkhalil cd92b41214 Composer collapsing when editing canceled/done (#17785)
* fix: composer height when entering and canceling edit

* fix: blur the composer input when canceling edit

* fix: focusing animation and composer height after blur

* fix: input height when canceling edit while unfocused

* ref: removed arbitrary keyboard check

* fix: moved edit-mentions logic to use-edit to fix unresolved mention

* fix: composer edit should put the cursor at the end

* fix: (potentially) fixing the mention not resolved during edit

* fix: emoji-kb handler changing the height when default kb appears

* Fix text content when editing and reentering chat

* prevent composer when focusing on opening chat with edit/reply

* clean

* Clauxx comments

* Apply for reply

* Lintil soup = yummy

* refactor variable name

* Extract the focusing logic from the data setting logic

* Edge case

* fix: composer mention key & edit re-enter issues

* fix: reply cancel input blur and smooth reply focus

---------

Co-authored-by: Ibrkhalil <vampirekid017@gmail.com>
2023-11-17 11:14:23 +00:00
Andrea Maria Piana 56f7206da7 Restore shards 2023-11-16 19:43:29 +00:00
Andrea Maria Piana eb5de3506a Revert changes in sharded keys 2023-11-16 19:11:20 +00:00
flexsurfer 22005f916e [#17854] [IOS] The tutorial video animation keeps playing after openi… (#17915)
(cherry picked from commit 7153e4da48)
2023-11-16 12:36:13 +01:00
Flavio Fraschetti ff50aacb3a Hide channel list at token-gated communities overview (#17901)
This commit hides the categorized channel list for token-gated communities overview.
2023-11-16 10:57:54 +00:00
Icaro Motta 91300b9ff8 Fix: unable to join token-gated communities (#17894)
Fixes the bug by explicitly passing all available addresses to be revealed
to wakuext_requestToJoinCommunity and picking up the first available address
as the airdrop address. This is a temporary solution while we work on the
feature to allow users to choose which addresses to expose.

Fixes https://github.com/status-im/status-mobile/issues/17861

*Areas that may be impacted*: join community flows.

    ----------------------------------------------------------------------
    Community "Request to join" option is enabled.
    User holds more than X ETH.
    Anyone who holds <X> ETH is allowed to Become member in <COMMUNITY>.
    
    Expected: request to join is received by desktop client and accepted,
    mobile user joins the community.
    ----------------------------------------------------------------------
    
    ----------------------------------------------------------------------
    Community "Request to join" option is enabled.
    User holds less than X ETH.
    Anyone who holds <X> ETH is allowed to View and post in <CHANNEL>.
    
    Expected: request to join is received by desktop client and accepted, mobile
    user joins the community, but can't post in <CHANNEL>.
    ----------------------------------------------------------------------
    
    ----------------------------------------------------------------------
    Community "Request to join" option is enabled.
    No token permissions.
    
    Expected: request to join is received by desktop client and accepted,
    mobile user joins the community.
    ----------------------------------------------------------------------
2023-11-15 06:46:55 -03:00
Andrea Maria Piana d93b20242a Point to shared release branch 2023-11-14 10:54:02 +00:00
Andrea Maria Piana 0a43e5c97a Bump release to 1.26.0 2023-11-14 10:52:00 +00:00
2924 changed files with 104220 additions and 111215 deletions
+143 -142
View File
@@ -1,55 +1,55 @@
legacy.status-im.utils.build/warning-handler status-im.utils.build/warning-handler
legacy.status-im.utils.build/get-current-sha status-im.utils.build/get-current-sha
status-im.constants/spacing-char status-im2.constants/spacing-char
status-im.constants/arg-wrapping-char status-im2.constants/arg-wrapping-char
legacy.status-im.ios.core/init status-im.ios.core/init
legacy.status-im.ui.components.camera/aspects status-im.ui.components.camera/aspects
legacy.status-im.ui.components.camera/capture-targets status-im.ui.components.camera/capture-targets
legacy.status-im.ui.components.camera/set-torch status-im.ui.components.camera/set-torch
legacy.status-im.ui.components.camera/request-access-ios status-im.ui.components.camera/request-access-ios
legacy.status-im.chat.models.message-content/stylings status-im.chat.models.message-content/stylings
legacy.status-im.chat.models.message-content/actions status-im.chat.models.message-content/actions
legacy.status-im.chat.models.message-content/blank-string status-im.chat.models.message-content/blank-string
legacy.status-im.chat.models.message-content/sorted-ranges status-im.chat.models.message-content/sorted-ranges
legacy.status-im.ethereum.mnemonic/words->passphrase status-im.ethereum.mnemonic/words->passphrase
native-module.core/listener native-module.core/listener
native-module.core/multiaccount-reset native-module.core/multiaccount-reset
native-module.core/extract-group-membership-signatures native-module.core/extract-group-membership-signatures
native-module.core/sign-group-membership native-module.core/sign-group-membership
native-module.core/update-mailservers native-module.core/update-mailservers
legacy.status-im.ethereum.abi-spec/bytes-to-hex status-im.ethereum.abi-spec/bytes-to-hex
legacy.status-im.android.core/init status-im.android.core/init
legacy.status-im.chat.models.message/transport-keys status-im.chat.models.message/transport-keys
legacy.status-im.utils.datetime/week status-im.utils.datetime/week
legacy.status-im.utils.datetime/time-ago status-im.utils.datetime/time-ago
legacy.status-im.utils.datetime/format-date status-im.utils.datetime/format-date
legacy.status-im.utils.datetime/get-ordinal-date status-im.utils.datetime/get-ordinal-date
reagent.dom/render reagent.dom/render
reagent.dom/unmount-component-at-node reagent.dom/unmount-component-at-node
reagent.dom/dom-node reagent.dom/dom-node
reagent.dom/force-update-all reagent.dom/force-update-all
legacy.status-im.multiaccounts.create.core/get-new-key-code status-im.multiaccounts.create.core/get-new-key-code
legacy.status-im.ethereum.decode/string status-im.ethereum.decode/string
legacy.status-im.ui.screens.network.views/mainnet? status-im.ui.screens.network.views/mainnet?
legacy.status-im.data-store.chats/event->string status-im.data-store.chats/event->string
legacy.status-im.mailserver.constants/seven-days status-im.mailserver.constants/seven-days
legacy.status-im.mailserver.constants/connection-timeout status-im.mailserver.constants/connection-timeout
legacy.status-im.hardwallet.card/install-applet status-im.hardwallet.card/install-applet
legacy.status-im.hardwallet.card/install-cash-applet status-im.hardwallet.card/install-cash-applet
legacy.status-im.multiaccount.login.data-test/all-contacts status-im.multiaccount.login.data-test/all-contacts
legacy.status-im.multiaccount.login.data-test/multiaccounts status-im.multiaccount.login.data-test/multiaccounts
legacy.status-im.multiaccount.login.data-test/get-chats status-im.multiaccount.login.data-test/get-chats
legacy.status-im.multiaccount.login.data-test/transport status-im.multiaccount.login.data-test/transport
legacy.status-im.multiaccount.login.data-test/topics status-im.multiaccount.login.data-test/topics
legacy.status-im.utils.utils/clear-timeout status-im.utils.utils/clear-timeout
legacy.status-im.utils.handlers/logged-in status-im.utils.handlers/logged-in
legacy.status-im.multiaccounts.model/credentials status-im.multiaccounts.model/credentials
legacy.status-im.multiaccounts.login.core/contract-fleet? status-im.multiaccounts.login.core/contract-fleet?
legacy.status-im.multiaccounts.login.core/fetch-nodes status-im.multiaccounts.login.core/fetch-nodes
status-im.config/rpc-networks-only? status-im2.config/rpc-networks-only?
status-im.config/waku-enabled? status-im2.config/waku-enabled?
legacy.status-im.utils.pairing/has-paired-installations? status-im.utils.pairing/has-paired-installations?
legacy.status-im.tribute-to-talk.core-test/user-cofx status-im.tribute-to-talk.core-test/user-cofx
mocks.js-dependencies/action-button mocks.js-dependencies/action-button
mocks.js-dependencies/camera mocks.js-dependencies/camera
mocks.js-dependencies/dismiss-keyboard mocks.js-dependencies/dismiss-keyboard
@@ -78,108 +78,109 @@ mocks.js-dependencies/react-navigation-bottom-tabs
mocks.js-dependencies/react-native-haptic-feedback mocks.js-dependencies/react-native-haptic-feedback
mocks.js-dependencies/mock mocks.js-dependencies/mock
quo.previews.main/init quo.previews.main/init
legacy.status-im.chat.models.message-list-test/descending-range status-im.chat.models.message-list-test/descending-range
legacy.status-im.chat.models.message-list-test/random-range status-im.chat.models.message-list-test/random-range
legacy.status-im.ethereum.eip165/supports? status-im.ethereum.eip165/supports?
legacy.status-im.utils.hex/valid-hex? status-im.utils.hex/valid-hex?
legacy.status-im.multiaccounts.core/chat-send? status-im.multiaccounts.core/chat-send?
legacy.status-im.hardwallet.simulated-keycard/install-cash-applet status-im.hardwallet.simulated-keycard/install-cash-applet
legacy.status-im.hardwallet.simulated-keycard/sign-typed-data status-im.hardwallet.simulated-keycard/sign-typed-data
legacy.status-im.utils.core/safe-read-message-content status-im.utils.core/safe-read-message-content
legacy.status-im.ui.components.react/native-modules status-im.ui.components.react/native-modules
legacy.status-im.ui.components.react/progress-bar status-im.ui.components.react/progress-bar
react-native.fs/move-file react-native.fs/move-file
react-native.fs/read-dir react-native.fs/read-dir
react-native.fs/mkdir react-native.fs/mkdir
react-native.fs/unlink react-native.fs/unlink
react-native.fs/file-exists? react-native.fs/file-exists?
legacy.status-im.ui.components.colors/white status-im.ui.components.colors/white
legacy.status-im.ui.components.colors/black status-im.ui.components.colors/black
legacy.status-im.ui.components.core/animated-header status-im.transport.core-test/messages
legacy.status-im.ui.components.core/safe-area-provider status-im.ui.components.core/animated-header
legacy.status-im.ui.components.core/safe-area-consumer status-im.ui.components.core/safe-area-provider
legacy.status-im.ui.components.core/safe-area-view status-im.ui.components.core/safe-area-consumer
legacy.status-im.utils.universal-links.core/open! status-im.ui.components.core/safe-area-view
legacy.status-im.transport.filters.core-test/member-2 status-im.utils.universal-links.core/open!
legacy.status-im.ui.screens.chat.ttt/one-to-one-chat-description-container status-im.transport.filters.core-test/member-2
legacy.status-im.ethereum.ens/ttl status-im.ui.screens.chat.ttt/one-to-one-chat-description-container
legacy.status-im.ethereum.ens/addr-hash status-im.ethereum.ens/ttl
legacy.status-im.ethereum.ens/name-hash status-im.ethereum.ens/addr-hash
legacy.status-im.ethereum.ens/ABI-hash status-im.ethereum.ens/name-hash
legacy.status-im.ethereum.ens/pubkey-hash status-im.ethereum.ens/ABI-hash
legacy.status-im.network.core/get-network status-im.ethereum.ens/pubkey-hash
status-im.constants/desktop-content-types status-im.network.core/get-network
status-im.constants/blocks-per-hour status-im2.constants/desktop-content-types
status-im.constants/one-earth-day status-im2.constants/blocks-per-hour
status-im.constants/left-pane-min-width status-im2.constants/one-earth-day
status-im.constants/system status-im2.constants/left-pane-min-width
status-im.constants/contact-discovery status-im2.constants/system
status-im.constants/send-transaction-failed-parse-response status-im2.constants/contact-discovery
status-im.constants/send-transaction-failed-parse-params status-im2.constants/send-transaction-failed-parse-response
status-im.constants/send-transaction-no-account-selected status-im2.constants/send-transaction-failed-parse-params
status-im.constants/send-transaction-invalid-tx-sender status-im2.constants/send-transaction-no-account-selected
status-im.constants/web3-get-logs status-im2.constants/send-transaction-invalid-tx-sender
status-im.constants/web3-transaction-receipt status-im2.constants/web3-get-logs
status-im.constants/web3-new-filter status-im2.constants/web3-transaction-receipt
status-im.constants/web3-new-pending-transaction-filter status-im2.constants/web3-new-filter
status-im.constants/web3-new-block-filter status-im2.constants/web3-new-pending-transaction-filter
status-im.constants/web3-uninstall-filter status-im2.constants/web3-new-block-filter
status-im.constants/web3-get-filter-changes status-im2.constants/web3-uninstall-filter
status-im.constants/web3-shh-post status-im2.constants/web3-get-filter-changes
status-im.constants/web3-shh-new-identity status-im2.constants/web3-shh-post
status-im.constants/web3-shh-has-identity status-im2.constants/web3-shh-new-identity
status-im.constants/web3-shh-new-group status-im2.constants/web3-shh-has-identity
status-im.constants/web3-shh-add-to-group status-im2.constants/web3-shh-new-group
status-im.constants/web3-shh-new-filter status-im2.constants/web3-shh-add-to-group
status-im.constants/web3-shh-uninstall-filter status-im2.constants/web3-shh-new-filter
status-im.constants/web3-shh-get-filter-changes status-im2.constants/web3-shh-uninstall-filter
status-im.constants/web3-shh-get-messages status-im2.constants/web3-shh-get-filter-changes
status-im.constants/status-create-address status-im2.constants/web3-shh-get-messages
status-im.constants/event-transfer-hash status-im2.constants/status-create-address
status-im.constants/regx-rtl-characters status-im2.constants/event-transfer-hash
status-im.constants/desktop-msg-chars-hard-limit status-im2.constants/regx-rtl-characters
status-im.constants/debug-metrics status-im2.constants/desktop-msg-chars-hard-limit
status-im.constants/scan-qr-code status-im2.constants/debug-metrics
status-im.constants/ipfs-proto-code status-im2.constants/scan-qr-code
status-im.constants/swarm-proto-code status-im2.constants/ipfs-proto-code
legacy.status-im.multiaccounts.update.publisher/publish-update! status-im2.constants/swarm-proto-code
legacy.status-im.utils.async/task-queue status-im.multiaccounts.update.publisher/publish-update!
legacy.status-im.utils.async/async-periodic-run! status-im.utils.async/task-queue
legacy.status-im.desktop.core/app-root status-im.utils.async/async-periodic-run!
legacy.status-im.desktop.core/init status-im.desktop.core/app-root
legacy.status-im.chat.models-test/test-db status-im.desktop.core/init
legacy.status-im.ui.components.spacing/padding-vertical status-im.chat.models-test/test-db
legacy.status-im.utils.money/percent-change status-im.ui.components.spacing/padding-vertical
status-im.utils.money/percent-change
utils.debounce/clear-all utils.debounce/clear-all
legacy.status-im.transport.db/create-chat status-im.transport.db/create-chat
legacy.status-im.utils.priority-map/priority-map status-im.utils.priority-map/priority-map
legacy.status-im.utils.priority-map/priority-map-by status-im.utils.priority-map/priority-map-by
legacy.status-im.utils.priority-map/priority-map-keyfn status-im.utils.priority-map/priority-map-keyfn
legacy.status-im.utils.priority-map/empty-message-map status-im.utils.priority-map/empty-message-map
legacy.status-im.wallet.choose-recipient.core/use-default-eth-gas status-im.wallet.choose-recipient.core/use-default-eth-gas
legacy.status-im.ui.components.animation/decay status-im.ui.components.animation/decay
legacy.status-im.ui.components.animation/remove-all-listeners status-im.ui.components.animation/remove-all-listeners
legacy.status-im.ui.components.animation/stop-animation status-im.ui.components.animation/stop-animation
legacy.status-im.ui.components.animation/animated status-im.ui.components.animation/animated
legacy.status-im.ui.components.animation/add status-im.ui.components.animation/add
legacy.status-im.ui.components.animation/subtract status-im.ui.components.animation/subtract
legacy.status-im.ui.components.animation/get-layout status-im.ui.components.animation/get-layout
legacy.status-im.wallet.transactions-test/uri-query-data status-im.wallet.transactions-test/uri-query-data
legacy.status-im.utils.name/shortened-name status-im.utils.name/shortened-name
legacy.status-im.ui.components.button.haptic/trigger status-im.ui.components.button.haptic/trigger
legacy.status-im.contact.db/filter-dapps status-im.contact.db/filter-dapps
legacy.status-im.contact.db/filter-group-contacts status-im.contact.db/filter-group-contacts
legacy.status-im.contact.db/legacy-pending? status-im.contact.db/legacy-pending?
legacy.status-im.utils.transducers-test/preview-call-1 status-im.utils.transducers-test/preview-call-1
legacy.status-im.utils.transducers-test/preview-call-2 status-im.utils.transducers-test/preview-call-2
legacy.status-im.utils.types/to-string status-im.utils.types/to-string
legacy.status-im.chat.db/datemark? status-im.chat.db/datemark?
legacy.status-im.chat.db/gap? status-im.chat.db/gap?
legacy.status-im.chat.db/map->sorted-seq status-im.chat.db/map->sorted-seq
legacy.status-im.utils.snoopy/status-module-filter status-im.utils.snoopy/status-module-filter
legacy.status-im.utils.snoopy/websocket-filter status-im.utils.snoopy/websocket-filter
legacy.status-im.utils.snoopy/touches-filter status-im.utils.snoopy/touches-filter
legacy.status-im.utils.snoopy/native-animation-filter status-im.utils.snoopy/native-animation-filter
legacy.status-im.utils.snoopy/keyboard-observer-filter status-im.utils.snoopy/keyboard-observer-filter
legacy.status-im.utils.multihash/hex status-im.utils.multihash/hex
legacy.status-im.utils.multihash/decode-array status-im.utils.multihash/decode-array
+17 -28
View File
@@ -1,41 +1,30 @@
{:config-paths ["status-im"] {:config-paths ["status-im"]
:lint-as {legacy.status-im.utils.views/defview clojure.core/defn :lint-as {status-im.utils.views/defview clojure.core/defn
legacy.status-im.utils.views/letsubs clojure.core/let status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let reagent.core/with-let clojure.core/let
legacy.status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/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.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for quo.previews.preview/list-comp clojure.core/for
legacy.status-im.utils.styles/def clojure.core/def status-im.utils.styles/def clojure.core/def
legacy.status-im.utils.styles/defn clojure.core/defn status-im.utils.styles/defn clojure.core/defn
test-helpers.unit/deftest-sub clojure.core/defn test-helpers.unit/deftest-sub clojure.core/defn
taoensso.tufte/defnp clojure.core/defn} taoensso.tufte/defnp clojure.core/defn}
:linters {:case-duplicate-test {:level :error} :linters {:case-duplicate-test {:level :error}
:case-quoted-test {:level :error} :case-quoted-test {:level :error}
:case-symbol-test {:level :error} :case-symbol-test {:level :error}
:clj-kondo-config {:level :error} :clj-kondo-config {:level :error}
:cond-else {:level :error} :cond-else {:level :error}
:consistent-alias {:level :error :consistent-alias {:level :error
:aliases {clojure.set set :aliases {clojure.string string
clojure.string string clojure.set set
clojure.walk walk clojure.walk walk
malli.core malli taoensso.timbre log}}
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} :deprecated-namespace {:level :warning}
:docstring-blank {:level :error} :docstring-blank {:level :error}
:equals-true {:level :error} :equals-true {:level :error}
:inline-def {:level :error} :inline-def {:level :error}
:invalid-arity {:skip-args [legacy.status-im.utils.fx/defn :invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
utils.re-frame/defn]}
:loop-without-recur {:level :error} :loop-without-recur {:level :error}
:minus-one {:level :error} :minus-one {:level :error}
:misplaced-docstring {:level :error} :misplaced-docstring {:level :error}
@@ -65,7 +54,7 @@
;; https://github.com/borkdude/clj-kondo/issues/867 ;; https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY :unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number number
legacy.status-im.test-helpers/restore-app-db]} status-im.test-helpers/restore-app-db]}
:unresolved-var {:level :error} :unresolved-var {:level :error}
:unsorted-required-namespaces {:level :error} :unsorted-required-namespaces {:level :error}
:unused-alias {:level :warning} :unused-alias {:level :warning}
-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/->>}}
+1 -7
View File
@@ -1,8 +1,2 @@
{:hooks {:hooks {:analyze-call {utils.i18n/label utils.i18n/label}}
{: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}}
:linters {:status-im.linter/invalid-translation-keyword {:level :error}}} :linters {:status-im.linter/invalid-translation-keyword {:level :error}}}
-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))}))
-3
View File
@@ -34,6 +34,3 @@ STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1 LOCAL_PAIRING_ENABLED=1
TEST_STATEOFUS=1 TEST_STATEOFUS=1
FAST_CREATE_COMMUNITY_ENABLED=1 FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
SHOW_NOT_IMPLEMENTED_FEATURES=0
ENABLE_ALERT_BANNER=0
-5
View File
@@ -33,8 +33,3 @@ TWO_MINUTES_SYNCING=1
STICKERS_TEST_ENABLED=1 STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1 LOCAL_PAIRING_ENABLED=1
FAST_CREATE_COMMUNITY_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
-3
View File
@@ -35,6 +35,3 @@ ENABLE_QUO_PREVIEW=1
STICKERS_TEST_ENABLED=1 STICKERS_TEST_ENABLED=1
LOCAL_PAIRING_ENABLED=1 LOCAL_PAIRING_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=1 FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
SHOW_NOT_IMPLEMENTED_FEATURES=1
ENABLE_ALERT_BANNER=1
-2
View File
@@ -22,5 +22,3 @@ COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1 DATABASE_MANAGEMENT_ENABLED=1
DELETE_MESSAGE_ENABLED=1 DELETE_MESSAGE_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0 FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
ENABLE_ALERT_BANNER=1
-1
View File
@@ -20,4 +20,3 @@ MAX_IMAGES_BATCH=1
DELETE_MESSAGE_ENABLED=1 DELETE_MESSAGE_ENABLED=1
COLLECTIBLES_ENABLED=1 COLLECTIBLES_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0 FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
+1 -1
View File
@@ -1,4 +1,4 @@
module.exports = { module.exports = {
root: true, root: true,
extends: '@react-native', extends: '@react-native-community',
}; };
+3 -6
View File
@@ -36,10 +36,6 @@ project.xcworkspace
**/android/.project **/android/.project
**/android/.settings/org.eclipse.buildship.core.prefs **/android/.settings/org.eclipse.buildship.core.prefs
local.properties local.properties
*.hprof
.cxx/
*.keystore
!debug.keystore
# Atom # Atom
.tags* .tags*
@@ -195,5 +191,6 @@ test/appium/tests/users.py
## git hooks ## git hooks
lefthook.yml lefthook.yml
## build time logs ## clj-kondo
/logs/*.log /.clj-kondo/taoensso/*
/.clj-kondo/babashka/*
+4 -4
View File
@@ -1,10 +1,10 @@
{ {
"include": [ "include": [
"target/test/legacy/status_im/**" "target/test/status_im/**"
], ],
"exclude": [ "exclude": [
"target/test/legacy/status_im/test/**", "target/test/status_im/test/**",
"target/test/legacy/status_im/ui/**" "target/test/status_im/ui/**"
], ],
"report-dir": "./coverage-report", "report-dir": "./coverage-report",
"all": true, "all": true,
@@ -14,4 +14,4 @@
"exclude-after-remap": false, "exclude-after-remap": false,
"extension": [".js"], "extension": [".js"],
"reporter": ["lcovonly"] "reporter": ["lcovonly"]
} }
+40 -49
View File
@@ -1,61 +1,52 @@
;; -*- mode: clojure -*- ;; -*- mode: clojure -*-
;; vi: ft=clojure ;; vi: ft=clojure
{:width 105 {:width 105
:remove {:fn-force-nl #{:noarg1-body}} :style [;; community style
;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community
:community
:style ;; no comma in map
[;; community style https://github.com/kkinnear/zprint/blob/main/doc/reference.md#community :no-comma
:community
;; no comma in map :custom-justify
:no-comma
: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 blank line
:respect-nl ;; https://github.com/kkinnear/zprint/blob/main/doc/reference.md#respect-bl
:respect-bl
;; 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]
;; hang multiline left-hand-thing
;; https://github.com/kkinnear/zprint/issues/273
:multi-lhs-hang]
:fn-map :fn-map
{"reg-sub" :arg1-pair {"reg-sub" :arg1-pair
"h/describe" :arg1-body "h/describe" :arg1-body
"h/describe-skip" :arg1-body "h/test" :arg1-body
"h/describe-only" :arg1-body "global.describe" :arg1-body
"h/test" :arg1-body "global.test" :arg1-body
"h/test-skip" :arg1-body "list-comp" :binding
"h/test-only" :arg1-body "defview" :arg1-body
"test/async" :arg1-body "letsubs" :binding
"test/use-fixtures" :arg1-body "with-let" "let"
"global.describe" :arg1-body "reg-event-fx" :arg1-pair
"global.test" :arg1-body "testing" :arg1-body
"list-comp" :binding "deftest-sub" :arg1-body
"defview" :arg1-body "wait-for" :arg1-body
"letsubs" :binding "with-deps-check" :arg1-body
"with-let" "let" "->" [:noarg1-body
"reg-event-fx" :arg1-pair {:list {:constant-pair? false :force-nl? false}
"reg-fx" :arg1-pair :next-inner-restore [[:list :constant-pair?]]}]
"testing" :arg1-body "set!" "reset!"
"deftest-sub" :arg1-body "assoc-when" "assoc"
"test-async" :arg1-body "assoc-some" "assoc"
"wait-for" :arg1-body "conj-when" "conj"
"with-deps-check" :arg1-body "conj-some" "conj"}
"schema/=>" :arg1-body :remove {:fn-force-nl #{:noarg1-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"}
:style-map :style-map
{:no-comma {:map {:comma? false}} {:no-comma {:map {:comma? false}}
:custom-justify :custom-justify
{:doc "Justify everything using pre-1.1.2 approach" {:doc "Justify everything using pre-1.1.2 approach"
:binding {:justify? true :justify {:max-variance 1000}} :binding {:justify? true :justify {:max-variance 1000}}
+67 -106
View File
@@ -36,8 +36,6 @@ endif
export TMPDIR = /tmp/tmp-status-mobile-$(BUILD_TAG) export TMPDIR = /tmp/tmp-status-mobile-$(BUILD_TAG)
# This has to be specified for both the Node.JS server process and the Qt process. # This has to be specified for both the Node.JS server process and the Qt process.
export REACT_SERVER_PORT ?= 5001 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. # Fix for ERR_OSSL_EVP_UNSUPPORTED error.
export NODE_OPTIONS += --openssl-legacy-provider export NODE_OPTIONS += --openssl-legacy-provider
# The path can be anything, but home is usually safest. # The path can be anything, but home is usually safest.
@@ -46,7 +44,7 @@ export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
# Our custom config is located in nix/nix.conf # Our custom config is located in nix/nix.conf
export NIX_USER_CONF_FILES = $(PWD)/nix/nix.conf export NIX_USER_CONF_FILES = $(PWD)/nix/nix.conf
# Location of symlinks to derivations that should not be garbage collected # 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 # Defines which variables will be kept for Nix pure shell, use semicolon as divider
export _NIX_KEEP ?= TMPDIR,BUILD_ENV,\ export _NIX_KEEP ?= TMPDIR,BUILD_ENV,\
BUILD_TYPE,BUILD_NUMBER,COMMIT_HASH,\ BUILD_TYPE,BUILD_NUMBER,COMMIT_HASH,\
@@ -56,6 +54,12 @@ export _NIX_KEEP ?= TMPDIR,BUILD_ENV,\
# Useful for Android release builds # Useful for Android release builds
TMP_BUILD_NUMBER := $(shell ./scripts/version/gen_build_no.sh | cut -c1-10) 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 # Nix targets
#---------------- #----------------
@@ -156,12 +160,10 @@ pod-install: export TARGET := ios
pod-install: ##@prepare Run 'pod install' to install podfiles and update Podfile.lock pod-install: ##@prepare Run 'pod install' to install podfiles and update Podfile.lock
cd ios && pod install; cd -- cd ios && pod install; cd --
FLEETS_FILE := ./resources/config/fleets.json
update-fleets: ##@prepare Download up-to-date JSON file with current fleets state update-fleets: ##@prepare Download up-to-date JSON file with current fleets state
curl -s https://fleets.status.im/ \ curl -s https://fleets.status.im/ \
| sed 's/"warning": "/"warning": "DO NOT EDIT! /' \ | sed 's/"warning": "/"warning": "DO NOT EDIT! /' \
> $(FLEETS_FILE) > resources/config/fleets.json
echo >> $(FLEETS_FILE)
$(KEYSTORE_PATH): export TARGET := keytool $(KEYSTORE_PATH): export TARGET := keytool
$(KEYSTORE_PATH): $(KEYSTORE_PATH):
@@ -210,7 +212,7 @@ build-fdroid: ##@build Build release for F-Droid
build-android: export BUILD_ENV ?= prod build-android: export BUILD_ENV ?= prod
build-android: export BUILD_TYPE ?= nightly 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_SPLIT ?= false
build-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86 build-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
build-android: ##@build Build unsigned Android APK build-android: ##@build Build unsigned Android APK
@@ -263,7 +265,7 @@ run-clojure: ##@run Watch for and build Clojure changes for mobile
run-metro: export TARGET := clojure run-metro: export TARGET := clojure
run-metro: ##@run Start Metro to build React Native changes run-metro: ##@run Start Metro to build React Native changes
@scripts/run-metro.sh @scripts/start-react-native.sh
run-re-frisk: export TARGET := clojure run-re-frisk: export TARGET := clojure
run-re-frisk: ##@run Start re-frisk server run-re-frisk: ##@run Start re-frisk server
@@ -271,27 +273,31 @@ run-re-frisk: ##@run Start re-frisk server
# TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix # TODO: Migrate this to a Nix recipe, much the same way as nix/mobile/android/targets/release-android.nix
run-android: export TARGET := android run-android: export TARGET := android
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors. # INFO: If it's empty (no devices attached, parsing issues, script error) - for Nix it's the same as not set.
# https://github.com/status-im/status-mobile/issues/18493 run-android: export ANDROID_ABI_INCLUDE ?= $(shell ./scripts/adb_devices_abis.sh)
run-android: export ORG_GRADLE_PROJECT_hermesEnabled := false
run-android: ##@run Build Android APK and start it on the device 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 SIMULATOR=iPhone 13
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios: export TARGET := ios run-ios: export TARGET := ios
run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64 run-ios: export IOS_STATUS_GO_TARGETS := iossimulator/amd64
run-ios: ##@run Build iOS app and start it in on the simulator run-ios: ##@run Build iOS app and start it in a simulator/device
@scripts/run-ios.sh "${SIMULATOR}" ifneq ("$(SIMULATOR)", "")
npx react-native run-ios --simulator="$(SIMULATOR)"
else
npx react-native run-ios
endif
show-ios-devices: ##@other shows connected ios device and its name show-ios-devices: ##@other shows connected ios device and its name
xcrun xctrace list devices 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 TARGET := ios
run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64 run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64
run-ios-device: ##@run iOS app and start it on the first connected iPhone run-ios-device: ##@run iOS app and start it on a connected device by its name
@scripts/run-ios-device.sh ifndef DEVICE_NAME
$(error Usage: make run-ios-device DEVICE_NAME=your-device-name)
endif
react-native run-ios --device "$(DEVICE_NAME)"
#-------------- #--------------
# Tests # Tests
@@ -299,20 +305,19 @@ run-ios-device: ##@run iOS app and start it on the first connected iPhone
# Get all clojure files, including untracked, excluding removed # Get all clojure files, including untracked, excluding removed
define find_all_clojure_files 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 endef
lint: export TARGET := clojure lint: export TARGET := clojure
lint: export CLJ_LINTER_PRINT_WARNINGS ?= false lint: export CLJ_LINTER_PRINT_WARNINGS ?= false
lint: ##@test Run code style checks lint: ##@test Run code style checks
@sh scripts/lint/re-frame-in-quo-components.sh && \ @sh scripts/lint-re-frame-in-quo-components.sh && \
sh scripts/lint/direct-require-component-outside-quo.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: ') && \ clj-kondo --config .clj-kondo/config.edn --cache false --fail-level error --lint src $(if $(filter $(CLJ_LINTER_PRINT_WARNINGS),true),,| grep -v ': warning: ') && \
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \ ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
scripts/lint/translations.clj && \ scripts/lint_translations.clj && \
zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \ zprint '{:search-config? true}' -sfc $$ALL_CLOJURE_FILES && \
sh scripts/lint/trailing-newline.sh && \ sh scripts/lint-trailing-newline.sh && \
node_modules/.bin/prettier --write . node_modules/.bin/prettier --write .
# NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271 # NOTE: We run the linter twice because of https://github.com/kkinnear/zprint/issues/271
@@ -321,83 +326,58 @@ lint-fix: ##@test Run code style checks and fix issues
ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \ ALL_CLOJURE_FILES=$(call find_all_clojure_files) && \
zprint '{:search-config? true}' -sw $$ALL_CLOJURE_FILES && \ zprint '{:search-config? true}' -sw $$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 && \ clojure-lsp --ns-exclude-regex ".*/src/status_im2/core\.cljs$$" clean-ns && \
sh scripts/lint/trailing-newline.sh --fix && \ sh scripts/lint-trailing-newline.sh --fix && \
node_modules/.bin/prettier --write . node_modules/.bin/prettier --write .
shadow-server: export TARGET := clojure shadow-server: export TARGET := clojure
shadow-server:##@ Start shadow-cljs in server mode for watching shadow-server:##@ Start shadow-cljs in server mode for watching
yarn shadow-cljs server yarn shadow-cljs server
_test-clojure: export TARGET := clojure test-watch: export TARGET := clojure
_test-clojure: export WATCH ?= false test-watch: ##@ Watch tests and re-run no changes to cljs files
_test-clojure: status-go-library yarn install
_test-clojure: nodemon --exec 'yarn shadow-cljs compile mocks && yarn shadow-cljs compile test && node --require ./test-resources/override.js target/test/test.js' -e cljs
ifeq ($(WATCH), true)
yarn node-pre-gyp rebuild && \ test-watch-for-repl: export TARGET := clojure
yarn shadow-cljs compile mocks && \ test-watch-for-repl: ##@ Watch tests and support REPL connections
nodemon --exec "yarn shadow-cljs compile test && node --require ./test-resources/override.js $$SHADOW_OUTPUT_TO" -e cljs yarn install
else rm -f target/test/test.js
yarn node-pre-gyp rebuild && \ 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 mocks && \
yarn shadow-cljs compile test && \ yarn shadow-cljs compile test && \
node --require ./test-resources/override.js "$$SHADOW_OUTPUT_TO" node --require ./test-resources/override.js target/test/test.js
endif
test: export SHADOW_OUTPUT_TO := target/test/test.js android-test: jsbundle
test: export SHADOW_NS_REGEXP := .*-test$$ android-test: export TARGET := android
test: ##@test Run all Clojure tests android-test:
test: _test-clojure
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: status-go-library
test-watch-for-repl: ##@test Watch all Clojure tests and support REPL connections
yarn node-pre-gyp rebuild
rm -f target/test/test.js
yarn shadow-cljs compile mocks && \
concurrently --kill-others --prefix-colors 'auto' --names 'build,repl' \
'yarn shadow-cljs watch test --verbose' \
"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 cd android && ./gradlew test
test-component-watch: export TARGET := clojure component-test-watch: export TARGET := clojure
test-component-watch: export COMPONENT_TEST := true component-test-watch: export COMPONENT_TEST := true
test-component-watch: export BABEL_ENV := test component-test-watch: export BABEL_ENV := test
test-component-watch: export JEST_USE_SILENT_REPORTER := false component-test-watch: ##@ Watch tests and re-run no changes to cljs files
test-component-watch: ##@ Watch tests and re-run no changes to cljs files @@scripts/check-metro-shadow-process.sh
@scripts/check-metro-shadow-process.sh
rm -rf ./component-spec rm -rf ./component-spec
nodemon --exec 'yarn shadow-cljs compile component-test && jest --config=test/jest/jest.config.js --testEnvironment node ' -e cljs yarn install
nodemon --exec 'yarn shadow-cljs compile component-test && jest --config=test/jest/jest.config.js' -e cljs
test-component: export TARGET := clojure component-test: export TARGET := clojure
test-component: export COMPONENT_TEST := true component-test: export COMPONENT_TEST := true
test-component: export BABEL_ENV := test component-test: export BABEL_ENV := test
test-component: export JEST_USE_SILENT_REPORTER := false component-test: ##@test Run component tests once in NodeJS
test-component: ##@test Run component tests once in NodeJS
@scripts/check-metro-shadow-process.sh @scripts/check-metro-shadow-process.sh
rm -rf ./component-spec rm -rf ./component-spec
yarn install
yarn shadow-cljs compile component-test && \ yarn shadow-cljs compile component-test && \
jest --clearCache && jest --config=test/jest/jest.config.js --testEnvironment node jest --config=test/jest/jest.config.js
#-------------- #--------------
# Other # Other
@@ -441,10 +421,6 @@ _list: SHELL := /bin/sh
_list: _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 '^$@$$' @$(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 # REPLs
#-------------- #--------------
@@ -454,18 +430,3 @@ repl-clojure: ##@repl Start Clojure repl for mobile App
yarn shadow-cljs cljs-repl mobile yarn shadow-cljs cljs-repl mobile
repl-nix: nix-repl ##@repl Start an interactive Nix REPL repl-nix: nix-repl ##@repl Start an interactive Nix REPL
#--------------
# Dev Automation Flows
#--------------
auto-login: export TARGET := default
auto-login: ##@auto runs flow for login or onboarding app on simulator/emulator
maestro test "maestro/create-account-or-login.yaml"
auto-custom: export TARGET := default
auto-custom: ##@auto runs any custom maestro automation flow on simulator/emulator
ifndef FLOW
$(error Usage: make automate FLOW=your-maestro-flow-file.yaml)
endif
maestro test "$(FLOW)"
+3 -3
View File
@@ -37,7 +37,7 @@ project dependencies, coding guidelines and testing procedures.
Check out our [coding guidelines](doc/new-guidelines.md). Check out our [coding guidelines](doc/new-guidelines.md).
- **Community Management** - **Community Management**
Metcalfe's law states that the value of a network is proportional to the square of the number of connected users of the system - without community Status is meaningless. We're looking to create a positive, fun environment to explore new ideas, experiment and grow the Status community. Building a community takes a lot of work but the people you'll meet and the long-lasting relationships you form will be well worth it, check out our [Mission and Community Principles](https://status.app/manifesto) Metcalfe's law states that the value of a network is proportional to the square of the number of connected users of the system - without community Status is meaningless. We're looking to create a positive, fun environment to explore new ideas, experiment and grow the Status community. Building a community takes a lot of work but the people you'll meet and the long-lasting relationships you form will be well worth it, check out our [Mission and Community Principles](https://status.im/about)
- **Specification / Documentation** - **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 and Designers need guidance and it all starts from documentation and specifications. Our software is only as good as its documentation, check out our [docs](doc/) and see how you can improve what we have.
@@ -53,10 +53,10 @@ Status is a visual interface to make permanent changes on the Blockchain, it han
- **Evangelism** - **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)
## Give me Binaries! ## 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 ## Core Contributors
+1 -1
View File
@@ -1 +1 @@
2.27.0 1.26.0
+230 -88
View File
@@ -1,75 +1,128 @@
apply plugin: "com.android.application" 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" apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
import com.android.build.OutputFile import com.android.build.OutputFile
import com.sun.org.apache.xalan.internal.xsltc.compiler.Copy import com.sun.org.apache.xalan.internal.xsltc.compiler.Copy
/* /**
* This is the configuration block to customize your React Native Android app. * The react.gradle file registers a task for each build variant:
* By default you don't need to apply any configuration, just uncomment the lines you need. * - 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: []
* ]
*/ */
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 Enabling Hermes on x86 devices is crashing the app after a few reloads,
// skip the bundling of the JS bundle and the assets. By default is just 'debug'. this flag can be used to disable Hermes while building app.
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. https://github.com/status-im/status-mobile/issues/14031
// debuggableVariants = ["liteDebug", "prodDebug"] */
/* Bundling */ def disableHermes = System.getenv('DISABLE_HERMES') == 'true'
// 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 = []
/* Hermes Commands */ project.ext.react = [
// The hermes compiler command to run. By default it is 'hermesc' nodeExecutableAndArgs: ["node", "--max-old-space-size=16384"],
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" entryFile: "index.js",
// /* NOTE: Hermes engine is required for Android 64-bit builds running on 64 devices,
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" * to guard against a hang in the UI thread after invoking status-go.
// hermesFlags = ["-O", "-output-source-map"] * 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/**"]
]
// 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 = false 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: * For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'` * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
* *
* The international variant includes ICU i18n library and necessary data * The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that * 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. * this variant is about 6MiB larger per architecture than default.
*/ */
def jscFlavor = 'org.webkit:android-jsc:+' def jscFlavor = 'org.webkit:android-jsc:+'
@@ -81,8 +134,15 @@ def jscFlavor = 'org.webkit:android-jsc:+'
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced. * 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 = { -> def getCommitHash = { ->
if (project.hasProperty("commitHash")) { if (project.hasProperty("commitHash")) {
@@ -138,27 +198,13 @@ def getEnvOrConfig = { varName ->
android { android {
ndkVersion rootProject.ext.ndkVersion ndkVersion rootProject.ext.ndkVersion
buildToolsVersion rootProject.ext.buildToolsVersion compileSdkVersion rootProject.ext.compileSdkVersion
compileSdk rootProject.ext.compileSdkVersion
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17
}
// 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"
}
}
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_11
} }
namespace "im.status.ethereum"
defaultConfig { defaultConfig {
applicationId "im.status.ethereum" applicationId "im.status.ethereum"
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
@@ -174,8 +220,70 @@ android {
abiFilters getEnvOrConfig('ANDROID_ABI_INCLUDE').split(";") 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 * Arbitrary project metadata
* https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html * https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html
@@ -207,6 +315,10 @@ android {
doNotStrip '*/mips/*.so' doNotStrip '*/mips/*.so'
doNotStrip '*/mips64/*.so' doNotStrip '*/mips64/*.so'
} }
dexOptions {
jumboMode true
javaMaxHeapSize "8g"
}
splits { splits {
abi { abi {
reset() reset()
@@ -242,11 +354,10 @@ android {
versionNameSuffix ".pr" versionNameSuffix ".pr"
debuggable false debuggable false
matchingFallbacks = ["release"] matchingFallbacks = ["release"]
// necessary to make react-native-config's code generation work // necessary to make react-native-config's code generation work
resValue "string", "build_config_package", "im.status.ethereum" resValue "string", "build_config_package", "im.status.ethereum"
} }
} }
// applicationVariants are e.g. debug, release // applicationVariants are e.g. debug, release
applicationVariants.all { variant -> applicationVariants.all { variant ->
variant.outputs.each { output -> variant.outputs.each { output ->
@@ -262,7 +373,6 @@ android {
} }
} }
aaptOptions { 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/) // 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 cruncherEnabled = false
@@ -274,30 +384,54 @@ android {
} }
dependencies { dependencies {
// The version of react-native is set by the React Native Gradle Plugin implementation fileTree(dir: "libs", include: ["*.jar"])
implementation("com.facebook.react:react-android") implementation "com.facebook.react:react-native:+" // From node_modules
implementation("androidx.core:core-splashscreen:1.0.0") implementation 'com.facebook.soloader:soloader:0.10.3+'
// we don't use hermes for debug but we need its pom file for release builds implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
// https://github.com/status-im/status-mobile/pull/18675 implementation "androidx.core:core-splashscreen:1.0.0"
implementation("com.facebook.react:hermes-android")
// FIXME: implementing both hermes & JSC increases bundle size by ~ 2MB if (enableHermes) {
implementation(jscFlavor) //noinspection GradleDynamicVersion
implementation("com.facebook.react:hermes-engine:+") { // From node_modules
exclude group: 'com.facebook.fbjni' }
} else {
implementation jscFlavor
}
// react-native-screens // react-native-screens
implementation("androidx.appcompat:appcompat:1.1.0-rc01") implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02") 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.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') 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')
implementation project(':react-native-status-keycard') implementation project(':react-native-status-keycard')
implementation("com.github.status-im:function:0.0.1") implementation 'com.github.status-im:function:0.0.1'
implementation("com.facebook.fresco:fresco:2.5.0") implementation 'com.facebook.fresco:fresco:2.5.0'
implementation("com.facebook.fresco:animated-gif:2.5.0") implementation 'com.facebook.fresco:animated-gif:2.5.0'
implementation("com.squareup.okhttp3:okhttp-tls:4.9.2") implementation "com.squareup.okhttp3:okhttp-tls:4.9.2"
implementation("com.google.prefab:cli:2.0.0")
implementation("com.android.tools.build:aapt2:8.1.1-10154469")
} }
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 getLocalNDKDir = { ->
def rootDir = project.rootDir def rootDir = project.rootDir
@@ -332,3 +466,11 @@ task hemroidBuild(type: Exec) {
preBuild.dependsOn hemroidBuild preBuild.dependsOn hemroidBuild
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 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"
}
+3 -1
View File
@@ -7,5 +7,7 @@
<!-- Remove licensing permission since we don't license our app and it blocks F-Droid submissions. --> <!-- 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"/> <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> </manifest>
+6 -19
View File
@@ -1,17 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto"> android:installLocation="auto"
package="im.status.ethereum">
<queries>
<intent>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<data android:mimeType="*/*" />
</intent>
</queries>
<!-- non-dangerous permissions --> <!-- non-dangerous permissions -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <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.INTERNET"/>
<uses-permission android:name="android.permission.NFC"/> <uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <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" />
<uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <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.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<application <application
@@ -82,13 +75,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/> <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
<service <service android:name="im.status.ethereum.pushnotifications.ForegroundService"></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>
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider" 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()
}
}
}
@@ -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();
});
}
+37 -27
View File
@@ -1,3 +1,4 @@
import org.apache.tools.ant.taskdefs.condition.Os
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
/** /**
@@ -5,19 +6,25 @@
*/ */
ext { ext {
// kotlin_version is needed for react-native-camera-kit library // kotlin_version is needed for react-native-camera-kit library
kotlin_version = project.kotlinPluginVersion kotlin_version = project.kotlinVersion
RNNKotlinVersion = project.kotlinPluginVersion RNNKotlinVersion = "1.6.20"
RNGH_kotlinVersion = project.kotlinPluginVersion RNGH_kotlinVersion = "1.6.20"
buildToolsVersion = project.buildToolsVersion buildToolsVersion = project.buildToolsVersion
minSdkVersion = Integer.valueOf(project.minSdkVersion) minSdkVersion = Integer.valueOf(project.minSdkVersion)
compileSdkVersion = Integer.valueOf(project.compileSdkVersion) compileSdkVersion = Integer.valueOf(project.compileSdkVersion)
targetSdkVersion = Integer.valueOf(project.targetSdkVersion) targetSdkVersion = Integer.valueOf(project.targetSdkVersion)
supportLibVersion = project.supportLibVersion supportLibVersion = project.supportLibVersion
gradlePluginVersion = project.gradlePluginVersion gradlePluginVersion = project.gradlePluginVersion
kotlinVersion = project.kotlinPluginVersion
kotlinPluginVersion = project.kotlinPluginVersion kotlinPluginVersion = project.kotlinPluginVersion
kotlinToolsVersion = project.kotlinPluginVersion
ndkVersion = "25.2.9519653" if (System.properties['os.arch'] == "aarch64") {
// For M1 Users we need to use the NDK 24 which added support for aarch64
ndkVersion = "24.0.8215888"
} else {
// Otherwise we default to the side-by-side NDK version from AGP.
ndkVersion = "21.4.7075529"
}
} }
buildscript { buildscript {
@@ -28,9 +35,11 @@ buildscript {
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${project.ext.kotlinPluginVersion}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${project.ext.kotlinPluginVersion}"
classpath("com.android.tools.build:gradle") classpath "com.android.tools.build:gradle:${project.ext.gradlePluginVersion}"
classpath("com.facebook.react:react-native-gradle-plugin") classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") classpath("de.undercouch:gradle-download-task:5.0.1")
// WARNING: Do not place your application dependencies here!
// They belong in the individual module build.gradle files.
} }
} }
@@ -44,44 +53,45 @@ subprojects {
defaultConfig { defaultConfig {
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
} }
// Speed up Tests Stage
tasks.withType(Test).configureEach {
// https://docs.gradle.org/current/userguide/performance.html#execute_tests_in_parallel
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
// https://docs.gradle.org/current/userguide/performance.html#fork_tests_into_multiple_processes
forkEvery = 100
// https://docs.gradle.org/current/userguide/performance.html#disable_reports
reports.html.required = false
reports.junitXml.required = false
}
// Speed up Java Compile Stage
// https://docs.gradle.org/current/userguide/performance.html#run_the_compiler_as_a_separate_process
tasks.withType(JavaCompile).configureEach {
options.fork = true
}
} }
} }
} }
} }
apply plugin: "com.facebook.react.rootproject"
allprojects { allprojects {
beforeEvaluate { beforeEvaluate {
if (System.env.STATUS_GO_ANDROID_LIBDIR == null || System.env.STATUS_GO_ANDROID_LIBDIR == "") { if (System.env.STATUS_GO_ANDROID_LIBDIR == null || System.env.STATUS_GO_ANDROID_LIBDIR == "") {
throw new GradleException('STATUS_GO_ANDROID_LIBDIR environment variable is not valid!') throw new GradleException('STATUS_GO_ANDROID_LIBDIR environment variable is not valid!')
} }
} }
repositories { repositories {
exclusiveContent {
// We get React Native's Android binaries exclusively through npm,
// from a local Maven repo inside node_modules/react-native/.
// (The use of exclusiveContent prevents looking elsewhere like Maven Central
// and potentially getting a wrong version.)
filter {
includeGroup "com.facebook.react"
}
forRepository {
maven {
url "$rootDir/../node_modules/react-native/android"
}
}
}
mavenLocal() mavenLocal()
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
maven { url("$rootDir/../node_modules/react-native/android") }
// Android JSC is installed from npm // Android JSC is installed from npm
maven { url("$rootDir/../node_modules/jsc-android/dist") } maven { url("$rootDir/../node_modules/jsc-android/dist") }
// For geth, function, and status-go // For geth, function, and status-go
flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR } flatDir { dirs "libs", System.env.STATUS_GO_ANDROID_LIBDIR }
// Everything Else
google() google()
jcenter() // Required for @react-native-community/blur:3.6.1, can be removed after updating to 3.6.1+
mavenCentral() mavenCentral()
// maven { url "https://www.jitpack.io" }
maven { url 'https://mvnrepository.com/artifact/com.github.gundy/semver4j'} maven { url 'https://mvnrepository.com/artifact/com.github.gundy/semver4j'}
} }
} }
+9 -14
View File
@@ -21,14 +21,15 @@
# $keytool -genkey -v -keystore ./status-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias status # $keytool -genkey -v -keystore ./status-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias status
# Version requirements used throughout the Gradle scripts # Version requirements used throughout the Gradle scripts
kotlinVersion=1.6.20
minSdkVersion=24 minSdkVersion=24
compileSdkVersion=34 compileSdkVersion=31
targetSdkVersion=34 targetSdkVersion=31
buildToolsVersion=34.0.0 buildToolsVersion=31.0.0
supportLibVersion=28.0.0 supportLibVersion=28.0.0
# This should match version from nix/pkgs/aapt2/default.nix # This should match version from nix/mobile/android/maven-and-npm-deps/maven/default.nix
gradlePluginVersion=7.4.2 gradlePluginVersion=7.2.2
kotlinPluginVersion=1.9.0 kotlinPluginVersion=1.6.20
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
@@ -41,9 +42,9 @@ KEYSTORE_KEY_PASSWORD=password
# By default we build a mostly universal APK # By default we build a mostly universal APK
ANDROID_ABI_SPLIT=false ANDROID_ABI_SPLIT=false
# Some platforms are excluded though # Some platforms are excluded though
ANDROID_ABI_INCLUDE=armeabi-v7a;arm64-v8a;x86;x86_64 ANDROID_ABI_INCLUDE=armeabi-v7a;arm64-v8a;x86
org.gradle.jvmargs=-Xmx8704M -XX:+UseParallelGC org.gradle.jvmargs=-Xmx8704M
versionCode=9999 versionCode=9999
commitHash=unknown commitHash=unknown
@@ -54,9 +55,3 @@ commitHash=unknown
# to write custom TurboModules/Fabric components OR use libraries that # to write custom TurboModules/Fabric components OR use libraries that
# are providing them. # are providing them.
newArchEnabled=false newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
# Disabled for debug builds to avoid 'maximum call stack exceeded' errors.
# https://github.com/status-im/status-mobile/issues/18493
hermesEnabled=false
+9 -1
View File
@@ -12,10 +12,18 @@ apply from: file("../node_modules/@react-native-community/cli-platform-android/n
include ':react-native-nfc-manager' include ':react-native-nfc-manager'
project(':react-native-nfc-manager').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-nfc-manager/android') project(':react-native-nfc-manager').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-nfc-manager/android')
include ':app' include ':app'
include ':react-native-dialogs'
project(':react-native-dialogs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-dialogs/android')
include ':react-native-status' include ':react-native-status'
project(':react-native-status').projectDir = new File(rootProject.projectDir, '../modules/react-native-status/android') project(':react-native-status').projectDir = new File(rootProject.projectDir, '../modules/react-native-status/android')
include ':react-native-status-keycard' include ':react-native-status-keycard'
project(':react-native-status-keycard').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-status-keycard/android') project(':react-native-status-keycard').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-status-keycard/android')
include ':react-native-blur' include ':react-native-blur'
project(':react-native-blur').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/blur/android') project(':react-native-blur').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/blur/android')
includeBuild('../node_modules/@react-native/gradle-plugin') includeBuild('../node_modules/react-native-gradle-plugin')
if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
include(":ReactAndroid")
project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
include(":ReactAndroid:hermes-engine")
project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/ReactAndroid/hermes-engine')
}
+16 -1
View File
@@ -1,4 +1,19 @@
module.exports = { module.exports = {
presets: ['module:@react-native/babel-preset'], presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin', '@babel/plugin-transform-named-capturing-groups-regex'], plugins: ['react-native-reanimated/plugin', '@babel/plugin-transform-named-capturing-groups-regex'],
env: {
test: {
presets: [
'@babel/preset-react',
[
'@babel/preset-env',
{
targets: {
node: '14',
},
},
],
],
},
},
}; };
+7 -7
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
/* Options section can't access functions in objects. */ /* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild() def isPRBuild = utils.isPRBuild()
pipeline { pipeline {
agent { label 'linux && x86_64 && nix-2.19' } agent { label 'linux && x86_64 && nix-2.14' }
options { options {
timestamps() timestamps()
@@ -15,7 +15,7 @@ pipeline {
buildDiscarder(logRotator( buildDiscarder(logRotator(
numToKeepStr: '10', numToKeepStr: '10',
daysToKeepStr: '20', daysToKeepStr: '20',
artifactNumToKeepStr: '1', artifactNumToKeepStr: '10',
)) ))
/* Allows combined build to copy */ /* Allows combined build to copy */
copyArtifactPermission('/status-mobile/*') copyArtifactPermission('/status-mobile/*')
@@ -34,10 +34,10 @@ pipeline {
} }
environment { environment {
LANG = 'en_US.UTF-8' LANG = "en_US.UTF-8"
LC_ALL = 'en_US.UTF-8' LC_ALL = "en_US.UTF-8"
LANGUAGE = 'en_US.UTF-8' LANGUAGE = "en_US.UTF-8"
PLATFORM = "android${utils.isE2EBuild() ? "-e2e" : ""}" TARGET = "android${utils.isE2EBuild() ? "-e2e" : ""}"
BUILD_ENV = 'prod' BUILD_ENV = 'prod'
NIX_CONF_DIR = "${env.WORKSPACE}/nix" NIX_CONF_DIR = "${env.WORKSPACE}/nix"
FASTLANE_DISABLE_COLORS = 1 FASTLANE_DISABLE_COLORS = 1
+8 -4
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
agent { label 'linux' } agent { label 'linux' }
@@ -13,7 +13,7 @@ pipeline {
buildDiscarder(logRotator( buildDiscarder(logRotator(
numToKeepStr: '10', numToKeepStr: '10',
daysToKeepStr: '30', daysToKeepStr: '30',
artifactNumToKeepStr: '1', artifactNumToKeepStr: '10',
)) ))
} }
@@ -35,6 +35,8 @@ pipeline {
stage('Prep') { stage('Prep') {
steps { script { steps { script {
println("Current JOB: ${env.JOB_NAME}") println("Current JOB: ${env.JOB_NAME}")
/* just for a shorter access */
btype = utils.getBuildType()
} } } }
} }
stage('Build') { stage('Build') {
@@ -81,9 +83,11 @@ pipeline {
stage('Publish') { stage('Publish') {
when { expression { params.PUBLISH } } when { expression { params.PUBLISH } }
steps { script { steps { script {
switch (utils.getBuildType()) { switch (btype) {
case 'nightly': /* Create JSON file with newest build URLs */ case 'nightly':
/* Create JSON file with newest build URLs */
s3.updateBucketJSON(urls, 'latest.json'); s3.updateBucketJSON(urls, 'latest.json');
build(job: 'website/status.im', wait: false);
break; break;
case 'release': case 'release':
github.publishReleaseFiles(repo: 'status-mobile'); github.publishReleaseFiles(repo: 'status-mobile');
+3 -4
View File
@@ -1,12 +1,12 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
agent { label 'linux' } agent { label 'linux' }
triggers { triggers {
// Nightly at 0am // Nightly at 2am
cron 'H 0 * * *' cron 'H 2 * * *'
} }
parameters { parameters {
@@ -23,7 +23,6 @@ pipeline {
buildDiscarder(logRotator( buildDiscarder(logRotator(
numToKeepStr: '10', numToKeepStr: '10',
daysToKeepStr: '30', daysToKeepStr: '30',
artifactNumToKeepStr: '1',
)) ))
} }
+11 -8
View File
@@ -1,11 +1,11 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
/* Options section can't access functions in objects. */ /* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild() def isPRBuild = utils.isPRBuild()
pipeline { pipeline {
agent { label 'macos && arm64 && nix-2.19 && xcode-15.1' } agent { label 'macos && arm64 && nix-2.14 && xcode-14.3' }
parameters { parameters {
string( string(
@@ -23,7 +23,7 @@ pipeline {
buildDiscarder(logRotator( buildDiscarder(logRotator(
numToKeepStr: '10', numToKeepStr: '10',
daysToKeepStr: '20', daysToKeepStr: '20',
artifactNumToKeepStr: '1', artifactNumToKeepStr: '10',
)) ))
/* Allows combined build to copy */ /* Allows combined build to copy */
copyArtifactPermission('/status-mobile/*') copyArtifactPermission('/status-mobile/*')
@@ -34,11 +34,13 @@ pipeline {
} }
environment { environment {
LANG = 'en_US.UTF-8' LANG = "en_US.UTF-8"
LC_ALL = 'en_US.UTF-8' LC_ALL = "en_US.UTF-8"
LANGUAGE = 'en_US.UTF-8' LANGUAGE = "en_US.UTF-8"
PLATFORM = 'ios' TARGET = 'ios'
NIX_CONF_DIR = "${env.WORKSPACE}/nix" NIX_CONF_DIR = "${env.WORKSPACE}/nix"
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
FASTLANE_DISABLE_COLORS = 1 FASTLANE_DISABLE_COLORS = 1
BUNDLE_PATH = "${HOME}/.bundle" BUNDLE_PATH = "${HOME}/.bundle"
} }
@@ -63,7 +65,7 @@ pipeline {
} }
post { post {
failure { failure {
archiveArtifacts 'logs/*' archiveArtifacts 'ios/logs/*'
} }
} }
} }
@@ -75,6 +77,7 @@ pipeline {
} }
} }
stage('Upload') { stage('Upload') {
when { expression { !utils.isReleaseBuild() } }
steps { script { steps { script {
env.DIAWI_URL = ios.uploadToDiawi() env.DIAWI_URL = ios.uploadToDiawi()
env.PKG_URL = env.DIAWI_URL env.PKG_URL = env.DIAWI_URL
+28 -37
View File
@@ -1,21 +1,21 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
/* Options section can't access functions in objects. */ /* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild() def isPRBuild = utils.isPRBuild()
pipeline { pipeline {
agent { label 'linux && x86_64 && nix-2.19' } agent { label 'linux && x86_64 && nix-2.14' }
options { options {
timestamps() timestamps()
/* Prevent Jenkins jobs from running forever */ /* Prevent Jenkins jobs from running forever */
timeout(time: 20, unit: 'MINUTES') timeout(time: 15, unit: 'MINUTES')
/* Limit builds retained */ /* Limit builds retained */
buildDiscarder(logRotator( buildDiscarder(logRotator(
numToKeepStr: '10', numToKeepStr: '10',
daysToKeepStr: '20', daysToKeepStr: '20',
artifactNumToKeepStr: '1', artifactNumToKeepStr: '10',
)) ))
/* Abort old PR builds. */ /* Abort old PR builds. */
disableConcurrentBuilds( disableConcurrentBuilds(
@@ -29,47 +29,45 @@ pipeline {
description: 'Specify build type. Values: pr / e2e / nightly / release', description: 'Specify build type. Values: pr / e2e / nightly / release',
defaultValue: 'pr', defaultValue: 'pr',
) )
booleanParam(
name: 'RUN_CONTRACT_TESTS',
description: 'Whether to run optional and slow contract tests.',
defaultValue: false,
)
} }
environment { environment {
LANG = 'en_US.UTF-8' LANG = "en_US.UTF-8"
LC_ALL = 'en_US.UTF-8' LC_ALL = "en_US.UTF-8"
LANGUAGE = 'en_US.UTF-8' LANGUAGE = "en_US.UTF-8"
PLATFORM = 'tests' TARGET = 'tests'
BUILD_ENV = 'prod' BUILD_ENV = 'prod'
NIX_CONF_DIR = "${env.WORKSPACE}/nix" NIX_CONF_DIR = "${env.WORKSPACE}/nix"
LOG_FILE = utils.pkgFilename(ext: 'log', arch: 'tests') LOG_FILE = utils.pkgFilename(ext: 'log', arch: 'tests')
CLJ_LINTER_PRINT_WARNINGS = 'true'
} }
stages { stages {
stage('Test') { stage('Checks') {
parallel { parallel {
stage('Lint') { stage('Lint') {
steps { make('lint') } steps {
sh """#!/bin/bash
set -eo pipefail
make lint CLJ_LINTER_PRINT_WARNINGS=true 2>&1 | tee ${LOG_FILE}
"""
}
} }
stage('Unit') { stage('Tests') {
steps { make('test-unit') } steps {
} sh """#!/bin/bash
stage('Component') { set -eo pipefail
steps { make('test-component') } make test 2>&1 | tee -a ${LOG_FILE}
"""
}
} }
} }
} }
stage('Heavy Test') { stage('Component Tests') {
parallel { steps {
stage('Contract') { sh """#!/bin/bash
when { expression { params.RUN_CONTRACT_TESTS } } set -eo pipefail
steps { make('test-contract') } make component-test 2>&1 | tee -a ${LOG_FILE}
} """
stage('Integration') {
steps { make('test-integration') }
}
} }
} }
stage('Upload') { stage('Upload') {
@@ -86,10 +84,3 @@ pipeline {
always { sh 'make purge' } always { sh 'make purge' }
} }
} }
def make(target) {
sh """#!/bin/bash
set -eo pipefail
make ${target} 2>&1 | tee -a ${LOG_FILE}
"""
}
+4 -16
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
@@ -29,17 +29,6 @@ pipeline {
options { options {
disableConcurrentBuilds() disableConcurrentBuilds()
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
environment {
/* Avoid race conditions with other builds using virtualenv. */
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
} }
stages { stages {
@@ -47,10 +36,10 @@ pipeline {
steps { script { steps { script {
copyArtifacts( copyArtifacts(
projectName: "status-mobile/platforms/android-e2e", projectName: "status-mobile/platforms/android-e2e",
filter: 'result/*-x86_64.apk', filter: 'result/*-x86.apk',
selector: specific(env.APK_BUILD_NUMBER), selector: specific(env.APK_BUILD_NUMBER),
) )
apk_path = "${env.WORKSPACE}/${utils.findFile('result/*-x86_64.apk')}" apk_path = "${env.WORKSPACE}/${utils.findFile('result/*-x86.apk')}"
} } } }
} }
@@ -58,8 +47,7 @@ pipeline {
stage('Setup') { stage('Setup') {
steps { script { steps { script {
dir('test/appium') { dir('test/appium') {
sh "python3 -m venv ${VIRTUAL_ENV}" sh 'pip3 install --user -r requirements.txt'
sh 'pip3 install -r requirements.txt'
} }
} } } }
} }
+2 -14
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
@@ -47,17 +47,6 @@ pipeline {
options { options {
disableConcurrentBuilds() disableConcurrentBuilds()
timeout(time: 90, unit: 'MINUTES') timeout(time: 90, unit: 'MINUTES')
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
}
environment {
/* Avoid race conditions with other builds using virtualenv. */
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
} }
stages { stages {
@@ -85,8 +74,7 @@ pipeline {
stage('Setup') { stage('Setup') {
steps { script { steps { script {
dir('test/appium') { dir('test/appium') {
sh "python3 -m venv ${VIRTUAL_ENV}" sh 'pip3 install --user -r requirements.txt'
sh 'pip3 install -r requirements.txt'
} }
} } } }
} }
+2 -13
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
@@ -28,18 +28,8 @@ pipeline {
options { options {
disableConcurrentBuilds() disableConcurrentBuilds()
buildDiscarder(logRotator(
numToKeepStr: '10',
daysToKeepStr: '30',
artifactNumToKeepStr: '1',
))
} }
environment {
/* Avoid race conditions with other builds using virtualenv. */
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
}
stages { stages {
stage('Prep') { stage('Prep') {
@@ -56,8 +46,7 @@ pipeline {
stage('Setup') { stage('Setup') {
steps { script { steps { script {
dir('test/appium') { dir('test/appium') {
sh "python3 -m venv ${VIRTUAL_ENV}" sh 'pip3 install --user -r requirements.txt'
sh 'pip3 install -r requirements.txt'
} }
} } } }
} }
+7 -5
View File
@@ -1,15 +1,17 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
agent { label 'macos' } agent { label 'macos' }
environment { environment {
LANG = 'en_US.UTF-8' LANG = 'en_US.UTF-8'
LANGUAGE = 'en_US.UTF-8' LANGUAGE = 'en_US.UTF-8'
LC_ALL = 'en_US.UTF-8' LC_ALL = 'en_US.UTF-8'
PLATFORM = 'ios' TARGET = 'ios'
FASTLANE_DISABLE_COLORS = 1 FASTLANE_DISABLE_COLORS = 1
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
/* avoid writing to r/o /nix */ /* avoid writing to r/o /nix */
GEM_HOME = '~/.rubygems' GEM_HOME = '~/.rubygems'
} }
+13 -29
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
agent { label params.AGENT_LABEL } agent { label params.AGENT_LABEL }
@@ -18,11 +18,11 @@ pipeline {
} }
environment { environment {
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
/* we source .bash_profile to be able to use nix-store */ /* we source .bash_profile to be able to use nix-store */
NIX_SSHOPTS = "-oStrictHostKeyChecking=no" NIX_SSHOPTS = "-o StrictHostKeyChecking=no source .profile;"
NIX_CONF_DIR = "${env.WORKSPACE}/nix" NIX_CONF_DIR = "${env.WORKSPACE}/nix"
NIX_STORE_CMD = '/nix/var/nix/profiles/default/bin/nix-store'
NIX_SSH_REMOTE = "ssh://${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}?remote-program=${env.NIX_STORE_CMD}"
} }
options { options {
@@ -34,7 +34,6 @@ pipeline {
buildDiscarder(logRotator( buildDiscarder(logRotator(
numToKeepStr: '20', numToKeepStr: '20',
daysToKeepStr: '30', daysToKeepStr: '30',
artifactNumToKeepStr: '1',
)) ))
} }
@@ -43,21 +42,19 @@ pipeline {
steps { script { steps { script {
nix.shell('nix-env -i openssh', sandbox: false, pure: false) nix.shell('nix-env -i openssh', sandbox: false, pure: false)
/* some build targets don't build on MacOS */ /* some build targets don't build on MacOS */
os = sh(script: 'uname', returnStdout: true).trim() os = sh(script: 'uname', returnStdout: true)
arch = sh(script: 'arch', returnStdout: true).trim() arch = sh(script: 'arch', returnStdout: true)
} } } }
} }
stage('Build status-go') { stage('Build status-go') {
steps { script { steps { script {
def platforms = ['mobile.android', 'mobile.ios', 'library'] def platforms = ['mobile.android', 'mobile.ios', 'library']
if (os != 'Darwin') { platforms.removeAll { it == 'mobile.ios' } } if (os != 'Darwin') { platforms.removeAll { it == 'mobile.ios' } }
/* FIXME: "'x86_64-darwin' with features {} is required to build" */ /* FIXME: Remove this when #16237 is merged. */
if (arch == 'arm64') { platforms.removeAll { it == 'mobile.android' } } if (arch == 'arm64') { platforms.removeAll { it == 'mobile.android' } }
platforms.each { platform -> platforms.each { os ->
/* Allow for Android builds on Apple ARM. */
env.NIXPKGS_SYSTEM_OVERRIDE = nixSysOverride(os, arch, platform)
nix.build( nix.build(
attr: "targets.status-go.${platform}", attr: "targets.status-go.${os}",
sandbox: false, sandbox: false,
link: false link: false
) )
@@ -77,11 +74,9 @@ pipeline {
} }
stage('Build android deps') { stage('Build android deps') {
steps { script { steps { script {
/* Allow for Android builds on Apple ARM. */
env.NIXPKGS_SYSTEM_OVERRIDE = nixSysOverride(os, arch, 'android')
/* Build/fetch deps required to build android release. */ /* Build/fetch deps required to build android release. */
nix.build( nix.build(
attr: 'targets.mobile.android.build.buildInputs', attr: 'targets.mobile.android.release.buildInputs',
sandbox: false, sandbox: false,
pure: false, pure: false,
link: false link: false
@@ -91,13 +86,9 @@ pipeline {
stage('Build nix shell deps') { stage('Build nix shell deps') {
steps { script { steps { script {
def shells = ['android', 'ios', 'fastlane', 'keytool', 'clojure', 'gradle'] def shells = ['android', 'ios', 'fastlane', 'keytool', 'clojure', 'gradle']
if (os != 'Darwin') { shells.removeAll { it == 'ios' } } if (os != "Darwin") { shells.removeAll { it == 'ios' } }
/* FIXME: "'x86_64-darwin' with features {} is required to build" */
if (arch == 'arm64') { shells.removeAll { it == 'android' } }
/* Build/fetch deps required to start default Nix shell. */ /* Build/fetch deps required to start default Nix shell. */
shells.each { shell -> shells.each { shell ->
/* Allow for Android builds on Apple ARM. */
env.NIXPKGS_SYSTEM_OVERRIDE = nixSysOverride(os, arch, shell)
nix.build( nix.build(
attr: "shells.${shell}.buildInputs", attr: "shells.${shell}.buildInputs",
sandbox: false, sandbox: false,
@@ -112,7 +103,8 @@ pipeline {
nix.shell(""" nix.shell("""
find /nix/store/ -mindepth 1 -maxdepth 1 -type d \ find /nix/store/ -mindepth 1 -maxdepth 1 -type d \
-not -name '*.links' -and -not -name '*-status-mobile-*' \ -not -name '*.links' -and -not -name '*-status-mobile-*' \
| xargs nix copy --to ${NIX_SSH_REMOTE} | xargs nix copy \
--to ssh-ng://${params.NIX_CACHE_USER}@${params.NIX_CACHE_HOST}
""", """,
pure: false pure: false
) )
@@ -127,11 +119,3 @@ pipeline {
} } } }
} }
} }
def nixSysOverride(os, arch, target='android') {
return (
os == 'Darwin' &&
arch == 'arm64' &&
target =~ /.*android$/
) ? 'x86_64-darwin' : ''
}
+7 -5
View File
@@ -1,15 +1,17 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
agent { label 'linux' } agent { label 'linux' }
environment { environment {
LANG = 'en_US.UTF-8' LANG = 'en_US.UTF-8'
LANGUAGE = 'en_US.UTF-8' LANGUAGE = 'en_US.UTF-8'
LC_ALL = 'en_US.UTF-8' LC_ALL = 'en_US.UTF-8'
PLATFORM = 'ios' TARGET = 'ios'
FASTLANE_DISABLE_COLORS = 1 FASTLANE_DISABLE_COLORS = 1
/* See nix/README.md */
NIX_IGNORE_SYMLINK_STORE = 1
/* avoid writing to r/o /nix */ /* avoid writing to r/o /nix */
GEM_HOME = '~/.rubygems' GEM_HOME = '~/.rubygems'
} }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy #!/usr/bin/env groovy
library 'status-jenkins-lib@v1.8.12' library 'status-jenkins-lib@v1.7.15'
pipeline { pipeline {
agent { agent {
-4
View File
@@ -10,8 +10,6 @@
[Coding guidelines](new-guidelines.md) [Coding guidelines](new-guidelines.md)
[UI components coding guidelines](ui-guidelines.md)
[Release Checklist](release-checklist.md) [Release Checklist](release-checklist.md)
[Release Guide](release-guide.md) [Release Guide](release-guide.md)
@@ -30,8 +28,6 @@
[Contributing to status-go](status-go-changes.md) [Contributing to status-go](status-go-changes.md)
[Malli schemas (recorded demo)](https://www.youtube.com/watch?v=SlRio70aYVI) ([slides](files/forging-code-with-schemas-sep-2023-slides.pdf))
## Testing ## Testing
[How to run local tests](testing.md) [How to run local tests](testing.md)
+5 -5
View File
@@ -16,10 +16,10 @@ Both of these links are showing it for React-Testing-Library (not Native) howeve
## Running the tests ## Running the tests
To run these tests there are two methods. To run these tests there are two methods.
`make test-component` `make component-test`
setups and runs the test suite once. setups and runs the test suite once.
`make test-component-watch` `make component-test-watch`
setups and runs the test suite and watches for code changes will then retrigger the test suite. setups and runs the test suite and watches for code changes will then retrigger the test suite.
## Writing Tests ## Writing Tests
@@ -38,7 +38,7 @@ There is a file of utility functions defined in "src/test_helpers/component.cljs
## Configuration ## Configuration
Status Mobile has a bespoke tech stack, as such there is more complexities to configuring the tests. Status Mobile has a bespoke tech stack, as such there is more complexities to configuring the tests.
### Shadow-CLJS ### Shadow-CLJS
the configuration for compiling our tests are defined in the "shadow-cljs.edn" file. the configuration for compiling our tests are defined in the "shadow-cljs.edn" file.
The three main parts of this are The three main parts of this are
`:target :npm-module` `:target :npm-module`
@@ -47,9 +47,9 @@ Needed for the configuration we are using
a vector of entry points for the test files. a vector of entry points for the test files.
and the `ns-regexp` to specify what tests to find. Since we have multiple forms of tests we decided that "component-spec" is the least likely to detect the wrong file type. and the `ns-regexp` to specify what tests to find. Since we have multiple forms of tests we decided that "component-spec" is the least likely to detect the wrong file type.
It's worth knowing that our tests are compiled to JS and then run in the temporary folder `component-tests`. It's worth knowing that our tests are compiled to JS and then run in the temporary folder `component-tests`.
### Jest ### Jest
There is also further configuration for Jest in "test/jest". There is a jest config file which has some mostly standard configuration pieces, where the tests live, what environment variables are set etc. This is documented by Jest here: https://jestjs.io/docs/configuration There is also further configuration for Jest in "test/jest". There is a jest config file which has some mostly standard configuration pieces, where the tests live, what environment variables are set etc. This is documented by Jest here: https://jestjs.io/docs/configuration
There is also a setup file which is used to set some global and default values. Additionally this file is used to mock some of the react native (among other) dependencies. There is also a setup file which is used to set some global and default values. Additionally this file is used to mock some of the react native (among other) dependencies
+17 -7
View File
@@ -20,6 +20,12 @@ required by bignumber.js otherwise there is a compilation error
used to generate guids and random values in `status-im.utils.random` used to generate guids and random values in `status-im.utils.random`
## "create-react-class": "15.6.2"
fixed version because even bugfix update causes compilation error with current version of react-native (0.59)
internal react library, used by figwheel for instance but also probably react
## "emojilib": "^2.4.0" ## "emojilib": "^2.4.0"
used for emojis used for emojis
@@ -107,6 +113,11 @@ used for profile picture
used for storing password when user saves password used for storing password when user saves password
TODO: check if fork is necessary, merge with upstream? TODO: check if fork is necessary, merge with upstream?
## "react-native-languages": "^3.0.2"
TODO DEPRECATED, should be replaced with https://github.com/react-native-community/react-native-localize
used to get user language and interact with i18n.js
## "react-native-mail": "git+https://github.com/status-im/react-native-mail.git#v3.0.8_status" ## "react-native-mail": "git+https://github.com/status-im/react-native-mail.git#v3.0.8_status"
used to send email to support when phone is shaked used to send email to support when phone is shaked
@@ -120,7 +131,6 @@ TODO: update once bug is fixed for Android that causes crash when app is back fr
## "react-native-shake": "^3.3.1" ## "react-native-shake": "^3.3.1"
used to send email to support when phone is shaked used to send email to support when phone is shaked
## "react-native-lottie-splash-screen": "^1.0.1" ## "react-native-lottie-splash-screen": "^1.0.1"
used to make splash screen with lottie animation during initial loading for android, also used as replacement of "react-native-splash-screen" for iOS used to make splash screen with lottie animation during initial loading for android, also used as replacement of "react-native-splash-screen" for iOS
@@ -134,9 +144,9 @@ used for keycard
used for svg icons, mostly collectibles are using svg used for svg icons, mostly collectibles are using svg
TODO: updating requires a pod update on iOS TODO: updating requires a pod update on iOS
## "react-native-biometrics": "^3.0.1" ## "react-native-touch-id": "^4.4.1"
used for biometric authentication on Android and iOS used for touch-id identification
## "react-native-webview": "git+https://github.com/status-im/react-native-webview.git#v8.0.7_3" ## "react-native-webview": "git+https://github.com/status-im/react-native-webview.git#v8.0.7_3"
@@ -147,10 +157,10 @@ used for browser
used for native navigation used for native navigation
fixed because even bugfix version upgrade causes runtime errors with current version of react-native fixed because even bugfix version upgrade causes runtime errors with current version of react-native
## "rn-emoji-keyboard": "https://github.com/status-im/rn-emoji-keyboard"
Used for taking emoji input, for custom emoji thumbnails for community channels
## "react-native-draggable-flatlist": "https://github.com/computerjazz/react-native-draggable-flatlist" ## "react-native-draggable-flatlist": "https://github.com/computerjazz/react-native-draggable-flatlist"
A drag-and-drop-enabled FlatList component for React Native A drag-and-drop-enabled FlatList component for React Native
## "react-native-shadow-2": "https://github.com/SrBrahma/react-native-shadow-2"
A shadow component that is consistent across both platforms
+2 -1
View File
@@ -122,9 +122,10 @@ See below:
Do the following: Do the following:
Ensure you have 2 terminals running the following Ensure you have 3 terminals running the following
- `make run-clojure` - `make run-clojure`
- `make run-metro`
- `make run-ios` / `make run-android` - `make run-ios` / `make run-android`
[See the STARTING GUIDE for details](STARTING_GUIDE.md#development) [See the STARTING GUIDE for details](STARTING_GUIDE.md#development)
+5 -56
View File
@@ -212,15 +212,16 @@ Properties must be set on view level
:bottom 0} :bottom 0}
``` ```
### Animated styles in the style file ### Apply animated styles in the style file
```clojure ```clojure
;; bad ;; bad
(defn circle (defn circle
[] []
(let [opacity (reanimated/use-shared-value 1)] (let [opacity (reanimated/use-shared-value 1)]
[reanimated/view {:style [{:opacity opacity} [reanimated/view {:style (reanimated/apply-animations-to-style
style/circle-container]}])) {:opacity opacity}
style/circle-container)}]))
;; good ;; good
(defn circle (defn circle
@@ -229,38 +230,6 @@ Properties must be set on view level
[reanimated/view {:style (style/circle-container opacity)}])) [reanimated/view {:style (style/circle-container opacity)}]))
``` ```
### Pass a vector of styles to Reanimated view
Prefer to pass a vector of styles to `react-native.reanimated/view` `:style`
prop instead of using `apply-animations-to-style` directly. For more details, check out Reanimated docs about [inline
styles](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/your-first-animation/#defining-a-shared-value)
and [useAnimatedStyle](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/animating-styles-and-props/#animating-styles).
```clojure
(defn f-view []
(let [scroll-x (reanimated/use-shared-value 0)
opacity (reanimated/interpolate scroll-x [0 45 50] [1 1 0])]
[reanimated/view
;; bad
{:style (reanimated/apply-animations-to-style
{:opacity opacity
:transform [{:translate-x scroll-x}]}
{:flex-direction :row})}
;; good
{:style [{:opacity opacity
:transform [{:translate-x scroll-x}]}
{:flex-direction :row}]}
;; other valid and good variants
{:style [{:opacity opacity}
{:transform [{:translate-x scroll-x}]}
{:flex-direction :row}]}
{:style {:opacity opacity
:transform [{:translate-x scroll-x}]
:flex-direction :row}}]))
```
### Don't use percents to define width/height ### Don't use percents to define width/height
In ReactNative, all layouts use the [flexbox In ReactNative, all layouts use the [flexbox
@@ -672,26 +641,6 @@ keywords and concatenating them into a single string.
``` ```
### Tests ### Tests
#### Prefer `match?` over `=` when comparing data structures
Prefer the `match?` directive over `=` when comparing data structures, otherwise
when the check fails the output can be too difficult to read. `match?` is
defined by library https://github.com/nubank/matcher-combinators.
```clojure
;; bad
(deftest some-test
(let [expected {...}
actual {...}]
(is (= expected actual))))
;; good
(deftest some-test
(let [expected {...}
actual {...}]
(is (match? expected actual))))
```
#### Subscription tests #### Subscription tests
Test [layer-3 subscriptions](https://day8.github.io/re-frame/subscriptions/) by Test [layer-3 subscriptions](https://day8.github.io/re-frame/subscriptions/) by
@@ -767,7 +716,7 @@ src
- `src/js`: Raw Javascript files, e.g. React Native Reanimated worklets. - `src/js`: Raw Javascript files, e.g. React Native Reanimated worklets.
- `src/mocks`: Plumbing configuration to be able to run tests. - `src/mocks`: Plumbing configuration to be able to run tests.
- `src/quo/`: The component library for Status Mobile. [Read more...](../src/quo/README.md) - `src/quo/`: The component library for Status Mobile.
- `src/react_native/`: Contains only low-level constructs to help React Native - `src/react_native/`: Contains only low-level constructs to help React Native
work in tandem with Clojure(Script). work in tandem with Clojure(Script).
- `src/status_im2/`: Directory where we try to be as strict as possible about - `src/status_im2/`: Directory where we try to be as strict as possible about
+22 -55
View File
@@ -2,80 +2,46 @@
[Pipeline for QA](https://github.com/status-im/status-mobile/projects/7) is a project board for developers and testers used to track the status of a pull request, get reviews and manual testing, and run autotests. [Pipeline for QA](https://github.com/status-im/status-mobile/projects/7) is a project board for developers and testers used to track the status of a pull request, get reviews and manual testing, and run autotests.
The generally accepted requirements for its use are described below: The generally accepted recommendations for its use are described below:
## Opening a PR ## Opening a PR
- Once a PR is created, it moves to the ```REVIEW``` column where a review will be requested automatically. - Once a PR is created, it moves to the ```REVIEW``` column where a review will be requested automatically.
- You can also request a review inside the PR from a particular person if needed. - You can also request a review inside the PR from a particular person if needed.
- When creating a PR, do not forget to assign it to yourself. - When creating a PR, do not forget to assign it to yourself.
- Also in case the PR adds new functionality, a description **MUST** be added. - Also in case the PR adds new functionality, a short description would be appreciated.
### What if the work is still in progress? ### What if the work is still in progress?
- If PR work is not finished yet, please mark it as a draft or add [WIP] to the title and keep it in the `CONTRIBUTOR` column until it's ready to be reviewed/tested. - If PR work is not finished yet, please mark it as a draft or add [WIP] to the title and keep it in the `CONTRIBUTOR` column until it's ready to be reviewed/tested.
- Alternatively, you can open a `draft`.
### When is a PR considered ready to move forward?
Ready for testing, a PR should meet the following criteria:
1. Reviewed and has at least 1 approval.
2. Rebased to the `develop` branch (both `status-mobile` and `status-go` if needed, depending on what part has changes).
- **NOTE:** QAs can use the `Update with rebase` button from GitHub if:
- The PR has no `status-go` changes.
- The PR has no conflict with the develop branch.
3. All possible conflicts have been resolved.
4. Has the label: `request-manual-qa` or `skip-manual-qa`.
5. PRs **MUST** identify what area is affected and should have a description.
### E2E tests and analyzing the results ### When is a PR considered to be Ready for testing by QA team? 


Ready for testing PR should meet the following criteria:
The PR **MUST** be moved to the E2E column when it is ready for testing (**mandatory for all PRs**). 1. Reviewed and has at least 1 approval
That will also trigger e2e tests run. QAs are monitoring PRs from E2E column and take it into test. 2. Rebased to `develop` branch (both `status-mobile` and `status-go` if needed, depending on what part has changes)
This step cannot be skipped. So, at least one comment from the `status-im-auto` bot with results is a prerequisite for moving forward. 3. All possible conflicts have been resolved
Information on how to analyze tests can be found [here](https://github.com/status-im/status-mobile/blob/develop/doc/how-to-launch-e2e.md). 4. Has the label: `request-manual-qa`
Tests might be flaky, as they depend on infrastructure - SauceLabs and Waku.
If there are `Failed tests` and you are not sure about the reason, you can always ping the mobile QAs for help (preferably in PRs by `@status-im/mobile-qa`). **From the perspective of a developer it means that once work on PR is finished:**
**For now, it is the only reliable source of regression in the app because, due to time constraints, it is not possible to test thoroughly each PR. 1. It should be rebased to the latest `develop`. If there are conflicts - they should be resolved if possible.
Please, respect this rule.** 2. If the PR was in the `Contributor` column - it should be moved to `Review` column.
3. Wait for the review.
4. Make sure that after review and before requesting manual QA your PR is rebased to current develop.
5. Once the PR has been approved by reviewer(s) - label `request-manual-qa` should be applied to the PR
6. Move PR to the E2E column when it is ready for testing (**mandatory for all PRs**). That will also trigger e2e tests run. QAs are monitoring PRs from E2E column and take it into test.
After that - PR will be taken into manual testing by the QA team.
## Testing PR ## Testing PR
### Adding `skip-manual-qa`
**Do not hesitate to use a `skip-manual-qa`** if you're sure that it is a simple flow and you checked it.
- Please ask another team member before adding the `skip-manual-qa` label (PR/Status community/DMs) so that there's a second opinion.
- The PR MUST have a proper reasoning why manual QA is skipped.
- The PR MUST include the steps of testing that has been done by the developer prior to moving it forward.
**NOTE:** Make sure that QAs are OK with that;
Before merging PRs, please make sure that information is added about how you tested the PRs, that e2s have been passed and their results have been reviewed.
The QA team appreciates your help!
### Manual testing ### Manual testing
- If you think PR needs and is ready for manual testing, please add the ```request-manual-qa``` label.
#### Prerequisites for manual testing
1. PR has a description of the change and details the area of the application affected by the change.
2. PR has automation results from the previous E2E test run step.
3. PR includes a demo, test steps, and any possible regression(s)
4. If appropriate, PR details what elements of a feature are out of scope.
**If one of the prerequisites is missing, the PR will be moved to the contributor folder with a corresponding comment.**
- If you think a PR needs and is ready for manual testing, please add the `request-manual-qa` label.
- QA engineer picks up one of PRs with the ```request-manual-qa``` label, drags the item to the ```IN TESTING``` column and assigns it to themselves. - QA engineer picks up one of PRs with the ```request-manual-qa``` label, drags the item to the ```IN TESTING``` column and assigns it to themselves.
- During testing, QA will add comments describing the issues found, and also review automation tests results. - During testing, QA will add comments describing the issues found, and also review automation tests results.
Usually found issues are numbered as "Issue 1, Issue 2", etc. Usually found issues are numbered as "Issue 1, Issue 2", etc.
When the first round of testing is completed and all issues for this stage are found, the QA can add the ```Tested - Issues``` label and drag the card to the ```CONTRIBUTOR``` column. These two actions are optional. When the first round of testing is completed and all issues for this stage are found, the QA can add the ```Tested - Issues``` label and drag the card to the ```CONTRIBUTOR``` column. These two actions are optional.
**IMPORTANT NOTE:** when the issues are fixed, developer **MUST** notify the QA that it is ready to be re-tested again by mention them in the PR.
- When manual testing of the PR is fully completed and all the issues are fixed, the QA adds the ```Tested - OK``` label and drags the card to the ```Design review``` column (the cases when design review is necessary are described below). - When manual testing of the PR is fully completed and all the issues are fixed, the QA adds the ```Tested - OK``` label and drags the card to the ```Design review``` column (the cases when design review is necessary are described below).
- If design review is not required, the QA drags the PR to the ```MERGE``` column. After that the developer merges PR into develop. - If design review is not required, the QA drags the PR to the ```MERGE``` column. After that the developer merges PR into develop.
- If design review has been done, the designer (```@Francesca-G```) drags the PR to the ```MERGE``` column. - If design review has been done, the designer (```@Francesca-G```) drags the PR to the ```MERGE``` column.
@@ -98,11 +64,11 @@ There are three possible scenarios when the design review is completed:
--- ---
**Notes:** **Notes:**
- If your PR has a long story and started from `develop` branch several days ago, please rebase it to current develop before adding label - If your PR has a long story and started from `develop` branch several days ago, please rebase it to current develop before adding label
- if PR can be tested by developer (in case of small changes) and/or developer is sure that the changes made cannot introduce a regression, then PR can be merged without manual testing. Also, currently, PRs are not manually tested if the changes relate only the design (creation of components, etc.) and do not affect the functionality (see `skip-manual-qa` label) - if PR can be tested by developer (in case of small changes) and/or developer is sure that the changes made cannot introduce a regression, then PR can be merged without manual testing. Also, currently, PRs are not manually tested if the changes relate only the design (creation of components, etc.) and do not affect the functionality.
--- ---
#### Why my PR is in `Contributor` column? #### Why my PR is in `Contributor` column?
PR can be moved to this column by the ```status-github-bot``` or by QA engineer with label `Tested-issues` or if one of the requirements for manual QA was not met. PR can be moved to this column by the ```status-github-bot``` or by QA engineer with label `Tested-issues`.
In the first case most often this happens due to conflicting files in PR. In the first case most often this happens due to conflicting files in PR.
In the second case - after fixing of all found issues, the developer should ping the QA in the PR comments for retesting. In the second case - after fixing of all found issues, the developer should ping the QA in the PR comments for retesting.
@@ -120,6 +86,7 @@ In the second case - after fixing of all found issues, the developer should ping
6. In case of manual testing - the label ```Tested - OK``` from QA 6. In case of manual testing - the label ```Tested - OK``` from QA
7. In case of design review - the approval from the designer 7. In case of design review - the approval from the designer
You can merge your PR into develop - some useful clues you can find [here](https://notes.status.im/setup-e2e#3-Merging-PR) You can merge your PR into develop - some useful clues you can find [here](https://notes.status.im/setup-e2e#3-Merging-PR)
HAPPY DEVELOPMENT! :tada: HAPPY DEVELOPMENT! :tada:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

+23 -37
View File
@@ -4,41 +4,22 @@ This document provides information on how to start developing Status App.
# Getting Started # Getting Started
To start developing clone the status-mobile repo in the directory of your choice. To start developing start a shell for the platform you are interested in.
``` ```
git clone https://github.com/status-im/status-mobile.git make shell TARGET=android
``` ```
This step will take a while the first time as it will download all dependencies.
Then open a terminal and cd into this directory. # Development
``` There are three steps necessary to start development, in this case for Android:
cd status-mobile
```
Then build the clojure terminal 1. `make run-clojure` - Compiles Clojure into JavaScript, watches for changes on cljs files, and hot-reloads code in the app.
2. `make run-metro` - Starts metro bundler and watches JavaScript code.
3. `make run-android` or `make run-ios` - Builds the Android/iOS app and starts it on the device.
``` The first two will continue watching for changes and keep re-building the app. They need to be ready first.
make run-clojure The last one will exit once the app is up and ready.
```
note: ⚠️ This might take a while if this is your first time.
This command installs `nix` and pulls in all the dependencies.
Do answer with "Y" to all the prompts and press "Enter" when `nix` setup asks you to Acknowledge.
This command builds the `jsbundle` and then compiles `Clojure` into `JavaScript`, watches for changes on `cljs` files, and hot-reloads code in the app.
wait till you see the following message :
```
[:mobile] Build completed. (1801 files, 52 compiled, 0 warnings, 9.52s)
```
Once the clojure terminal is running you need to run the appropriate command next for your platform in a separate terminal :
`make run-android` or `make run-ios`
These commands will build the app, start a metro bundler and deploy the app on your simulator OR connected device (android only). For building and deploying to connected iPhones use `make run-ios-device` instead of `make run-ios`
Also check [developing on a physical iOS Device](#Additional-requirements-for-developing-on-physical-ios-device).
## Simulators and Devices ## Simulators and Devices
### Android ### Android
@@ -65,9 +46,13 @@ Running `make run-ios` will target `iPhone 13` by default.
If you need to run on any other simulator, you can specify the simulator type by adding the `SIMULATOR` flag: If you need to run on any other simulator, you can specify the simulator type by adding the `SIMULATOR` flag:
```sh ```sh
make run-ios SIMULATOR="iPhone 15" make run-ios SIMULATOR="iPhone 13"
``` ```
#### Running on a physical device
Some manual steps are necessary for [developing on a physical iOS Device](#physical-ios-device).
# Build release # Build release
To build the app, you can simply run on of the following: To build the app, you can simply run on of the following:
@@ -117,15 +102,16 @@ Steps:
3. [Setup Git to sign commits](https://help.github.com/en/github/authenticating-to-github/signing-commits) 3. [Setup Git to sign commits](https://help.github.com/en/github/authenticating-to-github/signing-commits)
4. [Setup GitHub to validate commits](https://help.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account) 4. [Setup GitHub to validate commits](https://help.github.com/en/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account)
## Additional requirements for developing on Physical iOS Device ## Physical iOS Device
To use a physical iPhone your device UDID must be added to provisioning profiles and your Apple account invited as Developer to Status team. To use a physical iPhone your device UDID must be added to provisioning profiles and your Apple account invited as Developer to Status team.
1. [Get your UDID of your iPhone.](https://www.extentia.com/post/finding-the-udid-of-an-ios-device) 1. [Get your UDID of your iPhone.](https://www.extentia.com/post/finding-the-udid-of-an-ios-device)
2. Request from someone with access like @cammellos or @jakubgs to 2. Request from someone with access like @cammellos or @jakubgs to
- Add the UDID to development devices on Apple Developer Portal. - Add the UDID to development devices on Apple Developer Portal.
- Invite your Apple account to be Developer in Status team. - Invite your Apple account to be Developer in Status team.
3. Open XCode using the project from `status-mobile/ios` directory. 3. Run a build in XCode using the project from `status-mobile/ios` directory.
- You might see error: `Select a development team in the Signing & Capabilities editor` - You might see error: `Select a development team in the Signing & Capabilities editor`
- Select `Status Research & Development GmbH` as the development team. - Select `Status Research & Development GmbH` as the development team and rebuild again.
4. In a new terminal execute `make clean` and then `make xcode-clean`
Once build finishes Status should start on your iPhone with its logs in terminal running `make run-metro`.
+9 -35
View File
@@ -2,19 +2,21 @@
## Unit & integration tests ## Unit & integration tests
To run all tests: To run tests:
``` ```
make test make test
``` ```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified Also test watcher can be launched. It will re-run the entire test suite when any file is modified
``` ```
make test WATCH=true make test-watch
``` ```
Developers can also manually change the shadow-cljs option `:ns-regex` to control which namespaces the test runner should pick. Developers can also manually change the shadow-cljs option `:ns-regex` to control which namespaces the test runner should pick.
## Testing with REPL ## Testing with REPL
@@ -49,46 +51,18 @@ Here I'm showing a terminal-only experience using Tmux (left pane Emacs, right p
[2022-12-19 13-17.webm](https://user-images.githubusercontent.com/46027/208471199-1909c446-c82d-42a0-9350-0c15ca562713.webm) [2022-12-19 13-17.webm](https://user-images.githubusercontent.com/46027/208471199-1909c446-c82d-42a0-9350-0c15ca562713.webm)
## Component tests only ## Component tests
To run tests: To run tests:
``` ```
make test-component make component-test
``` ```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified Also test watcher can be launched. It will re-run the entire test suite when any file is modified
``` ```
make test-component-watch make component-test-watch
``` ```
Check [component tests doc](./component-tests-overview.md) for more. Check [component tests doc](./component-tests-overview.md) for more.
## Unit tests only
To run unit tests:
```
make test-unit
```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
make test-unit WATCH=true
```
## Integration tests only
To run integration tests:
```
make test-integration
```
Also test watcher can be launched. It will re-run the entire test suite when any file is modified
```
make test-integration WATCH=true
```
+14 -11
View File
@@ -88,7 +88,6 @@ info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this
Update yarn.lock file. In order to do this, perform the following steps on a clean `status-mobile` repo: Update yarn.lock file. In order to do this, perform the following steps on a clean `status-mobile` repo:
``` ```
cd status-mobile cd status-mobile
make shell
yarn install yarn install
``` ```
and don't forget to commit updated `yarn.lock` together with `package.json`. and don't forget to commit updated `yarn.lock` together with `package.json`.
@@ -129,18 +128,22 @@ Status-mobile uses `shadow-cljs` for hot reloading changes and uses its own [rel
### Solution ### Solution
Open react native's [In-App Developer Menu](https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu) and press "Disable Fast Refresh" or "Disable Hot Reloading" Open react native's [In-App Developer Menu](https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu) and press "Disable Fast Refresh" or "Disable Hot Reloading"
# App crashing after running `make run-ios` ## App Crashes after few reloads
### Cause ### Cause
It's possible that installing XCode from a `.xip` file might cause XCode to act funny For x86 CPU architecture Android Devices, Hermes is creating the issue and the app crashes after a few reloads.
Since it's not installed from the App Store, Or you might be missing a Rosetta installation. ([Original Issue](https://github.com/status-im/status-mobile/issues/14031))
[Reference/Similar issue](https://github.com/expo/expo-cli/issues/3197) <details>
<summary>How to Find CPU architecture</summary>
CPU architecture of android device can be found using
- `adb shell uname -m` or
- `adb shell getprop ro.product.cpu.abilist`
</details>
You might see something like this after running `make run-ios`:
```
Underlying error (domain=FBSOpenApplicationServiceErrorDomain, code=1):
```
### Solution ### Solution
Run `softwareupdate --install-rosetta --agree-to-license` Disable Hermes while building the app
to accept XCode's license and install Rosetta.
`make run-android DISABLE_HERMES=true`
-254
View File
@@ -1,254 +0,0 @@
# UI components coding guidelines
> [!IMPORTANT]
> React apps are made out of components. A component is a piece of the UI (user interface) that has its own logic and appearance. A component can be as small as a button, or as large as an entire screen.
> React components are JavaScript functions that return markup
> This document will provide best practices on how to write efficient React components in ClojureScript
At the time of creating the Status app, the Reagent library was a solid choice. Back then, hooks didn't exist, and there weren't any libraries providing effective global state management. After Reagent's emergence, another library called Re-frame built upon Reagent. Together, they offered powerful tools for developing React applications with ClojureScript. However, as React evolved, significant changes occurred. Class components, utilized in Reagent, became deprecated. Instead, functional components and hooks emerged for state management. In Status 2.0, we began incorporating more functional components and hooks, resulting in a blend of both approaches. To simplify matters and reduce confusion, we opted to transition to functional components and hooks for local state management.
BEFORE:
```clojure
(defn- view-internal
[_ _]
(let [pressed? (reagent/atom false)]
(fn
[{:keys [theme on-press on-long-press icon]}]
[rn/pressable
{:style (style/main @pressed? theme)
:on-press on-press
:on-press-in #(reset! pressed? true)
:on-press-out #(reset! pressed? nil)
:on-long-press on-long-press}
[quo.icons/icon icon]])))
(def view (theme/with-theme view-internal))
```
NOW:
```clojure
(defn view
[{:keys [on-press on-long-press icon]}]
(let [[pressed? set-pressed] (rn/use-state false)
theme (theme/use-theme-value)
on-press-in (rn/use-callback #(set-pressed true))
on-press-out (rn/use-callback #(set-pressed nil))]
[rn/pressable
{:style (style/main pressed? theme)
:on-press on-press
:on-press-in on-press-in
:on-press-out on-press-out
:on-long-press on-long-press}
[quo.icons/icon icon]]))
```
- We no longer need to create an anonymous function for rendering. This removes unnecessary confusion and the need for specific knowledge on how it works and why it was needed.
- `rn/use-state` is used instead of `reagent/atom`
- State values no longer need to be dereferenced; they are accessible as regular symbols. This eliminates a common bug where the "@" symbol was inadvertently omitted.
- `theme/with-theme` wrapper is not needed anymore, `(theme/use-theme-value)` hook can be used directly in the components
- `:f>` not needed anymore, all components are functional by default
- `rn/use-callback` hook should be used for anon callback functions
> [!IMPORTANT]
> DO NOT USE anon functions directly in the props
BAD
```clojure
(defn view
[]
(let [[pressed? set-pressed] (rn/use-state false)]
[rn/pressable
{:style (style/main pressed?)
:on-press-in #(set-pressed true)
:on-press-out #(set-pressed nil)}]))
```
GOOD:
```clojure
(defn view
[]
(let [[pressed? set-pressed] (rn/use-state false)
on-press-in (rn/use-callback #(set-pressed true))
on-press-out (rn/use-callback #(set-pressed nil))]
[rn/pressable
{:style (style/main pressed?)
:on-press-in on-press-in
:on-press-out on-press-out}]))
```
## Global state and subscriptions
For global state management, we utilize Re-frame subscriptions. They can be likened to React state. To obtain the state, `(rf/sub [])` is employed, and to modify it, `(rf/dispatch [])` is utilized. However, they update components in a similar manner to React states.
```clojure
(defn view
[{:keys [selected-tab]}]
(let [collectible-list (rf/sub [:wallet/all-collectibles])
on-collectible-press (rn/use-callback
(fn [{:keys [id]}]
(rf/dispatch [:wallet/get-collectible-details id])))]
[rn/view {:style style/container}
(case selected-tab
:assets [assets/view]
:collectibles [collectibles/view {:collectibles collectible-list
:on-collectible-press on-collectible-press}])
[activity/view]]))
```
## Regular atoms
In certain instances, components utilized regular atoms; however, they should now be used with `rn/use-ref-atom`
BEFORE:
```clojure
(defn view
[]
(let [focused? (atom false)]
(fn []
(let [on-clear #(reset! status (if @focused? :active :default))
on-focus #(reset! focused? true)
on-blur #(reset! focused? false)]))))
```
NOW:
```clojure
(defn view
[]
(let [focused? (rn/use-ref-atom false)
on-clear (rn/use-callback #(set-status (if @focused? :active :default)))
on-focus (rn/use-callback #(reset! focused? true))
on-blur (rn/use-callback #(reset! focused? false))]))
```
## Effects
LIFECYCLE:
```clojure
(defn view
[{:keys []}]
(let [opacity (reanimated/use-shared-value 0)]
(rn/use-mount #(reanimated/animate opacity 1))
[rn/view
{:style (style/opacity opacity)}]))
```
```clojure
(defn view
[{:keys []}]
(let []
(rn/use-unmount #(rn/dispatch [:unmounted]))
[rn/view]))
```
> [!IMPORTANT]
> Effects should NOT be utilized as a response to state changes for modifying logic. If you're unsure how to achieve this without using effects, please consult the team in the general chat. There may be instances where using effects is appropriate, so we can explore a solution together and enhance our guidelines.
BAD:
```clojure
(defn f-zoom-button
[{:keys [selected? current-zoom]}]
(let [size (reanimated/use-shared-value (if selected? 37 25))]
(rn/use-effect #(reanimated/animate size (if selected? 37 25)) [current-zoom])
[rn/touchable-opacity
{:style (style/zoom-button-container size)}]))
```
BAD:
```clojure
(defn view
[collectible-list (rf/sub [:wallet/all-collectibles])]
(let []
(rn/use-effect #(rn/dispatch [:all-collectibles-changed]) [collectible-list])
[rn/view]))
```
Instead `:all-collectibles-changed` should be used in the handler which changes `collectible-list` state
## Performance tips
To begin with, we need to understand that there are two distinct stages for a component: creation and update. React creates a render tree, a UI tree, composed of the rendered components.
![react_tree.png](react_tree.png)
### Component creation
For component creation, the most critical factor is the number of elements involved, so we should strive to minimize them. For instance, it's advisable to avoid using unnecessary wrappers or containers.
BAD:
```clojure
(defn view
[]
(let []
[rn/view {:style {:padding-top 20}}
[quo/button]]))
```
GOOD:
```clojure
(defn view
[]
(let []
[quo/button {:container-style {:padding-top 20}}]))
```
### Component updates
For component updates, it's crucial to recognize that React will invoke the function where state is utilized. Therefore, if you utilize state in the root component, React will execute the root function and re-render the entire root component along with all its children (unless optimizations like memoization are implemented).
BAD:
```clojure
(defn component
[{:keys [label]}]
(let []
[rn/text label]))
(defn component2
[{:keys [label2]}]
(let []
[rn/text label2]))
(defn screen
[]
(let [screen-params (rf/sub [:screen-params])]
[component screen-params]
[component1]
[component2 screen-params]
[component3]
[rn/view {:padding-top 20}
[quo/button]]))
```
Here, we have lost control over the `screen-params` map. It can contain any data, and if any field within this map changes, the entire screen function will be executed, resulting in the re-rendering of both `component` and `component2`.
GOOD:
```clojure
(defn component
[]
(let [label (rf/sub [:screen-params-label])]
[rn/text label]))
(defn component2
[]
(let [label2 (rf/sub [:screen-params-label2])]
[rn/text label2]))
(defn screen
[]
(let []
[component]
[component1]
[component2]
[component3]
[rn/view {:padding-top 20}
[quo/button]]))
```
So, now the screen component function will never be invoked, and `component` and `component2` will be re-rendered only when `label` or `label2` have changed.
+4 -5
View File
@@ -1,5 +1,4 @@
# This file contains the fastlane.tools configuration # This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools # You can find the documentation at https://docs.fastlane.tools
# #
# For a list of all available actions, check out # For a list of all available actions, check out
@@ -97,7 +96,7 @@ end
# if false - read list of devices from AppStoreConnect, and upgrade the provisioning profiles from it # if false - read list of devices from AppStoreConnect, and upgrade the provisioning profiles from it
# `pr_build`: # `pr_build`:
# if true - uses StatusImPR scheme and postfixed app id with `.pr` to build an app, which can be used in parallel with release # if true - uses StatusImPR scheme and postfixed app id with `.pr` to build an app, which can be used in parallel with release
# if false - uses StatusIm scheme to build the release app # if false - uses StatusIm scheme to build the release app
def build_ios_adhoc(readonly: false, pr_build: false) def build_ios_adhoc(readonly: false, pr_build: false)
# PR builds should appear as a separate App on iOS # PR builds should appear as a separate App on iOS
@@ -124,7 +123,7 @@ def build_ios_adhoc(readonly: false, pr_build: false)
export_method: 'ad-hoc', export_method: 'ad-hoc',
output_name: 'StatusIm', output_name: 'StatusIm',
output_directory: 'status-ios', output_directory: 'status-ios',
buildlog_path: 'logs', buildlog_path: 'ios/logs',
export_options: { export_options: {
signingStyle: 'manual', signingStyle: 'manual',
provisioningProfiles: { provisioningProfiles: {
@@ -164,7 +163,7 @@ def build_ios_e2e
# 3. directory where to up StatusIm.app # 3. directory where to up StatusIm.app
derived_data_path: 'status-ios', derived_data_path: 'status-ios',
output_name: 'StatusIm.app', output_name: 'StatusIm.app',
buildlog_path: 'logs', buildlog_path: 'ios/logs',
# ------------------------------------- # -------------------------------------
# Normal stuff # Normal stuff
scheme: 'StatusIm', scheme: 'StatusIm',
@@ -231,7 +230,7 @@ platform :ios do
clean: true, clean: true,
export_method: 'app-store', export_method: 'app-store',
output_directory: 'status-ios', output_directory: 'status-ios',
buildlog_path: 'logs', buildlog_path: 'ios/logs',
include_symbols: false, include_symbols: false,
export_options: { export_options: {
"combileBitcode": true, "combileBitcode": true,
-1
View File
@@ -1,4 +1,3 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
gem 'fastlane', '>= 2.131.0' gem 'fastlane', '>= 2.131.0'
+51 -60
View File
@@ -3,30 +3,25 @@ GEM
specs: specs:
CFPropertyList (3.0.6) CFPropertyList (3.0.6)
rexml rexml
activesupport (7.0.8) addressable (2.8.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0) public_suffix (>= 2.0.2, < 6.0)
artifactory (3.0.15) artifactory (3.0.15)
atomos (0.1.3) atomos (0.1.3)
aws-eventstream (1.3.0) aws-eventstream (1.2.0)
aws-partitions (1.872.0) aws-partitions (1.768.0)
aws-sdk-core (3.190.1) aws-sdk-core (3.173.0)
aws-eventstream (~> 1, >= 1.3.0) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0) aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8) aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1) jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.75.0) aws-sdk-kms (1.64.0)
aws-sdk-core (~> 3, >= 3.188.0) aws-sdk-core (~> 3, >= 3.165.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.141.0) aws-sdk-s3 (1.122.0)
aws-sdk-core (~> 3, >= 3.189.0) aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.8) aws-sigv4 (~> 1.4)
aws-sigv4 (1.8.0) aws-sigv4 (1.5.2)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4) babosa (1.0.4)
claide (1.1.0) claide (1.1.0)
@@ -34,14 +29,14 @@ GEM
colored2 (3.1.2) colored2 (3.1.2)
commander (4.6.0) commander (4.6.0)
highline (~> 2.0.0) highline (~> 2.0.0)
concurrent-ruby (1.2.2)
declarative (0.0.20) declarative (0.0.20)
digest-crc (0.6.5) digest-crc (0.6.4)
rake (>= 12.0.0, < 14.0.0) rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20231109) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1) dotenv (2.8.1)
emoji_regex (3.2.3) emoji_regex (3.2.3)
excon (0.108.0) excon (0.99.0)
faraday (1.10.3) faraday (1.10.3)
faraday-em_http (~> 1.0) faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0) faraday-em_synchrony (~> 1.0)
@@ -71,7 +66,7 @@ GEM
faraday_middleware (1.2.0) faraday_middleware (1.2.0)
faraday (~> 1.0) faraday (~> 1.0)
fastimage (2.2.7) fastimage (2.2.7)
fastlane (2.217.0) fastlane (2.212.2)
CFPropertyList (>= 2.3, < 4.0.0) CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0) addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0) artifactory (~> 3.0)
@@ -92,11 +87,10 @@ GEM
google-apis-playcustomapp_v1 (~> 0.1) google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31) google-cloud-storage (~> 1.31)
highline (~> 2.0) highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0) json (< 3.0.0)
jwt (>= 2.1.0, < 3) jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0) mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0) multipart-post (~> 2.0.0)
naturally (~> 2.2) naturally (~> 2.2)
optparse (~> 0.1.1) optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0) plist (>= 3.1.0, < 4.0.0)
@@ -104,7 +98,7 @@ GEM
security (= 0.1.3) security (= 0.1.3)
simctl (~> 1.6.3) simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3) terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0) tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0) word_wrap (~> 1.0.0)
@@ -112,9 +106,9 @@ GEM
xcpretty (~> 0.3.0) xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3) xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3) gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0) google-apis-androidpublisher_v3 (0.42.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.2) google-apis-core (0.11.0)
addressable (~> 2.5, >= 2.5.1) addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a) httpclient (>= 2.8.1, < 3.a)
@@ -127,26 +121,26 @@ GEM
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0) google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.29.0) google-apis-storage_v1 (0.19.0)
google-apis-core (>= 0.11.0, < 2.a) google-apis-core (>= 0.9.0, < 2.a)
google-cloud-core (1.6.1) google-cloud-core (1.6.0)
google-cloud-env (>= 1.0, < 3.a) google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0) google-cloud-errors (~> 1.0)
google-cloud-env (2.1.0) google-cloud-env (1.6.0)
faraday (>= 1.0, < 3.a) faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.3.1) google-cloud-errors (1.3.1)
google-cloud-storage (1.45.0) google-cloud-storage (1.44.0)
addressable (~> 2.8) addressable (~> 2.8)
digest-crc (~> 0.4) digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1) google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.29.0) google-apis-storage_v1 (~> 0.19.0)
google-cloud-core (~> 1.6) google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a) googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0) mini_mime (~> 1.0)
googleauth (1.9.1) googleauth (1.5.2)
faraday (>= 1.0, < 3.a) faraday (>= 0.17.3, < 3.a)
google-cloud-env (~> 2.1)
jwt (>= 1.4, < 3.0) jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11) multi_json (~> 1.11)
os (>= 0.9, < 2.0) os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a) signet (>= 0.16, < 2.a)
@@ -154,34 +148,32 @@ GEM
http-cookie (1.0.5) http-cookie (1.0.5)
domain_name (~> 0.5) domain_name (~> 0.5)
httpclient (2.8.3) httpclient (2.8.3)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jmespath (1.6.2) jmespath (1.6.2)
json (2.7.1) json (2.6.3)
jwt (2.7.1) jwt (2.7.0)
memoist (0.16.2)
mini_magick (4.12.0) mini_magick (4.12.0)
mini_mime (1.1.5) mini_mime (1.1.2)
minitest (5.20.0)
multi_json (1.15.0) multi_json (1.15.0)
multipart-post (2.3.0) multipart-post (2.0.0)
nanaimo (0.3.0) nanaimo (0.3.0)
naturally (2.2.1) naturally (2.2.1)
optparse (0.1.1) optparse (0.1.1)
os (1.1.4) os (1.1.4)
plist (3.7.0) plist (3.7.0)
public_suffix (5.0.4) public_suffix (5.0.1)
rake (13.1.0) rake (13.0.6)
representable (3.2.0) representable (3.2.0)
declarative (< 0.1.0) declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0) trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0) uber (< 0.2.0)
retriable (3.1.2) retriable (3.1.2)
rexml (3.2.6) rexml (3.2.5)
rouge (2.0.7) rouge (2.0.7)
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
rubyzip (2.3.2) rubyzip (2.3.2)
security (0.1.3) security (0.1.3)
signet (0.18.0) signet (0.17.0)
addressable (~> 2.8) addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a) faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0) jwt (>= 1.5, < 3.0)
@@ -190,20 +182,21 @@ GEM
CFPropertyList CFPropertyList
naturally naturally
terminal-notifier (2.0.0) terminal-notifier (2.0.0)
terminal-table (3.0.2) terminal-table (1.8.0)
unicode-display_width (>= 1.1.1, < 3) unicode-display_width (~> 1.1, >= 1.1.1)
trailblazer-option (0.1.2) trailblazer-option (0.1.2)
tty-cursor (0.7.1) tty-cursor (0.7.1)
tty-screen (0.8.2) tty-screen (0.8.1)
tty-spinner (0.9.3) tty-spinner (0.9.3)
tty-cursor (~> 0.7) tty-cursor (~> 0.7)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uber (0.1.0) uber (0.1.0)
unicode-display_width (2.5.0) unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
webrick (1.8.1) webrick (1.8.1)
word_wrap (1.0.0) word_wrap (1.0.0)
xcodeproj (1.23.0) xcodeproj (1.22.0)
CFPropertyList (>= 2.3.3, < 4.0) CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3) atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0) claide (>= 1.0.2, < 2.0)
@@ -216,12 +209,10 @@ GEM
xcpretty (~> 0.2, >= 0.0.7) xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS PLATFORMS
arm64-darwin-22 ruby
x86_64-darwin-22
DEPENDENCIES DEPENDENCIES
activesupport (>= 6.1.7.3, < 7.1.0)
fastlane (>= 2.131.0) fastlane (>= 2.131.0)
BUNDLED WITH BUNDLED WITH
2.4.13 2.3.9
+94 -115
View File
@@ -1,25 +1,14 @@
{ {
activesupport = {
dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "188kbwkn1lbhz40ala8ykp20jzqphgc68g3d8flin8cqa2xid0s5";
type = "gem";
};
version = "7.0.8";
};
addressable = { addressable = {
dependencies = ["public_suffix"]; dependencies = ["public_suffix"];
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0irbdwkkjwzajq1ip6ba46q49sxnrl2cw7ddkdhsfhb6aprnm3vr"; sha256 = "15s8van7r2ad3dq6i03l3z4hqnvxcq75a3h72kxvf9an53sqma20";
type = "gem"; type = "gem";
}; };
version = "2.8.6"; version = "2.8.4";
}; };
artifactory = { artifactory = {
groups = ["default"]; groups = ["default"];
@@ -46,20 +35,20 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0gvdg4yx4p9av2glmp7vsxhs0n8fj1ga9kq2xdb8f95j7b04qhzi"; sha256 = "1pyis1nvnbjxk12a43xvgj2gv0mvp4cnkc1gzw0v1018r61399gz";
type = "gem"; type = "gem";
}; };
version = "1.3.0"; version = "1.2.0";
}; };
aws-partitions = { aws-partitions = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1ddbcz8p3abbw8d8pn796z1ry1mbapl6ayhh37ziwal6bd047kvm"; sha256 = "1256rf6zjh3canwr636w7yczbvhh72cpz2fw5ixljbh4fcfkrvlm";
type = "gem"; type = "gem";
}; };
version = "1.872.0"; version = "1.768.0";
}; };
aws-sdk-core = { aws-sdk-core = {
dependencies = ["aws-eventstream" "aws-partitions" "aws-sigv4" "jmespath"]; dependencies = ["aws-eventstream" "aws-partitions" "aws-sigv4" "jmespath"];
@@ -67,10 +56,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1ansagfl5irx1y6b9xf4xpi9j6q6k5pbd2aw80hn0p4m3ycafamh"; sha256 = "10djgbz4k9w3axka8xrhf97h9yh9svi5g5xvncfwnkg6h22w2177";
type = "gem"; type = "gem";
}; };
version = "3.190.1"; version = "3.173.0";
}; };
aws-sdk-kms = { aws-sdk-kms = {
dependencies = ["aws-sdk-core" "aws-sigv4"]; dependencies = ["aws-sdk-core" "aws-sigv4"];
@@ -78,10 +67,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1qzxqfgrhnl5rdc39a1gl2pgrdxgnsj12zycpxnsx8lg6arfmnr1"; sha256 = "1bcm0c9f7xy5qj5f0z3gddqslhb2vzrj9smc39pgqyq4jmn5kpj0";
type = "gem"; type = "gem";
}; };
version = "1.75.0"; version = "1.64.0";
}; };
aws-sdk-s3 = { aws-sdk-s3 = {
dependencies = ["aws-sdk-core" "aws-sdk-kms" "aws-sigv4"]; dependencies = ["aws-sdk-core" "aws-sdk-kms" "aws-sigv4"];
@@ -89,10 +78,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0bnhpmi0iiaj88rqc5lhhnp2gyrk4fs8xz51lj36wwzng94qinya"; sha256 = "01cryf8kfkmlsxb327szcwcagsp7lss5gmk6zxlgap65lv8bc7rx";
type = "gem"; type = "gem";
}; };
version = "1.141.0"; version = "1.122.0";
}; };
aws-sigv4 = { aws-sigv4 = {
dependencies = ["aws-eventstream"]; dependencies = ["aws-eventstream"];
@@ -100,10 +89,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1g3w27wzjy4si6kp49w10as6ml6g6zl3xrfqs5ikpfciidv9kpc4"; sha256 = "11hkna2av47bl0yprgp8k4ya70rc3m2ib5w10fn0piplgkkmhz7m";
type = "gem"; type = "gem";
}; };
version = "1.8.0"; version = "1.5.2";
}; };
babosa = { babosa = {
groups = ["default"]; groups = ["default"];
@@ -167,16 +156,6 @@
}; };
version = "4.6.0"; version = "4.6.0";
}; };
concurrent-ruby = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0krcwb6mn0iklajwngwsg850nk8k9b35dhmc2qkbdqvmifdi2y9q";
type = "gem";
};
version = "1.2.2";
};
declarative = { declarative = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
@@ -193,20 +172,21 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "09114ndpnnyamc2q07bmpzw7kp3rbbfv7plmxcbzzi9d6prmd92w"; sha256 = "1czaak53w8n13y1fr0q23gp0fhklvxjac5n562qj3xk6sh5ad0x2";
type = "gem"; type = "gem";
}; };
version = "0.6.5"; version = "0.6.4";
}; };
domain_name = { domain_name = {
dependencies = ["unf"];
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1gpciaifmxql8h01ci12qq08dnqrdlzkkz6fmia9v9yc3r9a29si"; sha256 = "0lcqjsmixjp52bnlgzh4lg9ppsk52x9hpwdjd53k8jnbah2602h0";
type = "gem"; type = "gem";
}; };
version = "0.6.20231109"; version = "0.5.20190701";
}; };
dotenv = { dotenv = {
groups = ["default"]; groups = ["default"];
@@ -233,10 +213,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1q9yz7x36mpzpz04bg6hdyrzzk4bri9jg3h2ygw26bf6v3axq53q"; sha256 = "0j826kfvzn7nc5pv950n270r0sx1702k988ad11cdlav3dcxxw09";
type = "gem"; type = "gem";
}; };
version = "0.108.0"; version = "0.99.0";
}; };
faraday = { faraday = {
dependencies = ["faraday-em_http" "faraday-em_synchrony" "faraday-excon" "faraday-httpclient" "faraday-multipart" "faraday-net_http" "faraday-net_http_persistent" "faraday-patron" "faraday-rack" "faraday-retry" "ruby2_keywords"]; dependencies = ["faraday-em_http" "faraday-em_synchrony" "faraday-excon" "faraday-httpclient" "faraday-multipart" "faraday-net_http" "faraday-net_http_persistent" "faraday-patron" "faraday-rack" "faraday-retry" "ruby2_keywords"];
@@ -383,15 +363,15 @@
version = "2.2.7"; version = "2.2.7";
}; };
fastlane = { fastlane = {
dependencies = ["CFPropertyList" "addressable" "artifactory" "aws-sdk-s3" "babosa" "colored" "commander" "dotenv" "emoji_regex" "excon" "faraday" "faraday-cookie_jar" "faraday_middleware" "fastimage" "gh_inspector" "google-apis-androidpublisher_v3" "google-apis-playcustomapp_v1" "google-cloud-storage" "highline" "http-cookie" "json" "jwt" "mini_magick" "multipart-post" "naturally" "optparse" "plist" "rubyzip" "security" "simctl" "terminal-notifier" "terminal-table" "tty-screen" "tty-spinner" "word_wrap" "xcodeproj" "xcpretty" "xcpretty-travis-formatter"]; dependencies = ["CFPropertyList" "addressable" "artifactory" "aws-sdk-s3" "babosa" "colored" "commander" "dotenv" "emoji_regex" "excon" "faraday" "faraday-cookie_jar" "faraday_middleware" "fastimage" "gh_inspector" "google-apis-androidpublisher_v3" "google-apis-playcustomapp_v1" "google-cloud-storage" "highline" "json" "jwt" "mini_magick" "multipart-post" "naturally" "optparse" "plist" "rubyzip" "security" "simctl" "terminal-notifier" "terminal-table" "tty-screen" "tty-spinner" "word_wrap" "xcodeproj" "xcpretty" "xcpretty-travis-formatter"];
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0p2b92csayzlj60v15fz3mq4h23kvvr7swhaavi6fpaqzf70iafi"; sha256 = "15sa3v3aaslympg9nmadmpxpbzykdiybzxn3navc7mf0iscb3q7s";
type = "gem"; type = "gem";
}; };
version = "2.217.0"; version = "2.212.2";
}; };
gh_inspector = { gh_inspector = {
groups = ["default"]; groups = ["default"];
@@ -409,10 +389,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "046j100lrh5dhb8p3gr38fyqrw8vcif97pqb55ysipy874lafw49"; sha256 = "0ks2ak4fcvlflhyinykvd88g2ybxwsbc347aww349zhn1mqprbvg";
type = "gem"; type = "gem";
}; };
version = "0.54.0"; version = "0.42.0";
}; };
google-apis-core = { google-apis-core = {
dependencies = ["addressable" "googleauth" "httpclient" "mini_mime" "representable" "retriable" "rexml" "webrick"]; dependencies = ["addressable" "googleauth" "httpclient" "mini_mime" "representable" "retriable" "rexml" "webrick"];
@@ -420,10 +400,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1cly6ycryjhk15d60v3nqvhqpjk9f0nznnslbdnin90f5r54sbpd"; sha256 = "184zkm5agi7r5fl79hgahjpydsc4d23nd2ynh2sr9z8gs2w4h82f";
type = "gem"; type = "gem";
}; };
version = "0.11.2"; version = "0.11.0";
}; };
google-apis-iamcredentials_v1 = { google-apis-iamcredentials_v1 = {
dependencies = ["google-apis-core"]; dependencies = ["google-apis-core"];
@@ -453,10 +433,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1k432qgxf41c4m6d68rascm0gyj18r7ypmrnyzmxh7k7nh543awx"; sha256 = "17qamcjnf22zvw1g169g8a2gkzdsxx4ij3a4ganihyrcf9r62asj";
type = "gem"; type = "gem";
}; };
version = "0.29.0"; version = "0.19.0";
}; };
google-cloud-core = { google-cloud-core = {
dependencies = ["google-cloud-env" "google-cloud-errors"]; dependencies = ["google-cloud-env" "google-cloud-errors"];
@@ -464,10 +444,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "00wfvdvdv9m4l5ydn6xp65n68mgmpqr3n09hzvxs7gp8fly3j17v"; sha256 = "0amp8vd16pzbdrfbp7k0k38rqxpwd88bkyp35l3x719hbb6l85za";
type = "gem"; type = "gem";
}; };
version = "1.6.1"; version = "1.6.0";
}; };
google-cloud-env = { google-cloud-env = {
dependencies = ["faraday"]; dependencies = ["faraday"];
@@ -475,10 +455,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "056r1p8vhjswnx2cy3mzhwc5gj03whmpz8m4p2ph37gag5bpnxmf"; sha256 = "05gshdqscg4kil6ppfzmikyavsx449bxyj47j33r4n4p8swsqyb1";
type = "gem"; type = "gem";
}; };
version = "2.1.0"; version = "1.6.0";
}; };
google-cloud-errors = { google-cloud-errors = {
groups = ["default"]; groups = ["default"];
@@ -496,21 +476,21 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0033bi8qwm0ksxsv5zhz4nzwsiaapq3xk79z8f8rx3v09vdap07j"; sha256 = "1skhlpcykxxzw3050cwngdyc3n746wfx443w1w9chxwjbh2ix6i9";
type = "gem"; type = "gem";
}; };
version = "1.45.0"; version = "1.44.0";
}; };
googleauth = { googleauth = {
dependencies = ["faraday" "google-cloud-env" "jwt" "multi_json" "os" "signet"]; dependencies = ["faraday" "jwt" "memoist" "multi_json" "os" "signet"];
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0spv89di017rg25psiv4w3pn6f67y2w6vv8w910i83b5yii84rl1"; sha256 = "1lj5haarpn7rybbq9s031zcn9ji3rlz5bk64bwa2j34q5s1h5gis";
type = "gem"; type = "gem";
}; };
version = "1.9.1"; version = "1.5.2";
}; };
highline = { highline = {
groups = ["default"]; groups = ["default"];
@@ -543,17 +523,6 @@
}; };
version = "2.8.3"; version = "2.8.3";
}; };
i18n = {
dependencies = ["concurrent-ruby"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0qaamqsh5f3szhcakkak8ikxlzxqnv49n2p7504hcz2l0f4nj0wx";
type = "gem";
};
version = "1.14.1";
};
jmespath = { jmespath = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
@@ -569,20 +538,30 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0r9jmjhg2ly3l736flk7r2al47b5c8cayh0gqkq0yhjqzc9a6zhq"; sha256 = "0nalhin1gda4v8ybk6lq8f407cgfrj6qzn234yra4ipkmlbfmal6";
type = "gem"; type = "gem";
}; };
version = "2.7.1"; version = "2.6.3";
}; };
jwt = { jwt = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "16z11alz13vfc4zs5l3fk6n51n2jw9lskvc4h4prnww0y797qd87"; sha256 = "09yj3z5snhaawh2z1w45yyihzmh57m6m7dp8ra8gxavhj5kbiq5p";
type = "gem"; type = "gem";
}; };
version = "2.7.1"; version = "2.7.0";
};
memoist = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0i9wpzix3sjhf6d9zw60dm4371iq8kyz7ckh2qapan2vyaim6b55";
type = "gem";
};
version = "0.16.2";
}; };
mini_magick = { mini_magick = {
groups = ["default"]; groups = ["default"];
@@ -599,20 +578,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1vycif7pjzkr29mfk4dlqv3disc5dn0va04lkwajlpr1wkibg0c6"; sha256 = "0lbim375gw2dk6383qirz13hgdmxlan0vc5da2l072j3qw6fqjm5";
type = "gem"; type = "gem";
}; };
version = "1.1.5"; version = "1.1.2";
};
minitest = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0bkmfi9mb49m0fkdhl2g38i3xxa02d411gg0m8x0gvbwfmmg5ym3";
type = "gem";
};
version = "5.20.0";
}; };
multi_json = { multi_json = {
groups = ["default"]; groups = ["default"];
@@ -629,10 +598,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0lgyysrpl50wgcb9ahg29i4p01z0irb3p9lirygma0kkfr5dgk9x"; sha256 = "09k0b3cybqilk1gwrwwain95rdypixb2q9w65gd44gfzsd84xi1x";
type = "gem"; type = "gem";
}; };
version = "2.3.0"; version = "2.0.0";
}; };
nanaimo = { nanaimo = {
groups = ["default"]; groups = ["default"];
@@ -689,20 +658,20 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1bni4qjrsh2q49pnmmd6if4iv3ak36bd2cckrs6npl111n769k9m"; sha256 = "0hz0bx2qs2pwb0bwazzsah03ilpf3aai8b7lk7s35jsfzwbkjq35";
type = "gem"; type = "gem";
}; };
version = "5.0.4"; version = "5.0.1";
}; };
rake = { rake = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1ilr853hawi09626axx0mps4rkkmxcs54mapz9jnqvpnlwd3wsmy"; sha256 = "15whn7p9nrkxangbs9hh75q585yfn66lv0v2mhj6q6dl6x8bzr2w";
type = "gem"; type = "gem";
}; };
version = "13.1.0"; version = "13.0.6";
}; };
representable = { representable = {
dependencies = ["declarative" "trailblazer-option" "uber"]; dependencies = ["declarative" "trailblazer-option" "uber"];
@@ -730,10 +699,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "05i8518ay14kjbma550mv0jm8a6di8yp5phzrd8rj44z9qnrlrp0"; sha256 = "08ximcyfjy94pm1rhcx04ny1vx2sk0x4y185gzn86yfsbzwkng53";
type = "gem"; type = "gem";
}; };
version = "3.2.6"; version = "3.2.5";
}; };
rouge = { rouge = {
groups = ["default"]; groups = ["default"];
@@ -781,10 +750,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0fzakk5y7zzii76zlkynpp1c764mzkkfg4mpj18f5pf2xp1aikb6"; sha256 = "0100rclkhagf032rg3r0gf3f4znrvvvqrimy6hpa73f21n9k2a0x";
type = "gem"; type = "gem";
}; };
version = "0.18.0"; version = "0.17.0";
}; };
simctl = { simctl = {
dependencies = ["CFPropertyList" "naturally"]; dependencies = ["CFPropertyList" "naturally"];
@@ -813,10 +782,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "14dfmfjppmng5hwj7c5ka6qdapawm3h6k9lhn8zj001ybypvclgr"; sha256 = "1512cngw35hsmhvw4c05rscihc59mnj09m249sm9p3pik831ydqk";
type = "gem"; type = "gem";
}; };
version = "3.0.2"; version = "1.8.0";
}; };
trailblazer-option = { trailblazer-option = {
groups = ["default"]; groups = ["default"];
@@ -843,10 +812,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "0l4vh6g333jxm9lakilkva2gn17j6gb052626r1pdbmy2lhnb460"; sha256 = "18jr6s1cg8yb26wzkqa6874q0z93rq0y5aw092kdqazk71y6a235";
type = "gem"; type = "gem";
}; };
version = "0.8.2"; version = "0.8.1";
}; };
tty-spinner = { tty-spinner = {
dependencies = ["tty-cursor"]; dependencies = ["tty-cursor"];
@@ -859,17 +828,6 @@
}; };
version = "0.9.3"; version = "0.9.3";
}; };
tzinfo = {
dependencies = ["concurrent-ruby"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "16w2g84dzaf3z13gxyzlzbf748kylk5bdgg3n1ipvkvvqy685bwd";
type = "gem";
};
version = "2.0.6";
};
uber = { uber = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
@@ -880,15 +838,36 @@
}; };
version = "0.1.0"; version = "0.1.0";
}; };
unf = {
dependencies = ["unf_ext"];
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "0bh2cf73i2ffh4fcpdn9ir4mhq8zi50ik0zqa1braahzadx536a9";
type = "gem";
};
version = "0.1.4";
};
unf_ext = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "1yj2nz2l101vr1x9w2k83a0fag1xgnmjwp8w8rw4ik2rwcz65fch";
type = "gem";
};
version = "0.0.8.2";
};
unicode-display_width = { unicode-display_width = {
groups = ["default"]; groups = ["default"];
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "1d0azx233nags5jx3fqyr23qa2rhgzbhv8pxp46dgbg1mpf82xky"; sha256 = "1204c1jx2g89pc25qk5150mk7j5k90692i7ihgfzqnad6qni74h2";
type = "gem"; type = "gem";
}; };
version = "2.5.0"; version = "1.8.0";
}; };
webrick = { webrick = {
groups = ["default"]; groups = ["default"];
@@ -916,10 +895,10 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["https://rubygems.org"]; remotes = ["https://rubygems.org"];
sha256 = "176ndahc5fssyx04q176vy6wngs1av4vrsdrkdpjij700hqll8hn"; sha256 = "1s7hxaqd1fi4rlmm2jbrglyvka1r95frlxan61vfcnd8n6pxynpi";
type = "gem"; type = "gem";
}; };
version = "1.23.0"; version = "1.22.0";
}; };
xcpretty = { xcpretty = {
dependencies = ["rouge"]; dependencies = ["rouge"];
+22 -35
View File
@@ -1,33 +1,16 @@
def node_require(script) require_relative '../node_modules/react-native/scripts/react_native_pods'
# Resolve script with node to allow for hoisting require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
require Pod::Executable.execute_command('node', ['-p',
"require.resolve(
'#{script}',
{paths: [process.argv[1]]},
)", __dir__]).strip
end
node_require('react-native/scripts/react_native_pods.rb') platform :ios, '12.4'
node_require('react-native-permissions/scripts/setup.rb')
platform :ios, min_ios_version_supported production = ENV["PRODUCTION"] == "1"
prepare_react_native_project!
setup_permissions([ # We need to enable codegen discovery to fix the issue of these files not being generated properly:
'Camera', # ios/build/generated/ios/FBReactNativeSpec/FBReactNativeSpec-generated.mm
'FaceID', # ios/build/generated/ios/FBReactNativeSpec/FBReactNativeSpec.h
'MediaLibrary', # more details here : https://github.com/status-im/status-mobile/issues/15911
'Microphone', # TODO: remove this flag once you upgrade react-native above version 0.70
'Notifications', ENV['USE_CODEGEN_DISCOVERY'] = "1"
'PhotoLibrary',
'PhotoLibraryAddOnly',
])
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
# If inside a Nix shell, allow pod install # If inside a Nix shell, allow pod install
inside_nix_shell = ENV['IN_NIX_SHELL'] inside_nix_shell = ENV['IN_NIX_SHELL']
@@ -47,8 +30,11 @@ abstract_target 'Status' do
use_react_native!( use_react_native!(
:path => config[:reactNativePath], :path => config[:reactNativePath],
# to enable hermes on iOS, change `false` to `true` and then install pods
:production => production,
:hermes_enabled => flags[:hermes_enabled],
:fabric_enabled => flags[:fabric_enabled], :fabric_enabled => flags[:fabric_enabled],
:hermes_enabled => true, :use_codegen_discovery => true,
# An absolute path to your application root. # An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.." :app_path => "#{Pod::Config.instance.installation_root}/.."
) )
@@ -58,6 +44,10 @@ abstract_target 'Status' do
pod 'SSZipArchive', '2.4.3' pod 'SSZipArchive', '2.4.3'
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone.podspec"
pod 'Permission-Camera', :path => "#{permissions_path}/Camera.podspec"
pod "react-native-status-keycard", path: "../node_modules/react-native-status-keycard" pod "react-native-status-keycard", path: "../node_modules/react-native-status-keycard"
pod "react-native-status", path: "../modules/react-native-status" pod "react-native-status", path: "../modules/react-native-status"
pod "Keycard", git: "https://github.com/status-im/Keycard.swift.git" pod "Keycard", git: "https://github.com/status-im/Keycard.swift.git"
@@ -75,18 +65,15 @@ abstract_target 'Status' do
end end
post_install do |installer| post_install do |installer|
# as per react-native 0.73.2 template
# https://github.com/facebook/react-native/blob/c5c0563f209ead8f884204763e02115bd66d1960/packages/react-native/template/ios/Podfile#L49-L52
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
)
# some of libs wouldn't be build for x86_64 otherwise and that is # some of libs wouldn't be build for x86_64 otherwise and that is
# necessary for ios simulators # necessary for ios simulators
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
target.build_configurations.each do |config| target.build_configurations.each do |config|
config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO' config.build_settings['ONLY_ACTIVE_ARCH'] = 'NO'
# fix for no template named 'unary_function' in namespace 'std'; did you mean '__unary_function'?
# ref : https://github.com/facebook/react-native/issues/37748
# TODO : remove after upgrading to react-native 0.72.x
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION']
end end
# We need to remove the predefinition of IPHONEOS_DEPLOYMENT_TARGET from RNCK lib to use our own. # We need to remove the predefinition of IPHONEOS_DEPLOYMENT_TARGET from RNCK lib to use our own.
case target.name case target.name
+372 -1175
View File
File diff suppressed because it is too large Load Diff
+207 -300
View File
@@ -3,13 +3,12 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 54; objectVersion = 52;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
00E356F31AD99517003FC87E /* StatusImTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* StatusImTests.m */; }; 00E356F31AD99517003FC87E /* StatusImTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* StatusImTests.m */; };
0BF51D8C7FBD6A668E6E1FC0 /* libPods-Status-StatusIm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45C29909A975E0654116557F /* libPods-Status-StatusIm.a */; }; 04515E9DF839CBF55C690E79 /* libPods-Status-StatusImPR.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5006FF03675A7E50320B4002 /* libPods-Status-StatusImPR.a */; };
131972279C6DBF736235F9F9 /* libPods-Status-StatusIm-StatusImTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D9DF8AC0F6547107DE1A25D /* libPods-Status-StatusIm-StatusImTests.a */; };
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */; }; 25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */; };
@@ -45,6 +44,7 @@
715D8132290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */; }; 715D8132290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */; };
715D8133290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */; }; 715D8133290BE850006F5C88 /* UbuntuMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */; };
74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */; }; 74B758FC20D7C00B003343C3 /* launch-image-universal.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */; };
81F3191BB1D4BDF3442402BD /* libPods-Status-StatusIm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F8E9088BDE117AB71366407 /* libPods-Status-StatusIm.a */; };
8391E8E0E93C41A98AAA6631 /* Inter-SemiBoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */; }; 8391E8E0E93C41A98AAA6631 /* Inter-SemiBoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */; };
B24FC7FD1DE7195700D694FF /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B24FC7FC1DE7195700D694FF /* Social.framework */; }; B24FC7FD1DE7195700D694FF /* Social.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B24FC7FC1DE7195700D694FF /* Social.framework */; };
B24FC7FF1DE7195F00D694FF /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B24FC7FE1DE7195F00D694FF /* MessageUI.framework */; }; B24FC7FF1DE7195F00D694FF /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B24FC7FE1DE7195F00D694FF /* MessageUI.framework */; };
@@ -57,10 +57,10 @@
C1715FFB29C0BCE50088FA8B /* launch-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C14C5F8C29C0A149005C58A7 /* launch-icon@3x.png */; }; C1715FFB29C0BCE50088FA8B /* launch-icon@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C14C5F8C29C0A149005C58A7 /* launch-icon@3x.png */; };
C1715FFC29C0BCE80088FA8B /* launch-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = C14C5F9229C0ADB5005C58A7 /* launch-icon.png */; }; C1715FFC29C0BCE80088FA8B /* launch-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = C14C5F9229C0ADB5005C58A7 /* launch-icon.png */; };
CE4E31B31D8695250033ED64 /* Statusgo.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE4E31B21D8695250033ED64 /* Statusgo.xcframework */; }; CE4E31B31D8695250033ED64 /* Statusgo.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE4E31B21D8695250033ED64 /* Statusgo.xcframework */; };
D156FF2CCF43C136F7BF8AE5 /* libPods-Status-StatusIm-StatusImTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3EFEEB5FC1235562D5D3BF1 /* libPods-Status-StatusIm-StatusImTests.a */; };
D1786306E0184916B11F4C37 /* Inter-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = B2A38FC3D3954DE7B2B171F8 /* Inter-Medium.otf */; }; D1786306E0184916B11F4C37 /* Inter-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = B2A38FC3D3954DE7B2B171F8 /* Inter-Medium.otf */; };
D84616FB563A48EBB1678699 /* Inter-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD4A2C27D6D5473184DC1F7E /* Inter-Bold.otf */; }; D84616FB563A48EBB1678699 /* Inter-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CD4A2C27D6D5473184DC1F7E /* Inter-Bold.otf */; };
D99C50E5E18942A39C8DDF61 /* Inter-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = B321D25F4493470980039457 /* Inter-BoldItalic.otf */; }; D99C50E5E18942A39C8DDF61 /* Inter-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = B321D25F4493470980039457 /* Inter-BoldItalic.otf */; };
DE2F1721F9D5702C7CEC5594 /* libPods-Status-StatusImPR.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B17DF204648B8189F8ABD0A7 /* libPods-Status-StatusImPR.a */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -108,23 +108,23 @@
00E356EE1AD99517003FC87E /* StatusImTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StatusImTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356EE1AD99517003FC87E /* StatusImTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StatusImTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* StatusImTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StatusImTests.m; sourceTree = "<group>"; }; 00E356F21AD99517003FC87E /* StatusImTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StatusImTests.m; sourceTree = "<group>"; };
06AF19FA626AFFC91E66916B /* Pods-Status-StatusImPR.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusImPR.release.xcconfig"; path = "Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR.release.xcconfig"; sourceTree = "<group>"; };
0F8E9088BDE117AB71366407 /* libPods-Status-StatusIm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusIm.a"; sourceTree = BUILT_PRODUCTS_DIR; };
13B07F961A680F5B00A75B9A /* StatusIm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StatusIm.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* StatusIm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StatusIm.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = StatusIm/AppDelegate.h; sourceTree = "<group>"; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = StatusIm/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = StatusIm/AppDelegate.mm; sourceTree = "<group>"; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = StatusIm/AppDelegate.mm; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = StatusIm/Info.plist; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = StatusIm/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = StatusIm/main.m; sourceTree = "<group>"; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = StatusIm/main.m; sourceTree = "<group>"; };
1426DF592BA248FC81D955CB /* Inter-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Regular.otf"; path = "../resources/fonts/Inter-Regular.otf"; sourceTree = "<group>"; }; 1426DF592BA248FC81D955CB /* Inter-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Regular.otf"; path = "../resources/fonts/Inter-Regular.otf"; sourceTree = "<group>"; };
1B74FBFCB9B8E34B63250A52 /* Pods-Status-StatusIm-StatusImTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm-StatusImTests.release.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests.release.xcconfig"; sourceTree = "<group>"; }; 1CDF317A2E103217DF386083 /* Pods-Status-StatusIm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm.release.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm.release.xcconfig"; sourceTree = "<group>"; };
232FE8EAB57384181B0DB836 /* Pods-Status-StatusIm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm.release.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm.release.xcconfig"; sourceTree = "<group>"; };
2D9DF8AC0F6547107DE1A25D /* libPods-Status-StatusIm-StatusImTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusIm-StatusImTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
3A2626CE245C3F2200D5F94B /* Dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dummy.swift; sourceTree = "<group>"; }; 3A2626CE245C3F2200D5F94B /* Dummy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dummy.swift; sourceTree = "<group>"; };
3A6406FB24A3ADF90046ED37 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 3A6406FB24A3ADF90046ED37 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3A8F8EA924A4D31600BF206D /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; 3A8F8EA924A4D31600BF206D /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
3AAD2ADC24A3A60E0075D594 /* Status PR.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Status PR.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 3AAD2ADC24A3A60E0075D594 /* Status PR.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Status PR.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3AB1C3AD245C043900098F67 /* StatusIm-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatusIm-Bridging-Header.h"; sourceTree = "<group>"; }; 3AB1C3AD245C043900098F67 /* StatusIm-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatusIm-Bridging-Header.h"; sourceTree = "<group>"; };
45C29909A975E0654116557F /* libPods-Status-StatusIm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusIm.a"; sourceTree = BUILT_PRODUCTS_DIR; };
4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 4C16DE0B1F89508700AA10DB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
4E586E1B0E544F64AA9F5BD1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 4E586E1B0E544F64AA9F5BD1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
5006FF03675A7E50320B4002 /* libPods-Status-StatusImPR.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusImPR.a"; sourceTree = BUILT_PRODUCTS_DIR; };
65F693BD2578002500A45E76 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = System/Library/Frameworks/CoreNFC.framework; sourceTree = SDKROOT; }; 65F693BD2578002500A45E76 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = System/Library/Frameworks/CoreNFC.framework; sourceTree = SDKROOT; };
65F693BF2578003600A45E76 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/iOSSupport/System/Library/Frameworks/CoreNFC.framework; sourceTree = DEVELOPER_DIR; }; 65F693BF2578003600A45E76 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk/System/iOSSupport/System/Library/Frameworks/CoreNFC.framework; sourceTree = DEVELOPER_DIR; };
65F6941725780A4E00A45E76 /* StatusImTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatusImTests-Bridging-Header.h"; sourceTree = "<group>"; }; 65F6941725780A4E00A45E76 /* StatusImTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "StatusImTests-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -132,16 +132,14 @@
693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBold.otf"; path = "../resources/fonts/Inter-SemiBold.otf"; sourceTree = "<group>"; }; 693A62DB37BC4CD5A30E5C96 /* Inter-SemiBold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBold.otf"; path = "../resources/fonts/Inter-SemiBold.otf"; sourceTree = "<group>"; };
715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "UbuntuMono-Regular.ttf"; path = "../resources/fonts/UbuntuMono-Regular.ttf"; sourceTree = "<group>"; }; 715D8131290BE850006F5C88 /* UbuntuMono-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "UbuntuMono-Regular.ttf"; path = "../resources/fonts/UbuntuMono-Regular.ttf"; sourceTree = "<group>"; };
74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "launch-image-universal.storyboard"; sourceTree = "<group>"; }; 74B758FB20D7C00B003343C3 /* launch-image-universal.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "launch-image-universal.storyboard"; sourceTree = "<group>"; };
7A393286DD0E844D050D0B89 /* Pods-Status-StatusImPR.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusImPR.release.xcconfig"; path = "Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR.release.xcconfig"; sourceTree = "<group>"; };
7BF7B2DB23EE09E5229629DA /* Pods-Status-StatusImPR.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusImPR.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR.debug.xcconfig"; sourceTree = "<group>"; };
8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
922C4CA61F4D5F8B0033C753 /* StatusIm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = StatusIm.entitlements; path = StatusIm/StatusIm.entitlements; sourceTree = "<group>"; }; 922C4CA61F4D5F8B0033C753 /* StatusIm.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = StatusIm.entitlements; path = StatusIm/StatusIm.entitlements; sourceTree = "<group>"; };
93347A9564A62A24509EFA9C /* Pods-Status-StatusIm-StatusImTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm-StatusImTests.release.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests.release.xcconfig"; sourceTree = "<group>"; };
9C76AF5A418D4D65A4CAD1D9 /* InterStatus-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "InterStatus-Regular.otf"; path = "../resources/fonts/InterStatus-Regular.otf"; sourceTree = "<group>"; }; 9C76AF5A418D4D65A4CAD1D9 /* InterStatus-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "InterStatus-Regular.otf"; path = "../resources/fonts/InterStatus-Regular.otf"; sourceTree = "<group>"; };
9EC0135C1E06FB1900155B5C /* RCTWKWebView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWKWebView.xcodeproj; path = "../node_modules/react-native-wkwebview-reborn/ios/RCTWKWebView.xcodeproj"; sourceTree = "<group>"; }; 9EC0135C1E06FB1900155B5C /* RCTWKWebView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWKWebView.xcodeproj; path = "../node_modules/react-native-wkwebview-reborn/ios/RCTWKWebView.xcodeproj"; sourceTree = "<group>"; };
A0B5AD061DF0F6CC98603A99 /* Pods-Status-StatusIm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm.debug.xcconfig"; sourceTree = "<group>"; };
A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBoldItalic.otf"; path = "../resources/fonts/Inter-SemiBoldItalic.otf"; sourceTree = "<group>"; }; A4F2BBE8D4DD4140A6CCAC39 /* Inter-SemiBoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-SemiBoldItalic.otf"; path = "../resources/fonts/Inter-SemiBoldItalic.otf"; sourceTree = "<group>"; };
AA6DC18226EB1EFB2A8FE64D /* Pods-Status-StatusIm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm.debug.xcconfig"; sourceTree = "<group>"; };
B07176ACDAA1422E8F0A3D6B /* Inter-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Italic.otf"; path = "../resources/fonts/Inter-Italic.otf"; sourceTree = "<group>"; }; B07176ACDAA1422E8F0A3D6B /* Inter-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Italic.otf"; path = "../resources/fonts/Inter-Italic.otf"; sourceTree = "<group>"; };
B17DF204648B8189F8ABD0A7 /* libPods-Status-StatusImPR.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusImPR.a"; sourceTree = BUILT_PRODUCTS_DIR; };
B24FC7FC1DE7195700D694FF /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; }; B24FC7FC1DE7195700D694FF /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; };
B24FC7FE1DE7195F00D694FF /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; B24FC7FE1DE7195F00D694FF /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; };
B2A38FC3D3954DE7B2B171F8 /* Inter-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Medium.otf"; path = "../resources/fonts/Inter-Medium.otf"; sourceTree = "<group>"; }; B2A38FC3D3954DE7B2B171F8 /* Inter-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Medium.otf"; path = "../resources/fonts/Inter-Medium.otf"; sourceTree = "<group>"; };
@@ -150,10 +148,12 @@
C14C5F8C29C0A149005C58A7 /* launch-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "launch-icon@3x.png"; path = "StatusIm/launch-icon@3x.png"; sourceTree = "<group>"; }; C14C5F8C29C0A149005C58A7 /* launch-icon@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "launch-icon@3x.png"; path = "StatusIm/launch-icon@3x.png"; sourceTree = "<group>"; };
C14C5F9029C0AD9C005C58A7 /* launch-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "launch-icon@2x.png"; path = "StatusIm/launch-icon@2x.png"; sourceTree = "<group>"; }; C14C5F9029C0AD9C005C58A7 /* launch-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "launch-icon@2x.png"; path = "StatusIm/launch-icon@2x.png"; sourceTree = "<group>"; };
C14C5F9229C0ADB5005C58A7 /* launch-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "launch-icon.png"; path = "StatusIm/launch-icon.png"; sourceTree = "<group>"; }; C14C5F9229C0ADB5005C58A7 /* launch-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "launch-icon.png"; path = "StatusIm/launch-icon.png"; sourceTree = "<group>"; };
C618F2C2EF820C722B1E7624 /* Pods-Status-StatusImPR.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusImPR.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR.debug.xcconfig"; sourceTree = "<group>"; };
C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-MediumItalic.otf"; path = "../resources/fonts/Inter-MediumItalic.otf"; sourceTree = "<group>"; }; C6B1215047604CD59A4C74D6 /* Inter-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-MediumItalic.otf"; path = "../resources/fonts/Inter-MediumItalic.otf"; sourceTree = "<group>"; };
CD4A2C27D6D5473184DC1F7E /* Inter-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Bold.otf"; path = "../resources/fonts/Inter-Bold.otf"; sourceTree = "<group>"; }; CD4A2C27D6D5473184DC1F7E /* Inter-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inter-Bold.otf"; path = "../resources/fonts/Inter-Bold.otf"; sourceTree = "<group>"; };
CE4E31B21D8695250033ED64 /* Statusgo.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Statusgo.xcframework; path = "../modules/react-native-status/ios/RCTStatus/Statusgo.xcframework"; sourceTree = "<group>"; }; CE4E31B21D8695250033ED64 /* Statusgo.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Statusgo.xcframework; path = "../modules/react-native-status/ios/RCTStatus/Statusgo.xcframework"; sourceTree = "<group>"; };
D40C4023C7D5B793AEF98426 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm-StatusImTests.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests.debug.xcconfig"; sourceTree = "<group>"; }; D3EFEEB5FC1235562D5D3BF1 /* libPods-Status-StatusIm-StatusImTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Status-StatusIm-StatusImTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DAE7378308FEB005CE0A6E42 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Status-StatusIm-StatusImTests.debug.xcconfig"; path = "Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -161,7 +161,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
131972279C6DBF736235F9F9 /* libPods-Status-StatusIm-StatusImTests.a in Frameworks */, D156FF2CCF43C136F7BF8AE5 /* libPods-Status-StatusIm-StatusImTests.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -174,7 +174,7 @@
CE4E31B31D8695250033ED64 /* Statusgo.xcframework in Frameworks */, CE4E31B31D8695250033ED64 /* Statusgo.xcframework in Frameworks */,
25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */, 25DC9C9DC25846BD8D084888 /* libc++.tbd in Frameworks */,
BA68A2377A20496EA737000D /* libz.tbd in Frameworks */, BA68A2377A20496EA737000D /* libz.tbd in Frameworks */,
0BF51D8C7FBD6A668E6E1FC0 /* libPods-Status-StatusIm.a in Frameworks */, 81F3191BB1D4BDF3442402BD /* libPods-Status-StatusIm.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -188,7 +188,7 @@
3AAD2AC224A3A60E0075D594 /* Statusgo.xcframework in Frameworks */, 3AAD2AC224A3A60E0075D594 /* Statusgo.xcframework in Frameworks */,
3AAD2AC524A3A60E0075D594 /* libc++.tbd in Frameworks */, 3AAD2AC524A3A60E0075D594 /* libc++.tbd in Frameworks */,
3AAD2AC624A3A60E0075D594 /* libz.tbd in Frameworks */, 3AAD2AC624A3A60E0075D594 /* libz.tbd in Frameworks */,
DE2F1721F9D5702C7CEC5594 /* libPods-Status-StatusImPR.a in Frameworks */, 04515E9DF839CBF55C690E79 /* libPods-Status-StatusImPR.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -314,9 +314,9 @@
CE4E31B21D8695250033ED64 /* Statusgo.xcframework */, CE4E31B21D8695250033ED64 /* Statusgo.xcframework */,
8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */, 8B9A886A2CB448B1ABA0EB62 /* libc++.tbd */,
4E586E1B0E544F64AA9F5BD1 /* libz.tbd */, 4E586E1B0E544F64AA9F5BD1 /* libz.tbd */,
45C29909A975E0654116557F /* libPods-Status-StatusIm.a */, 0F8E9088BDE117AB71366407 /* libPods-Status-StatusIm.a */,
2D9DF8AC0F6547107DE1A25D /* libPods-Status-StatusIm-StatusImTests.a */, D3EFEEB5FC1235562D5D3BF1 /* libPods-Status-StatusIm-StatusImTests.a */,
B17DF204648B8189F8ABD0A7 /* libPods-Status-StatusImPR.a */, 5006FF03675A7E50320B4002 /* libPods-Status-StatusImPR.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -324,12 +324,12 @@
D0D5C8D06825D33BA2D2121E /* Pods */ = { D0D5C8D06825D33BA2D2121E /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A0B5AD061DF0F6CC98603A99 /* Pods-Status-StatusIm.debug.xcconfig */, AA6DC18226EB1EFB2A8FE64D /* Pods-Status-StatusIm.debug.xcconfig */,
232FE8EAB57384181B0DB836 /* Pods-Status-StatusIm.release.xcconfig */, 1CDF317A2E103217DF386083 /* Pods-Status-StatusIm.release.xcconfig */,
D40C4023C7D5B793AEF98426 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */, DAE7378308FEB005CE0A6E42 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */,
1B74FBFCB9B8E34B63250A52 /* Pods-Status-StatusIm-StatusImTests.release.xcconfig */, 93347A9564A62A24509EFA9C /* Pods-Status-StatusIm-StatusImTests.release.xcconfig */,
7BF7B2DB23EE09E5229629DA /* Pods-Status-StatusImPR.debug.xcconfig */, C618F2C2EF820C722B1E7624 /* Pods-Status-StatusImPR.debug.xcconfig */,
7A393286DD0E844D050D0B89 /* Pods-Status-StatusImPR.release.xcconfig */, 06AF19FA626AFFC91E66916B /* Pods-Status-StatusImPR.release.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -341,12 +341,11 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "StatusImTests" */; buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "StatusImTests" */;
buildPhases = ( buildPhases = (
5937040F3338CDF93E777A93 /* [CP] Check Pods Manifest.lock */, A461E3110C485D2A21EB942C /* [CP] Check Pods Manifest.lock */,
00E356EA1AD99517003FC87E /* Sources */, 00E356EA1AD99517003FC87E /* Sources */,
00E356EB1AD99517003FC87E /* Frameworks */, 00E356EB1AD99517003FC87E /* Frameworks */,
00E356EC1AD99517003FC87E /* Resources */, 00E356EC1AD99517003FC87E /* Resources */,
7AD665439C08CFEF5EF84F6A /* [CP] Embed Pods Frameworks */, 2B2389E62F0A9702C522FD40 /* [CP] Copy Pods Resources */,
02C1A8CA208E38DA07BAC311 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@@ -362,15 +361,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "StatusIm" */; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "StatusIm" */;
buildPhases = ( buildPhases = (
1DFD6BF757E89B72F40FCEE9 /* [CP] Check Pods Manifest.lock */, C5DA0344FCE555AD1908FBCD /* [CP] Check Pods Manifest.lock */,
13B07F871A680F5B00A75B9A /* Sources */, 13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */, 13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
20B6B6891D92C42700CC5C6A /* Embed Frameworks */, 20B6B6891D92C42700CC5C6A /* Embed Frameworks */,
E3914A731DF919ED00EBB515 /* Run Script */, E3914A731DF919ED00EBB515 /* Run Script */,
50F2A2E15670F86233743A5C /* [CP] Embed Pods Frameworks */, EC618D80223E4CE064CFF898 /* [CP] Copy Pods Resources */,
1B623A051F855FC5B09A0480 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@@ -385,15 +383,14 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 3AAD2AD924A3A60E0075D594 /* Build configuration list for PBXNativeTarget "StatusImPR" */; buildConfigurationList = 3AAD2AD924A3A60E0075D594 /* Build configuration list for PBXNativeTarget "StatusImPR" */;
buildPhases = ( buildPhases = (
EB421F3ED78A38D285D771D2 /* [CP] Check Pods Manifest.lock */, 0196982A5A6EB89DC2106F9B /* [CP] Check Pods Manifest.lock */,
3AAD2ABB24A3A60E0075D594 /* Sources */, 3AAD2ABB24A3A60E0075D594 /* Sources */,
3AAD2ABF24A3A60E0075D594 /* Frameworks */, 3AAD2ABF24A3A60E0075D594 /* Frameworks */,
3AAD2AC924A3A60E0075D594 /* Resources */, 3AAD2AC924A3A60E0075D594 /* Resources */,
3AAD2AD524A3A60E0075D594 /* Bundle React Native code and images */, 3AAD2AD524A3A60E0075D594 /* Bundle React Native code and images */,
3AAD2AD624A3A60E0075D594 /* Embed Frameworks */, 3AAD2AD624A3A60E0075D594 /* Embed Frameworks */,
3AAD2AD724A3A60E0075D594 /* Run Script */, 3AAD2AD724A3A60E0075D594 /* Run Script */,
F4561A2D3C9E6C4B66F4C4F5 /* [CP] Embed Pods Frameworks */, 4DBAAF9A3117797361E216BA /* [CP] Copy Pods Resources */,
6FA1467F7B916ED92FA688E0 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@@ -545,203 +542,9 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh"; shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\n\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n"; shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
}; };
02C1A8CA208E38DA07BAC311 /* [CP] Copy Pods Resources */ = { 0196982A5A6EB89DC2106F9B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNPermissions/RNPermissionsPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNPermissionsPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
1B623A051F855FC5B09A0480 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNPermissions/RNPermissionsPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNPermissionsPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-resources.sh\"\n";
showEnvVarsInLog = 0;
};
1DFD6BF757E89B72F40FCEE9 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Status-StatusIm-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3AAD2AD524A3A60E0075D594 /* Bundle React Native code and images */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Bundle React Native code and images";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\n\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n";
};
3AAD2AD724A3A60E0075D594 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/usr/bin/env sh";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ../logs/set_xcode_version.log 2>&1\n";
};
50F2A2E15670F86233743A5C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
5937040F3338CDF93E777A93 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Status-StatusIm-StatusImTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
6FA1467F7B916ED92FA688E0 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNPermissions/RNPermissionsPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNPermissionsPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-resources.sh\"\n";
showEnvVarsInLog = 0;
};
7AD665439C08CFEF5EF84F6A /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
E3914A731DF919ED00EBB515 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/usr/bin/env sh";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ../logs/set_xcode_version.log 2>&1\n";
};
EB421F3ED78A38D285D771D2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@@ -763,22 +566,156 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
F4561A2D3C9E6C4B66F4C4F5 /* [CP] Embed Pods Frameworks */ = { 2B2389E62F0A9702C522FD40 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-resources.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Copy Pods Resources";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm-StatusImTests/Pods-Status-StatusIm-StatusImTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3AAD2AD524A3A60E0075D594 /* Bundle React Native code and images */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Bundle React Native code and images";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/usr/bin/env sh";
shellScript = "set -o errexit\nexport NODE_BINARY=\"${NODE_BINARY:-node}\"\nexport NODE_ARGS=\"${NODE_ARGS:- --max-old-space-size=16384 }\"\n\nbash -x ../node_modules/react-native/scripts/react-native-xcode.sh > ./logs/react-native-xcode.log 2>&1";
};
3AAD2AD724A3A60E0075D594 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/usr/bin/env sh";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ./logs/set_xcode_version.log 2>&1";
};
4DBAAF9A3117797361E216BA /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusImPR/Pods-Status-StatusImPR-resources.sh\"\n";
showEnvVarsInLog = 0;
};
A461E3110C485D2A21EB942C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Status-StatusIm-StatusImTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C5DA0344FCE555AD1908FBCD /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Status-StatusIm-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
E3914A731DF919ED00EBB515 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 8;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 1;
shellPath = "/usr/bin/env sh";
shellScript = "\"${PROJECT_DIR}/scripts/set_xcode_version.sh\" > ./logs/set_xcode_version.log 2>&1";
};
EC618D80223E4CE064CFF898 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Status-StatusIm/Pods-Status-StatusIm-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
@@ -828,7 +765,7 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
00E356F61AD99517003FC87E /* Debug */ = { 00E356F61AD99517003FC87E /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = D40C4023C7D5B793AEF98426 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */; baseConfigurationReference = DAE7378308FEB005CE0A6E42 /* Pods-Status-StatusIm-StatusImTests.debug.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_ID_SUFFIX = .debug; BUNDLE_ID_SUFFIX = .debug;
@@ -845,27 +782,27 @@
"$(inherited)", "$(inherited)",
); );
INFOPLIST_FILE = StatusImTests/Info.plist; INFOPLIST_FILE = StatusImTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@loader_path/Frameworks", "@loader_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "StatusImTests-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "StatusImTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.2; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StatusIm.app/StatusIm"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StatusIm.app/StatusIm";
}; };
name = Debug; name = Debug;
}; };
00E356F71AD99517003FC87E /* Release */ = { 00E356F71AD99517003FC87E /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 1B74FBFCB9B8E34B63250A52 /* Pods-Status-StatusIm-StatusImTests.release.xcconfig */; baseConfigurationReference = 93347A9564A62A24509EFA9C /* Pods-Status-StatusIm-StatusImTests.release.xcconfig */;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_ID_SUFFIX = ""; BUNDLE_ID_SUFFIX = "";
@@ -879,30 +816,30 @@
"$(inherited)", "$(inherited)",
); );
INFOPLIST_FILE = StatusImTests/Info.plist; INFOPLIST_FILE = StatusImTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@loader_path/Frameworks", "@loader_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LIBRARY_SEARCH_PATHS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "StatusImTests-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "StatusImTests-Bridging-Header.h";
SWIFT_VERSION = 5.2; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StatusIm.app/StatusIm"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StatusIm.app/StatusIm";
}; };
name = Release; name = Release;
}; };
13B07F941A680F5B00A75B9A /* Debug */ = { 13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = A0B5AD061DF0F6CC98603A99 /* Pods-Status-StatusIm.debug.xcconfig */; baseConfigurationReference = AA6DC18226EB1EFB2A8FE64D /* Pods-Status-StatusIm.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(BUNDLE_ID_SUFFIX)"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(BUNDLE_ID_SUFFIX)";
BUNDLE_ID_SUFFIX = .debug; BUNDLE_ID_SUFFIX = .debug;
CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = StatusIm/StatusIm.entitlements; CODE_SIGN_ENTITLEMENTS = StatusIm/StatusIm.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
@@ -942,14 +879,13 @@
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS",
); );
INFOPLIST_FILE = StatusIm/Info.plist; INFOPLIST_FILE = StatusIm/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift, /usr/lib/swift,
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)", "$(PROJECT_DIR)",
); );
@@ -958,20 +894,19 @@
"-DFOLLY_NO_CONFIG", "-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
); );
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-lc++", "-lc++",
"-ObjC", "-ObjC",
"-lresolv",
); );
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum;
PRODUCT_NAME = StatusIm; PRODUCT_NAME = StatusIm;
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.2; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = 1;
VALID_ARCHS = "x86_64 arm64"; VALID_ARCHS = "x86_64 arm64";
"VALID_ARCHS[sdk=iphonesimulator*]" = "x86_64 "; "VALID_ARCHS[sdk=iphonesimulator*]" = "x86_64 ";
@@ -980,11 +915,11 @@
}; };
13B07F951A680F5B00A75B9A /* Release */ = { 13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 232FE8EAB57384181B0DB836 /* Pods-Status-StatusIm.release.xcconfig */; baseConfigurationReference = 1CDF317A2E103217DF386083 /* Pods-Status-StatusIm.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(BUNDLE_ID_SUFFIX)"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(BUNDLE_ID_SUFFIX)";
BUNDLE_ID_SUFFIX = ""; BUNDLE_ID_SUFFIX = "";
CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = StatusIm/StatusIm.entitlements; CODE_SIGN_ENTITLEMENTS = StatusIm/StatusIm.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
@@ -1018,14 +953,13 @@
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS",
); );
INFOPLIST_FILE = StatusIm/Info.plist; INFOPLIST_FILE = StatusIm/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift, /usr/lib/swift,
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)", "$(PROJECT_DIR)",
); );
@@ -1034,20 +968,19 @@
"-DFOLLY_NO_CONFIG", "-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
); );
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-lc++", "-lc++",
"-ObjC", "-ObjC",
"-lresolv",
); );
PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum;
PRODUCT_NAME = StatusIm; PRODUCT_NAME = StatusIm;
PROVISIONING_PROFILE = "e2202b12-7a66-4ff7-af3c-a52e35f32dc1"; PROVISIONING_PROFILE = "e2202b12-7a66-4ff7-af3c-a52e35f32dc1";
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc im.status.ethereum"; PROVISIONING_PROFILE_SPECIFIER = "match AdHoc im.status.ethereum";
SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h";
SWIFT_VERSION = 5.2; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = 1;
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
}; };
@@ -1055,11 +988,11 @@
}; };
3AAD2ADA24A3A60E0075D594 /* Debug */ = { 3AAD2ADA24A3A60E0075D594 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7BF7B2DB23EE09E5229629DA /* Pods-Status-StatusImPR.debug.xcconfig */; baseConfigurationReference = C618F2C2EF820C722B1E7624 /* Pods-Status-StatusImPR.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(BUNDLE_ID_SUFFIX)"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon$(BUNDLE_ID_SUFFIX)";
BUNDLE_ID_SUFFIX = .debug; BUNDLE_ID_SUFFIX = .debug;
CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = StatusImPR/StatusImPR.entitlements; CODE_SIGN_ENTITLEMENTS = StatusImPR/StatusImPR.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "iPhone Distribution";
@@ -1098,14 +1031,13 @@
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS",
); );
INFOPLIST_FILE = StatusImPR/Info.plist; INFOPLIST_FILE = StatusImPR/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift, /usr/lib/swift,
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)", "$(PROJECT_DIR)",
); );
@@ -1114,20 +1046,18 @@
"-DFOLLY_NO_CONFIG", "-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
); );
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-lc++", "-lc++",
"-ObjC", "-ObjC",
"-lresolv",
); );
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum.pr; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum.pr;
PRODUCT_NAME = "Status PR"; PRODUCT_NAME = "Status PR";
PROVISIONING_PROFILE_SPECIFIER = "match Development im.status.ethereum.pr"; PROVISIONING_PROFILE_SPECIFIER = "match Development im.status.ethereum.pr";
SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.2; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = 1;
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
}; };
@@ -1135,11 +1065,11 @@
}; };
3AAD2ADB24A3A60E0075D594 /* Release */ = { 3AAD2ADB24A3A60E0075D594 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7A393286DD0E844D050D0B89 /* Pods-Status-StatusImPR.release.xcconfig */; baseConfigurationReference = 06AF19FA626AFFC91E66916B /* Pods-Status-StatusImPR.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIconPR$(BUNDLE_ID_SUFFIX)"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIconPR$(BUNDLE_ID_SUFFIX)";
BUNDLE_ID_SUFFIX = ""; BUNDLE_ID_SUFFIX = "";
CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = StatusImPR/StatusImPR.entitlements; CODE_SIGN_ENTITLEMENTS = StatusImPR/StatusImPR.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_IDENTITY = "iPhone Developer";
@@ -1172,14 +1102,13 @@
"$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS", "$(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS",
); );
INFOPLIST_FILE = StatusImPR/Info.plist; INFOPLIST_FILE = StatusImPR/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
/usr/lib/swift, /usr/lib/swift,
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"$(inherited)", "$(inherited)",
"$(PROJECT_DIR)", "$(PROJECT_DIR)",
); );
@@ -1188,19 +1117,17 @@
"-DFOLLY_NO_CONFIG", "-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
); );
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-lc++", "-lc++",
"-ObjC", "-ObjC",
"-lresolv",
); );
PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum.pr; PRODUCT_BUNDLE_IDENTIFIER = im.status.ethereum.pr;
PRODUCT_NAME = "Status PR"; PRODUCT_NAME = "Status PR";
PROVISIONING_PROFILE_SPECIFIER = "match AdHoc im.status.ethereum.pr"; PROVISIONING_PROFILE_SPECIFIER = "match AdHoc im.status.ethereum.pr";
SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "StatusIm-Bridging-Header.h";
SWIFT_VERSION = 5.2; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1; TARGETED_DEVICE_FAMILY = 1;
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
}; };
@@ -1212,7 +1139,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
@@ -1239,14 +1166,13 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8B5X2M6H2Y; DEVELOPMENT_TEAM = 8B5X2M6H2Y;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
EXCLUDED_ARCHS = ""; EXCLUDED_ARCHS = "";
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
@@ -1277,30 +1203,21 @@
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer", "$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
"$(SRCROOT)/../node_modules/react-native-lottie-splash-screen/ios/**", "$(SRCROOT)/../node_modules/react-native-lottie-splash-screen/ios/**",
); );
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
"\"$(inherited)\"", "\"$(inherited)\"",
); );
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
" ",
);
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)", "$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG", "-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
" ",
); );
OTHER_LDFLAGS = "$(inherited)"; PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
USE_HERMES = true;
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
"VALID_ARCHS[sdk=iphonesimulator*]" = x86_64; "VALID_ARCHS[sdk=iphonesimulator*]" = x86_64;
}; };
@@ -1312,7 +1229,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
@@ -1339,13 +1256,12 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 8B5X2M6H2Y; DEVELOPMENT_TEAM = 8B5X2M6H2Y;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
EXCLUDED_ARCHS = ""; EXCLUDED_ARCHS = "";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES; GCC_NO_COMMON_BLOCKS = YES;
GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PRECOMPILE_PREFIX_HEADER = NO;
@@ -1368,30 +1284,21 @@
"$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer", "$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer",
"$(SRCROOT)/../node_modules/react-native-lottie-splash-screen/ios/**", "$(SRCROOT)/../node_modules/react-native-lottie-splash-screen/ios/**",
); );
IPHONEOS_DEPLOYMENT_TARGET = 13.4; IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LIBRARY_SEARCH_PATHS = ( LIBRARY_SEARCH_PATHS = (
"$(SDKROOT)/usr/lib/swift",
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
"\"$(inherited)\"", "\"$(inherited)\"",
); );
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
ONLY_ACTIVE_ARCH = NO; ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"$(inherited)",
" ",
);
OTHER_CPLUSPLUSFLAGS = ( OTHER_CPLUSPLUSFLAGS = (
"$(OTHER_CFLAGS)", "$(OTHER_CFLAGS)",
"-DFOLLY_NO_CONFIG", "-DFOLLY_NO_CONFIG",
"-DFOLLY_MOBILE=1", "-DFOLLY_MOBILE=1",
"-DFOLLY_USE_LIBCPP=1", "-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
" ",
); );
OTHER_LDFLAGS = "$(inherited)"; PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES;
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
USE_HERMES = true;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
VALID_ARCHS = arm64; VALID_ARCHS = arm64;
}; };
+4 -2
View File
@@ -7,10 +7,12 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import <RCTAppDelegate.h> #import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h> #import <UserNotifications/UNUserNotificationCenter.h>
@interface AppDelegate : RCTAppDelegate <UIApplicationDelegate, UNUserNotificationCenterDelegate> @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;
@end @end
+81 -7
View File
@@ -17,6 +17,7 @@
#import "RNSplashScreen.h" #import "RNSplashScreen.h"
#import "RCTLinkingManager.h" #import "RCTLinkingManager.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h> #import <React/RCTBundleURLProvider.h>
#import <React/RCTHTTPRequestHandler.h> #import <React/RCTHTTPRequestHandler.h>
@@ -27,8 +28,30 @@
#import <SDWebImage/SDWebImageDownloaderOperation.h> #import <SDWebImage/SDWebImageDownloaderOperation.h>
#import <Security/Security.h> #import <Security/Security.h>
// adding this for v0.68.x
#import <React/RCTAppSetupUtils.h>
#if RCT_NEW_ARCH_ENABLED
#import <React/CoreModulesPlugins.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#import <React/RCTSurfacePresenter.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <ReactCommon/RCTTurboModuleManager.h>
#import <react/config/ReactNativeConfig.h> #import <react/config/ReactNativeConfig.h>
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
@interface AppDelegate () <RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
RCTTurboModuleManager *_turboModuleManager;
RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
facebook::react::ContextContainer::Shared _contextContainer;
}
@end
#endif
//TODO: properly import the framework //TODO: properly import the framework
extern "C" NSString* StatusgoImageServerTLSCert(); extern "C" NSString* StatusgoImageServerTLSCert();
@@ -43,12 +66,18 @@ extern "C" NSString* StatusgoImageServerTLSCert();
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ {
RCTAppSetupPrepareApp(application);
if (!self.bridge) { RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; [ReactNativeNavigation bootstrapWithBridge:bridge];
}
[ReactNativeNavigation bootstrapWithBridge:self.bridge]; #if RCT_NEW_ARCH_ENABLED
_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
#endif
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
NSURL *jsCodeLocation; NSURL *jsCodeLocation;
@@ -103,12 +132,26 @@ extern "C" NSString* StatusgoImageServerTLSCert();
} }
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{ {
return [self getBundleURL]; // Switch this bool to turn on and off the concurrent root
return true;
}
- (NSDictionary *)prepareInitialProps
{
NSMutableDictionary *initProps = [NSMutableDictionary new];
#ifdef RCT_NEW_ARCH_ENABLED
initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
#endif
return initProps;
} }
- (NSURL *)getBundleURL - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{ {
#if DEBUG #if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
@@ -117,6 +160,37 @@ extern "C" NSString* StatusgoImageServerTLSCert();
#endif #endif
} }
#if RCT_NEW_ARCH_ENABLED
#pragma mark - RCTCxxBridgeDelegate
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
delegate:self
jsInvoker:bridge.jsCallInvoker];
return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
}
#pragma mark RCTTurboModuleManagerDelegate
- (Class)getModuleClassFromName:(const char *)name
{
return RCTCoreModulesClassProvider(name);
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return nullptr;
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
initParams:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return nullptr;
}
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass
{
return RCTAppSetupDefaultModuleFromClass(moduleClass);
}
#endif
- (void)applicationWillResignActive:(UIApplication *)application { - (void)applicationWillResignActive:(UIApplication *)application {
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"BLANK_PREVIEW"]) { if ([[NSUserDefaults standardUserDefaults] boolForKey:@"BLANK_PREVIEW"]) {
[self.window addSubview:_blankView]; [self.window addSubview:_blankView];
+18 -13
View File
@@ -2,12 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleBuildUrl</key> <key>CFBundleBuildUrl</key>
<string>????</string> <string>????</string>
<key>CFBundleCommitHash</key> <key>CFBundleCommitHash</key>
<string>unknown</string> <string>unknown</string>
<key>NSFaceIDUsageDescription</key>
<string>Enabling Face ID allows you quick and secure access to your account.</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
@@ -59,29 +59,31 @@
</array> </array>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NFCReaderUsageDescription</key>
<string>Enable Keycard</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
<true/> <true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict> </dict>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>Status uses camera to take pictures and scan QR codes.</string> <string>Status uses camera to take pictures and scan QR codes.</string>
<key>NSFaceIDUsageDescription</key>
<string>Enabling Face ID allows you quick and secure access to your account.</string>
<key>NSLocationAlwaysUsageDescription</key> <key>NSLocationAlwaysUsageDescription</key>
<string>Location access is required for some DApps to function properly.</string> <string>Location access is required for some DApps to function properly.</string>
<key>NSLocationWhenInUseUsageDescription</key> <key>NSLocationWhenInUseUsageDescription</key>
<string>Location access is required for some DApps to function properly.</string> <string>Location access is required for some DApps to function properly.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for sending audio messages.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Photos access is required to give you the ability to save images.</string>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>Photos access is required to give you the ability to send images.</string> <string>Photos access is required to give you the ability to send images.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Photos access is required to give you the ability to save images.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for sending audio messages.</string>
<key>UIAppFonts</key> <key>UIAppFonts</key>
<array> <array>
<string>Inter-Bold.otf</string> <string>Inter-Bold.otf</string>
@@ -131,12 +133,15 @@
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <true/>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key> <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array> <array>
<string>A00000080400010101</string> <string>A00000080400010101</string>
<string>A00000080400010301</string> <string>A00000080400010301</string>
<string>A000000151000000</string> <string>A000000151000000</string>
</array> </array>
<key>NFCReaderUsageDescription</key>
<string>Enable Keycard</string>
<key>CADisableMinimumFrameDurationOnPhone</key><true/>
</dict> </dict>
</plist> </plist>
+14
View File
@@ -0,0 +1,14 @@
# Description
This directory is the destination of logs created by Fastlane and React Native Xcode script.
# Logs
* `react-native-xcode.log` - Output from `node_modules/react-native/scripts/react-native-xcode.sh`.
- Created by redirecting output of `shellScript` in `ios/StatusIm.xcodeproj/project.pbxproj`.
* `Status PR-StatusImPR.log - Created by [Fastlane Gym](https://docs.fastlane.tools/actions/gym/).
- Configred via [`Fastfile`](../Fastfile) using `buildlog_path` argument for `build_ios_app`.
# CI
These log files are uploaded to Jenkins as CI job artifacts on failure using `archiveArtifacts`.
-29
View File
@@ -1,29 +0,0 @@
# Description
This directory is the destination of logs created during build time of debug builds and logs created by Fastlane on CI.
# Logs
* `xcrun_device_install.log` - Output from `status-mobile/scripts/run-ios-device.sh`.
- Created by redirecting output of `xcrun simctl install "$UDID" "$APP_PATH"`.
* `xcrun_device_process_launch.log` - Output from `status-mobile/scripts/run-ios-device.sh`.
- Created by specifying `--json-output` flag for `xcrun devicectl device process launch --no-activate --verbose --device "${DEVICE_UUID}" "${INSTALLATION_URL}"`.
* `xcrun_device_process_resume.log` - Output from `status-mobile/scripts/run-ios-device.sh`.
- Created by redirecting output of `xcrun devicectl device process resume --device "${DEVICE_UUID}" --pid "${STATUS_PID}"`.
* `adb_install.log` - Output from `scripts/run-android.sh`.
- Created by redirecting output of `adb install -r ./result/app-debug.apk`.
* `adb_shell_monkey.log` - Output from `status-mobile/scripts/run-android.sh`.
- Created by redirecting output of `adb shell monkey -p im.status.ethereum.debug 1 >`.
* `ios_simulators_list.log` - Output from `status-mobile/scripts/run-ios.sh`.
- Created by redirecting output of `xcrun simctl list devices -j`.
# CI
These log files are uploaded to Jenkins as CI job artifacts on failure using `archiveArtifacts`.
* `react-native-xcode.log` - Output from `node_modules/react-native/scripts/react-native-xcode.sh`.
- Created by redirecting output of `shellScript` in `ios/StatusIm.xcodeproj/project.pbxproj` for "Bundle React Native code and images" build Phase.
* `set_xcode_version.log` - Output from `node_modules/react-native/scripts/react-native-xcode.sh`.
- Created by redirecting output of `shellScript` in `ios/StatusIm.xcodeproj/project.pbxproj` for "Run Script" build Phase.
* `Status PR-StatusImPR.log - Created by [Fastlane Gym](https://docs.fastlane.tools/actions/gym/).
- Configred via [`Fastfile`](../Fastfile) using `buildlog_path` argument for `build_ios_app`.
-11
View File
@@ -1,11 +0,0 @@
appId: im.status.ethereum.debug
---
- runFlow: # to run onboarding flow only when device is in onboarding state
when:
visible: "Im new to Status"
file: onboarding.yaml
- runFlow: # to run login flow only when device is on login screen
when:
visible: "Profile password"
file: login.yaml
-5
View File
@@ -1,5 +0,0 @@
appId: im.status.ethereum.debug
---
- tapOn: "password-input"
- inputText: "password123" # update your account password here
- tapOn: login-button
-15
View File
@@ -1,15 +0,0 @@
appId: im.status.ethereum.debug
---
- tapOn: "Im new to Status"
- tapOn: "small-option-card"
- tapOn: "Your name"
- inputText: "DeviceA"
- tapOn: "submit-create-profile-button"
- inputText: "password123"
- tapOn: "Repeat password"
- inputText: "password123"
- tapOn: "disclaimer-touchable-opacity"
- tapOn: "Confirm password"
- tapOn: "skip-identifiers"
- tapOn: "enable-notifications-later-button"
- tapOn: "welcome-button"
+4 -9
View File
@@ -1,11 +1,10 @@
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
/** /**
* Metro configuration * Metro configuration for React Native
* https://facebook.github.io/metro/docs/configuration * https://github.com/facebook/react-native
* *
* @type {import('metro-config').MetroConfig} * @format
*/ */
const config = { module.exports = {
transformer: { transformer: {
getTransformOptions: async () => ({ getTransformOptions: async () => ({
transform: { transform: {
@@ -15,10 +14,6 @@ const config = {
}), }),
}, },
resolver: { resolver: {
resolverMainFields: ['react-native', 'browser', 'main'],
nodeModulesPaths: ['./node_modules'],
extraNodeModules: require('node-libs-react-native'), extraNodeModules: require('node-libs-react-native'),
unstable_enableSymlinks: true,
}, },
}; };
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
@@ -1,5 +1,4 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: "org.jetbrains.kotlin.android"
def getStatusGoSHA1 = { -> def getStatusGoSHA1 = { ->
def statusgoOverridePath = System.getenv("STATUS_GO_SRC_OVERRIDE") def statusgoOverridePath = System.getenv("STATUS_GO_SRC_OVERRIDE")
@@ -1,333 +0,0 @@
package im.status.ethereum.module
import android.app.Activity
import android.content.Context
import android.util.Log
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import org.json.JSONException
import org.json.JSONObject
import statusgo.Statusgo
import java.io.*
class AccountManager(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private val utils = Utils(reactContext)
private val logManager = LogManager(reactContext)
override fun getName() = "AccountManager"
private fun getTestnetDataDir(absRootDirPath: String) = utils.pathCombine(absRootDirPath, "ethereum/testnet")
@ReactMethod
fun createAccountAndLogin(createAccountRequest: String) {
Log.d(TAG, "createAccountAndLogin")
val result = Statusgo.createAccountAndLogin(createAccountRequest)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "createAccountAndLogin success: $result")
Log.d(TAG, "Geth node started")
} else {
Log.e(TAG, "createAccountAndLogin failed: $result")
}
}
@ReactMethod
fun restoreAccountAndLogin(restoreAccountRequest: String) {
Log.d(TAG, "restoreAccountAndLogin")
val result = Statusgo.restoreAccountAndLogin(restoreAccountRequest)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "restoreAccountAndLogin success: $result")
Log.d(TAG, "Geth node started")
} else {
Log.e(TAG, "restoreAccountAndLogin failed: $result")
}
}
private fun updateConfig(jsonConfigString: String, absRootDirPath: String, keystoreDirPath: String): String {
val jsonConfig = JSONObject(jsonConfigString)
// when doing local pair syncing, backend will provide default data dir
val dataDirPath = jsonConfig.optString("DataDir","")
val logEnabled = jsonConfig.getBoolean("LogEnabled")
val gethLogFile = if (logEnabled) logManager.prepareLogsFile(reactContext) else null
val gethLogDirPath = gethLogFile?.parent
Log.d(TAG, "log dir: $gethLogDirPath log name: $gethLogFileName")
jsonConfig.put("DataDir", dataDirPath)
jsonConfig.put("KeyStoreDir", keystoreDirPath)
jsonConfig.put("LogDir", gethLogDirPath)
jsonConfig.put("LogFile", gethLogFileName)
return jsonConfig.toString()
}
private fun copyDirectory(sourceLocation: File, targetLocation: File) {
if (sourceLocation.isDirectory) {
if (!targetLocation.exists() && !targetLocation.mkdirs()) {
throw IOException("Cannot create dir ${targetLocation.absolutePath}")
}
val children = sourceLocation.list()
children?.forEach { child ->
copyDirectory(File(sourceLocation, child), File(targetLocation, child))
}
} else {
val directory = targetLocation.parentFile
if (directory != null && !directory.exists() && !directory.mkdirs()) {
throw IOException("Cannot create dir ${directory.absolutePath}")
}
sourceLocation.inputStream().use { input ->
targetLocation.outputStream().use { output ->
input.copyTo(output)
}
}
}
}
private fun prepareDirAndUpdateConfig(jsonConfigString: String, keyUID: String): String {
val absRootDirPath = utils.getNoBackupDirectory()
val dataFolder = getTestnetDataDir(absRootDirPath)
Log.d(TAG, "Starting Geth node in folder: $dataFolder")
try {
File(dataFolder).mkdir()
} catch (e: Exception) {
Log.e(TAG, "error making folder: $dataFolder", e)
}
val ropstenFlagPath = utils.pathCombine(absRootDirPath, "ropsten_flag")
val ropstenFlag = File(ropstenFlagPath)
if (!ropstenFlag.exists()) {
try {
val chaindDataFolderPath = utils.pathCombine(dataFolder, "StatusIM/lightchaindata")
val lightChainFolder = File(chaindDataFolderPath)
if (lightChainFolder.isDirectory) {
lightChainFolder.listFiles()?.forEach { it.delete() }
}
lightChainFolder.delete()
ropstenFlag.createNewFile()
} catch (e: IOException) {
e.printStackTrace()
}
}
val testnetDataDir = dataFolder
val oldKeystoreDir = utils.pathCombine(testnetDataDir, "keystore")
val newKeystoreDir = utils.pathCombine(absRootDirPath, "keystore")
val oldKeystore = File(oldKeystoreDir)
if (oldKeystore.exists()) {
try {
val newKeystore = File(newKeystoreDir)
copyDirectory(oldKeystore, newKeystore)
if (oldKeystore.isDirectory) {
oldKeystore.listFiles()?.forEach { it.delete() }
}
oldKeystore.delete()
} catch (e: IOException) {
e.printStackTrace()
}
}
return try {
val multiaccountKeystoreDir = utils.pathCombine("/keystore", keyUID)
val updatedJsonConfigString = updateConfig(jsonConfigString, absRootDirPath, multiaccountKeystoreDir)
prettyPrintConfig(updatedJsonConfigString)
updatedJsonConfigString
} catch (e: JSONException) {
Log.e(TAG, "updateConfig failed: ${e.message}")
""
}
}
@ReactMethod
fun prepareDirAndUpdateConfig(keyUID: String, config: String, callback: Callback) {
Log.d(TAG, "prepareDirAndUpdateConfig")
val finalConfig = prepareDirAndUpdateConfig(config, keyUID)
callback.invoke(finalConfig)
}
@ReactMethod
fun saveAccountAndLoginWithKeycard(
multiaccountData: String,
password: String,
settings: String,
config: String,
accountsData: String,
chatKey: String
) {
try {
Log.d(TAG, "saveAccountAndLoginWithKeycard")
val keyUID = utils.getKeyUID(multiaccountData)
val finalConfig = prepareDirAndUpdateConfig(config, keyUID)
val result = Statusgo.saveAccountAndLoginWithKeycard(
multiaccountData,
password,
settings,
finalConfig,
accountsData,
chatKey
)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "saveAccountAndLoginWithKeycard result: $result")
Log.d(TAG, "Geth node started")
} else {
Log.e(TAG, "saveAccountAndLoginWithKeycard failed: $result")
}
} catch (e: JSONException) {
Log.e(TAG, "JSON conversion failed: ${e.message}")
}
}
@ReactMethod
fun loginWithKeycard(accountData: String, password: String, chatKey: String, nodeConfigJSON: String) {
Log.d(TAG, "loginWithKeycard")
utils.migrateKeyStoreDir(accountData, password)
val result = Statusgo.loginWithKeycard(accountData, password, chatKey, nodeConfigJSON)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "LoginWithKeycard result: $result")
} else {
Log.e(TAG, "LoginWithKeycard failed: $result")
}
}
@ReactMethod
fun loginWithConfig(accountData: String, password: String, configJSON: String) {
Log.d(TAG, "loginWithConfig")
utils.migrateKeyStoreDir(accountData, password)
val result = Statusgo.loginWithConfig(accountData, password, configJSON)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "LoginWithConfig result: $result")
} else {
Log.e(TAG, "LoginWithConfig failed: $result")
}
}
@ReactMethod
fun loginAccount(request: String) {
Log.d(TAG, "loginAccount")
val result = Statusgo.loginAccount(request)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "loginAccount result: $result")
} else {
Log.e(TAG, "loginAccount failed: $result")
}
}
@ReactMethod
fun verify(address: String, password: String, callback: Callback) {
val absRootDirPath = utils.getNoBackupDirectory()
val newKeystoreDir = utils.pathCombine(absRootDirPath, "keystore")
utils.executeRunnableStatusGoMethod(
{ Statusgo.verifyAccountPassword(newKeystoreDir, address, password) },
callback
)
}
@ReactMethod
fun verifyDatabasePassword(keyUID: String, password: String, callback: Callback) {
utils.executeRunnableStatusGoMethod(
{ Statusgo.verifyDatabasePassword(keyUID, password) },
callback
)
}
@ReactMethod
private fun openAccounts(callback: Callback) {
Log.d(TAG, "openAccounts")
val rootDir = utils.getNoBackupDirectory()
Log.d(TAG, "[Opening accounts $rootDir")
utils.executeRunnableStatusGoMethod({ Statusgo.openAccounts(rootDir) }, callback)
}
@ReactMethod
fun logout() {
Log.d(TAG, "logout")
val runnable = Runnable {
val result = Statusgo.logout()
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "Logout result: $result")
} else {
Log.e(TAG, "Logout failed: $result")
}
}
StatusThreadPoolExecutor.getInstance().execute(runnable)
}
@ReactMethod
fun multiAccountStoreAccount(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountStoreAccount(json) }, callback)
}
@ReactMethod
fun multiAccountLoadAccount(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountLoadAccount(json) }, callback)
}
@ReactMethod
fun multiAccountDeriveAddresses(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountDeriveAddresses(json) }, callback)
}
@ReactMethod
fun multiAccountGenerateAndDeriveAddresses(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountGenerateAndDeriveAddresses(json) }, callback)
}
@ReactMethod
fun multiAccountStoreDerived(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountStoreDerivedAccounts(json) }, callback)
}
@ReactMethod
fun multiAccountImportMnemonic(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountImportMnemonic(json) }, callback)
}
@ReactMethod
fun multiAccountImportPrivateKey(json: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.multiAccountImportPrivateKey(json) }, callback)
}
@ReactMethod
fun deleteMultiaccount(keyUID: String, callback: Callback) {
val keyStoreDir = utils.getKeyStorePath(keyUID)
utils.executeRunnableStatusGoMethod({ Statusgo.deleteMultiaccount(keyUID, keyStoreDir) }, callback)
}
@ReactMethod
fun getRandomMnemonic(callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.getRandomMnemonic() }, callback)
}
@ReactMethod
fun createAccountFromMnemonicAndDeriveAccountsForPaths(mnemonic: String, callback: Callback) {
utils.executeRunnableStatusGoMethod(
{ Statusgo.createAccountFromMnemonicAndDeriveAccountsForPaths(mnemonic) },
callback
)
}
companion object {
private const val TAG = "AccountManager"
private const val gethLogFileName = "geth.log"
private fun prettyPrintConfig(config: String) {
Log.d(TAG, "startNode() with config (see below)")
var configOutput = config
val maxOutputLen = 4000
Log.d(TAG, "********************** NODE CONFIG ****************************")
while (configOutput.isNotEmpty()) {
Log.d(TAG, "Node config:${configOutput.take(maxOutputLen)}")
configOutput = configOutput.drop(maxOutputLen)
}
Log.d(TAG, "******************* ENDOF NODE CONFIG *************************")
}
}
}
@@ -1,58 +0,0 @@
package im.status.ethereum.module
import android.content.Context
import android.os.Environment
import android.util.Log
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import statusgo.Statusgo
import java.io.File
class DatabaseManager(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private val utils = Utils(reactContext)
override fun getName() = "DatabaseManager"
private fun getExportDBFile(): File {
val pubDirectory = reactContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
return File(pubDirectory, exportDBFileName)
}
@ReactMethod
fun exportUnencryptedDatabase(accountData: String, password: String, callback: Callback) {
Log.d(TAG, "login")
val newFile = getExportDBFile()
utils.migrateKeyStoreDir(accountData, password)
val result = Statusgo.exportUnencryptedDatabase(accountData, password, newFile.absolutePath)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "Login result: $result")
} else {
Log.e(TAG, "Login failed: $result")
}
}
@ReactMethod
fun importUnencryptedDatabase(accountData: String, password: String) {
Log.d(TAG, "importUnencryptedDatabase")
val newFile = getExportDBFile()
utils.migrateKeyStoreDir(accountData, password)
val result = Statusgo.importUnencryptedDatabase(accountData, password, newFile.absolutePath)
if (result.startsWith("{\"error\":\"\"")) {
Log.d(TAG, "import result: $result")
} else {
Log.e(TAG, "import failed: $result")
}
}
companion object {
private const val TAG = "DatabaseManager"
private const val exportDBFileName = "export.db"
}
}
@@ -1,173 +0,0 @@
package im.status.ethereum.module;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.Callback;
import android.util.Log;
import statusgo.Statusgo;
import org.json.JSONException;
import java.util.function.Function;
import android.app.Activity;
import android.view.WindowManager;
import android.os.Build;
import android.view.Window;
import android.preference.PreferenceManager;
import android.content.SharedPreferences;
public class EncryptionUtils extends ReactContextBaseJavaModule {
private static final String TAG = "EncryptionUtils";
private ReactApplicationContext reactContext;
private Utils utils;
public EncryptionUtils(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
this.utils = new Utils(reactContext);
}
@Override
public String getName() {
return "EncryptionUtils";
}
@ReactMethod
private void initKeystore(final String keyUID, final Callback callback) throws JSONException {
Log.d(TAG, "initKeystore");
final String commonKeydir = this.utils.pathCombine(this.utils.getNoBackupDirectory(), "/keystore");
final String keydir = this.utils.pathCombine(commonKeydir, keyUID);
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.initKeystore(keydir), callback);
}
@ReactMethod
public void reEncryptDbAndKeystore(final String keyUID, final String password, final String newPassword, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.changeDatabasePassword(keyUID, password, newPassword), callback);
}
@ReactMethod
public void convertToKeycardAccount(final String keyUID, final String accountData, final String options, final String keycardUID, final String password,
final String newPassword, final Callback callback) throws JSONException {
final String keyStoreDir = this.utils.getKeyStorePath(keyUID);
this.utils.executeRunnableStatusGoMethod(() -> {
Statusgo.initKeystore(keyStoreDir);
return Statusgo.convertToKeycardAccount(accountData, options, keycardUID, password, newPassword);
}, callback);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String encodeTransfer(final String to, final String value) {
return Statusgo.encodeTransfer(to, value);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String decodeParameters(final String decodeParamJSON) {
return Statusgo.decodeParameters(decodeParamJSON);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String hexToNumber(final String hex) {
return Statusgo.hexToNumber(hex);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String numberToHex(final String numString) {
return Statusgo.numberToHex(numString);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String sha3(final String str) {
return Statusgo.sha3(str);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String utf8ToHex(final String str) {
return Statusgo.utf8ToHex(str);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String hexToUtf8(final String str) {
return Statusgo.hexToUtf8(str);
}
@ReactMethod
public void setBlankPreviewFlag(final Boolean blankPreview) {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.reactContext);
sharedPrefs.edit().putBoolean("BLANK_PREVIEW", blankPreview).commit();
setSecureFlag();
}
private void setSecureFlag() {
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this.reactContext);
final boolean setSecure = sharedPrefs.getBoolean("BLANK_PREVIEW", true);
final Activity activity = this.reactContext.getCurrentActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
final Window window = activity.getWindow();
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);
}
}
});
}
}
@ReactMethod
public void hashTransaction(final String txArgsJSON, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashTransaction(txArgsJSON), callback);
}
@ReactMethod
public void hashMessage(final String message, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashMessage(message), callback);
}
@ReactMethod
public void multiformatDeserializePublicKey(final String multiCodecKey, final String base58btc, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.multiformatDeserializePublicKey(multiCodecKey,base58btc), callback);
}
@ReactMethod
public void deserializeAndCompressKey(final String desktopKey, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.deserializeAndCompressKey(desktopKey), callback);
}
@ReactMethod
public void hashTypedData(final String data, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashTypedData(data), callback);
}
@ReactMethod
public void hashTypedDataV4(final String data, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.hashTypedDataV4(data), callback);
}
@ReactMethod
public void signMessage(final String rpcParams, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signMessage(rpcParams), callback);
}
@ReactMethod
public void signTypedData(final String data, final String account, final String password, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signTypedData(data, account, password), callback);
}
@ReactMethod
public void signTypedDataV4(final String data, final String account, final String password, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signTypedDataV4(data, account, password), callback);
}
@ReactMethod
public void signGroupMembership(final String content, final Callback callback) throws JSONException {
this.utils.executeRunnableStatusGoMethod(() -> Statusgo.signGroupMembership(content), callback);
}
}
@@ -1,211 +0,0 @@
package im.status.ethereum.module
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.net.Uri
import android.util.Log
import androidx.core.content.FileProvider
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import org.json.JSONException
import org.json.JSONObject
import statusgo.Statusgo
import java.io.*
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
class LogManager(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private val utils = Utils(reactContext)
override fun getName() = "LogManager"
private fun getLogsFile(): File {
val pubDirectory = utils.getPublicStorageDirectory()
return File(pubDirectory, gethLogFileName)
}
fun prepareLogsFile(context: Context): File? {
val logFile = utils.getLogsFile()
try {
logFile.setReadable(true)
val parent = logFile.parentFile
if (!parent?.canWrite()!!) {
return null
}
if (!parent.exists()) {
parent.mkdirs()
}
logFile.createNewFile()
logFile.setWritable(true)
Log.d(TAG, "Can write ${logFile.canWrite()}")
val gethLogUri = Uri.fromFile(logFile)
val gethLogFilePath = logFile.absolutePath
Log.d(TAG, gethLogFilePath)
return logFile
} catch (e: Exception) {
Log.d(TAG, "Can't create geth.log file! ${e.message}")
}
return null
}
private fun showErrorMessage(message: String) {
val activity = currentActivity
AlertDialog.Builder(activity)
.setTitle("Error")
.setMessage(message)
.setNegativeButton("Exit") { dialog, _ ->
dialog.dismiss()
}.show()
}
private fun dumpAdbLogsTo(statusLogStream: FileOutputStream) {
val filter = "logcat -d -b main ReactNativeJS:D StatusModule:D StatusService:D StatusNativeLogs:D *:S"
val p = Runtime.getRuntime().exec(filter)
val input = BufferedReader(InputStreamReader(p.inputStream))
val output = BufferedWriter(OutputStreamWriter(statusLogStream))
var line: String?
while (input.readLine().also { line = it } != null) {
output.write(line)
output.newLine()
}
output.close()
input.close()
}
private fun zip(files: Array<File>, zipFile: File, errorList: Stack<String>): Boolean {
val BUFFER = 0x8000
try {
var origin: BufferedInputStream? = null
val dest = FileOutputStream(zipFile)
val out = ZipOutputStream(BufferedOutputStream(dest))
val data = ByteArray(BUFFER)
for (file in files) {
if (file == null || !file.exists()) {
continue
}
Log.v("Compress", "Adding: ${file.absolutePath}")
try {
val fi = FileInputStream(file)
origin = BufferedInputStream(fi, BUFFER)
val entry = ZipEntry(file.name)
out.putNextEntry(entry)
var count: Int
while (origin.read(data, 0, BUFFER).also { count = it } != -1) {
out.write(data, 0, count)
}
origin.close()
} catch (e: IOException) {
Log.e(TAG, e.message!!)
errorList.push(e.message!!)
}
}
out.close()
return true
} catch (e: Exception) {
Log.e(TAG, e.message!!)
e.printStackTrace()
return false
}
}
@ReactMethod
fun sendLogs(dbJson: String, jsLogs: String, callback: Callback) {
Log.d(TAG, "sendLogs")
if (!utils.checkAvailability()) {
return
}
val context = reactApplicationContext
val logsTempDir = File(context.cacheDir, "logs") // This path needs to be in sync with android/app/src/main/res/xml/file_provider_paths.xml
logsTempDir.mkdir()
val dbFile = File(logsTempDir, "db.json")
try {
val outputStreamWriter = OutputStreamWriter(FileOutputStream(dbFile))
outputStreamWriter.write(dbJson)
outputStreamWriter.close()
} catch (e: IOException) {
Log.e(TAG, "File write failed: ${e}")
showErrorMessage(e.localizedMessage!!)
}
val zipFile = File(logsTempDir, logsZipFileName)
val statusLogFile = File(logsTempDir, statusLogFileName)
val gethLogFile = getLogsFile()
try {
if (zipFile.exists() || zipFile.createNewFile()) {
val usableSpace = zipFile.usableSpace
if (usableSpace < 20 * 1024 * 1024) {
val message = "Insufficient space available on device (${android.text.format.Formatter.formatShortFileSize(context, usableSpace)}) to write logs.\nPlease free up some space."
Log.e(TAG, message)
showErrorMessage(message)
return
}
}
dumpAdbLogsTo(FileOutputStream(statusLogFile))
val errorList = Stack<String>()
val zipped = zip(arrayOf(dbFile, gethLogFile, statusLogFile), zipFile, errorList)
if (zipped && zipFile.exists()) {
zipFile.setReadable(true, false)
val extUri = FileProvider.getUriForFile(context, "${context.packageName}.provider", zipFile)
callback.invoke(extUri.toString())
} else {
Log.d(TAG, "File ${zipFile.absolutePath} does not exist")
}
} catch (e: Exception) {
Log.e(TAG, e.message!!)
showErrorMessage(e.localizedMessage!!)
e.printStackTrace()
return
} finally {
dbFile.delete()
statusLogFile.delete()
zipFile.deleteOnExit()
}
}
@ReactMethod
fun initLogging(enabled: Boolean, mobileSystem: Boolean, logLevel: String, callback: Callback) {
val jsonConfig = JSONObject().apply {
put("Enabled", enabled)
put("MobileSystem", mobileSystem)
put("Level", logLevel)
put("File", getLogsFile().absolutePath)
}
val config = jsonConfig.toString()
utils.executeRunnableStatusGoMethod({ Statusgo.initLogging(config) }, callback)
}
@ReactMethod(isBlockingSynchronousMethod = true)
fun logFileDirectory(): String? {
return utils.getPublicStorageDirectory()?.absolutePath
}
companion object {
private const val TAG = "LogManager"
private const val gethLogFileName = "geth.log"
private const val statusLogFileName = "Status.log"
private const val logsZipFileName = "Status-debug-logs.zip"
}
}
@@ -1,133 +0,0 @@
package im.status.ethereum.module
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.Callback
import android.util.Log
import android.content.Intent
import android.net.Uri
import android.content.pm.PackageManager
import java.io.File
import androidx.core.content.FileProvider
import android.text.Html
class MailManager(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private val utils = Utils(reactContext)
override fun getName() = "MailManager"
@ReactMethod
fun mail(options: ReadableMap, callback: Callback) {
Log.d(TAG, "attempting to send email")
val i = Intent(Intent.ACTION_SEND_MULTIPLE)
val selectorIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
i.selector = selectorIntent
if (options.hasKey("subject") && !options.isNull("subject")) {
i.putExtra(Intent.EXTRA_SUBJECT, options.getString("subject"))
}
if (options.hasKey("body") && !options.isNull("body")) {
val body = options.getString("body")
if (options.hasKey("isHTML") && options.getBoolean("isHTML")) {
i.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(body))
} else {
i.putExtra(Intent.EXTRA_TEXT, body)
}
}
if (options.hasKey("recipients") && !options.isNull("recipients")) {
val recipients = options.getArray("recipients")
i.putExtra(Intent.EXTRA_EMAIL, this.utils.readableArrayToStringArray(recipients!!))
}
if (options.hasKey("ccRecipients") && !options.isNull("ccRecipients")) {
val ccRecipients = options.getArray("ccRecipients")
i.putExtra(Intent.EXTRA_CC, this.utils.readableArrayToStringArray(ccRecipients!!))
}
if (options.hasKey("bccRecipients") && !options.isNull("bccRecipients")) {
val bccRecipients = options.getArray("bccRecipients")
i.putExtra(Intent.EXTRA_BCC, this.utils.readableArrayToStringArray(bccRecipients!!))
}
if (options.hasKey("attachments") && !options.isNull("attachments")) {
val r = options.getArray("attachments")
val length = r?.size() ?: 0
val provider = reactContext.applicationContext.packageName + ".rnmail.provider"
val resolvedIntentActivities = reactContext.packageManager.queryIntentActivities(i,
PackageManager.MATCH_DEFAULT_ONLY)
val uris = ArrayList<Uri>()
for (keyIndex in 0 until length) {
val clip = r?.getMap(keyIndex)
val uri: Uri
if (clip?.hasKey("path") == true && !clip.isNull("path")) {
val path = clip.getString("path")
val file = File(path)
uri = FileProvider.getUriForFile(reactContext, provider, file)
} else if (clip?.hasKey("uri") == true && !clip.isNull("uri")) {
val uriPath = clip.getString("uri")
uri = Uri.parse(uriPath)
} else {
callback.invoke("not_found")
return
}
uris.add(uri)
for (resolvedIntentInfo in resolvedIntentActivities) {
val packageName = resolvedIntentInfo.activityInfo.packageName
reactContext.grantUriPermission(packageName, uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
}
val manager = reactContext.packageManager
val list = manager.queryIntentActivities(i, 0)
if (list == null || list.isEmpty()) {
Log.d(TAG, "not_available")
callback.invoke("not_available")
return
}
if (list.size == 1) {
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
reactContext.startActivity(i)
} catch (ex: Exception) {
Log.e(TAG, ex.message!!)
callback.invoke("error")
}
} else {
var chooserTitle = "Send Mail"
if (options.hasKey("customChooserTitle") && !options.isNull("customChooserTitle")) {
chooserTitle = options.getString("customChooserTitle") ?: ""
}
val chooser = Intent.createChooser(i, chooserTitle)
chooser.flags = Intent.FLAG_ACTIVITY_NEW_TASK
try {
reactContext.startActivity(chooser)
} catch (ex: Exception) {
Log.e(TAG, ex.message!!)
callback.invoke("error")
}
}
}
companion object {
private const val TAG = "MailManager"
}
}
@@ -1,78 +0,0 @@
package im.status.ethereum.module
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import org.json.JSONException
import org.json.JSONObject
import statusgo.Statusgo
class NetworkManager(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private val utils = Utils(reactContext)
override fun getName() = "NetworkManager"
@ReactMethod
fun startSearchForLocalPairingPeers(callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.startSearchForLocalPairingPeers() }, callback)
}
@ReactMethod
fun getConnectionStringForBootstrappingAnotherDevice(configJSON: String, callback: Callback) {
val jsonConfig = JSONObject(configJSON)
val senderConfig = jsonConfig.getJSONObject("senderConfig")
val keyUID = senderConfig.getString("keyUID")
val keyStorePath = utils.getKeyStorePath(keyUID)
senderConfig.put("keystorePath", keyStorePath)
utils.executeRunnableStatusGoMethod(
{ Statusgo.getConnectionStringForBootstrappingAnotherDevice(jsonConfig.toString()) },
callback
)
}
@ReactMethod
fun inputConnectionStringForBootstrapping(connectionString: String, configJSON: String, callback: Callback) {
val jsonConfig = JSONObject(configJSON)
val receiverConfig = jsonConfig.getJSONObject("receiverConfig")
val keyStorePath = utils.pathCombine(utils.getNoBackupDirectory(), "/keystore")
receiverConfig.put("keystorePath", keyStorePath)
receiverConfig.getJSONObject("nodeConfig").put("rootDataDir", utils.getNoBackupDirectory())
utils.executeRunnableStatusGoMethod(
{ Statusgo.inputConnectionStringForBootstrapping(connectionString, jsonConfig.toString()) },
callback
)
}
@ReactMethod
fun sendTransactionWithSignature(txArgsJSON: String, signature: String, callback: Callback) {
utils.executeRunnableStatusGoMethod(
{ Statusgo.sendTransactionWithSignature(txArgsJSON, signature) },
callback
)
}
@ReactMethod
fun sendTransaction(txArgsJSON: String, password: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.sendTransaction(txArgsJSON, password) }, callback)
}
@ReactMethod
fun callRPC(payload: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.callRPC(payload) }, callback)
}
@ReactMethod
fun callPrivateRPC(payload: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.callPrivateRPC(payload) }, callback)
}
@ReactMethod
fun recover(rpcParams: String, callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.recover(rpcParams) }, callback)
}
}
@@ -0,0 +1,78 @@
package im.status.ethereum.module;
import android.view.ActionMode;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.UIBlock;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.views.textinput.ReactEditText;
import javax.annotation.Nonnull;
class RNSelectableTextInputModule extends ReactContextBaseJavaModule {
private ActionMode lastActionMode;
public RNSelectableTextInputModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Nonnull
@Override
public String getName() {
return "RNSelectableTextInputManager";
}
@ReactMethod
public void setupMenuItems(final Integer selectableTextViewReactTag, final Integer textInputReactTag) {
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
RNSelectableTextInputViewManager rnSelectableTextManager = (RNSelectableTextInputViewManager) nvhm.resolveViewManager(selectableTextViewReactTag);
ReactEditText reactTextView = (ReactEditText) nvhm.resolveView(textInputReactTag);
rnSelectableTextManager.registerSelectionListener(reactTextView);
}
});
}
@ReactMethod
public void startActionMode(final Integer textInputReactTag) {
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
ReactEditText reactTextView = (ReactEditText) nvhm.resolveView(textInputReactTag);
lastActionMode = reactTextView.startActionMode(reactTextView.getCustomSelectionActionModeCallback(), ActionMode.TYPE_FLOATING);
}
});
}
@ReactMethod
public void hideLastActionMode(){
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
if(lastActionMode!=null){
lastActionMode.finish();
lastActionMode = null;
}
}
});
}
@ReactMethod
public void setSelection(final Integer textInputReactTag, final Integer start, final Integer end){
ReactApplicationContext reactContext = this.getReactApplicationContext();
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
uiManager.addUIBlock(new UIBlock() {
public void execute (NativeViewHierarchyManager nvhm) {
ReactEditText reactTextView = (ReactEditText) nvhm.resolveView(textInputReactTag);
reactTextView.setSelection(start, end);
}
});
}
}
@@ -1,72 +0,0 @@
package im.status.ethereum.module
import android.view.ActionMode
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.uimanager.NativeViewHierarchyManager
import com.facebook.react.uimanager.UIBlock
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.views.textinput.ReactEditText
class RNSelectableTextInputModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
private var lastActionMode: ActionMode? = null
override fun getName(): String {
return "RNSelectableTextInputManager"
}
@ReactMethod
fun setupMenuItems(selectableTextViewReactTag: Int?, textInputReactTag: Int?) {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
selectableTextViewReactTag?.let { selectableTag ->
textInputReactTag?.let { inputTag ->
uiManager?.addUIBlock(UIBlock { nvhm: NativeViewHierarchyManager ->
val rnSelectableTextManager = nvhm.resolveViewManager(selectableTag) as RNSelectableTextInputViewManager
val reactTextView = nvhm.resolveView(inputTag) as ReactEditText
rnSelectableTextManager.registerSelectionListener(reactTextView)
})
}
}
}
@ReactMethod
fun startActionMode(textInputReactTag: Int?) {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
textInputReactTag?.let { inputTag ->
uiManager?.addUIBlock(UIBlock { nvhm: NativeViewHierarchyManager ->
val reactTextView = nvhm.resolveView(inputTag) as ReactEditText
lastActionMode = reactTextView.startActionMode(reactTextView.customSelectionActionModeCallback, ActionMode.TYPE_FLOATING)
})
}
}
@ReactMethod
fun hideLastActionMode() {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
uiManager?.addUIBlock(UIBlock { _ ->
lastActionMode?.finish()
lastActionMode = null
})
}
@ReactMethod
fun setSelection(textInputReactTag: Int?, start: Int?, end: Int?) {
val reactContext = reactApplicationContext
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
textInputReactTag?.let { inputTag ->
start?.let { s ->
end?.let { e ->
uiManager?.addUIBlock(UIBlock { nvhm: NativeViewHierarchyManager ->
val reactTextView = nvhm.resolveView(inputTag) as ReactEditText
reactTextView.setSelection(s, e)
})
}
}
}
}
}
@@ -0,0 +1,102 @@
package im.status.ethereum.module;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.Menu;
import android.view.MenuItem;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.react.views.textinput.ReactEditText;
import com.facebook.react.views.view.ReactViewGroup;
import com.facebook.react.views.view.ReactViewManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class RNSelectableTextInputViewManager extends ReactViewManager {
public static final String REACT_CLASS = "RNSelectableTextInput";
private String[] _menuItems = new String[0];
@Override
public String getName() {
return REACT_CLASS;
}
@Override
public ReactViewGroup createViewInstance(ThemedReactContext context) {
return new ReactViewGroup(context);
}
@ReactProp(name = "menuItems")
public void setMenuItems(ReactViewGroup reactViewGroup, ReadableArray items) {
if(items != null) {
List<String> result = new ArrayList<String>(items.size());
for (int i = 0; i < items.size(); i++) {
result.add(items.getString(i));
}
this._menuItems = result.toArray(new String[items.size()]);
}
}
public void registerSelectionListener(final ReactEditText view) {
view.setCustomSelectionActionModeCallback(new Callback() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
menu.clear();
for (int i = 0; i < _menuItems.length; i++) {
menu.add(0, i, 0, _menuItems[i]);
}
return true;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
int selectionStart = view.getSelectionStart();
int selectionEnd = view.getSelectionEnd();
String selectedText = view.getText().toString().substring(selectionStart, selectionEnd);
// Dispatch event
onSelectNativeEvent(view, item.getItemId(), selectedText, selectionStart, selectionEnd);
mode.finish();
return true;
}
});
}
public void onSelectNativeEvent(ReactEditText view, int eventType, String content, int selectionStart, int selectionEnd) {
WritableMap event = Arguments.createMap();
event.putInt("eventType", eventType);
event.putString("content", content);
event.putInt("selectionStart", selectionStart);
event.putInt("selectionEnd", selectionEnd);
// Dispatch
ReactContext reactContext = (ReactContext) view.getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(view.getId(), "topSelection", event);
}
@Override
public Map getExportedCustomDirectEventTypeConstants() {
return MapBuilder.builder()
.put("topSelection", MapBuilder.of("registrationName","onSelection"))
.build();
}
}
@@ -1,85 +0,0 @@
package im.status.ethereum.module
import android.view.ActionMode
import android.view.Menu
import android.view.MenuItem
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.WritableMap
import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.uimanager.events.RCTEventEmitter
import com.facebook.react.views.textinput.ReactEditText
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.view.ReactViewManager
class RNSelectableTextInputViewManager : ReactViewManager() {
companion object {
const val REACT_CLASS = "RNSelectableTextInput"
}
private var _menuItems = arrayOf<String>()
override fun getName(): String {
return REACT_CLASS
}
override fun createViewInstance(context: ThemedReactContext): ReactViewGroup {
return ReactViewGroup(context)
}
@ReactProp(name = "menuItems")
fun setMenuItems(reactViewGroup: ReactViewGroup, items: ReadableArray?) {
_menuItems = items?.let {
Array(items.size()) { i -> items.getString(i) }
} ?: arrayOf()
}
fun registerSelectionListener(view: ReactEditText) {
view.customSelectionActionModeCallback = object : ActionMode.Callback {
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
menu.clear()
_menuItems.forEachIndexed { i, item ->
menu.add(0, i, 0, item)
}
return true
}
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
return true
}
override fun onDestroyActionMode(mode: ActionMode) {}
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
val selectionStart = view.selectionStart
val selectionEnd = view.selectionEnd
val selectedText = view.text.toString().substring(selectionStart, selectionEnd)
onSelectNativeEvent(view, item.itemId, selectedText, selectionStart, selectionEnd)
mode.finish()
return true
}
}
}
private fun onSelectNativeEvent(view: ReactEditText, eventType: Int, content: String, selectionStart: Int, selectionEnd: Int) {
val event: WritableMap = Arguments.createMap().apply {
putInt("eventType", eventType)
putString("content", content)
putInt("selectionStart", selectionStart)
putInt("selectionEnd", selectionEnd)
}
val reactContext = view.context as ReactContext
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(view.id, "topSelection", event)
}
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
return MapBuilder.builder<String, Any>()
.put("topSelection", MapBuilder.of("registrationName", "onSelection"))
.build()
}
}
@@ -1,113 +0,0 @@
package im.status.ethereum.module
import android.app.Activity
import android.os.Build
import android.util.Log
import com.facebook.react.bridge.*
import com.facebook.react.modules.core.DeviceEventManagerModule
import statusgo.SignalHandler
import statusgo.Statusgo
import org.json.JSONException
import android.view.WindowManager
class StatusModule(private val reactContext: ReactApplicationContext, private val rootedDevice: Boolean) : ReactContextBaseJavaModule(reactContext), LifecycleEventListener, SignalHandler {
companion object {
private const val TAG = "StatusModule"
private var module: StatusModule? = null
}
private val utils: Utils = Utils(reactContext)
private var background: Boolean = false
init {
reactContext.addLifecycleEventListener(this)
}
override fun getName(): String {
return "Status"
}
override fun onHostResume() {
module = this
background = false
Statusgo.setMobileSignalHandler(this)
}
override fun onHostPause() {
background = true
}
override fun onHostDestroy() {
Log.d(TAG, "******************* ON HOST DESTROY *************************")
}
override fun handleSignal(jsonEventString: String) {
val params = Arguments.createMap()
params.putString("jsonEvent", jsonEventString)
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java).emit("gethEvent", params)
}
@ReactMethod
fun closeApplication() {
System.exit(0)
}
@ReactMethod
fun connectionChange(type: String, isExpensive: Boolean) {
Log.d(TAG, "ConnectionChange: $type, is expensive $isExpensive")
Statusgo.connectionChange(type, if (isExpensive) 1 else 0)
}
@ReactMethod
fun appStateChange(type: String) {
Log.d(TAG, "AppStateChange: $type")
Statusgo.appStateChange(type)
}
@ReactMethod
fun startLocalNotifications() {
Log.d(TAG, "startLocalNotifications")
Statusgo.startLocalNotifications()
}
@ReactMethod
fun getNodeConfig(callback: Callback) {
utils.executeRunnableStatusGoMethod({ Statusgo.getNodeConfig() }, callback)
}
@ReactMethod
fun deleteImportedKey(keyUID: String, address: String, password: String, callback: Callback) {
val keyStoreDir = utils.getKeyStorePath(keyUID)
utils.executeRunnableStatusGoMethod({ Statusgo.deleteImportedKey(address, password, keyStoreDir) }, callback)
}
@ReactMethod(isBlockingSynchronousMethod = true)
fun fleets(): String {
return Statusgo.fleets()
}
override fun getConstants(): Map<String, Any>? {
return hashMapOf(
"is24Hour" to utils.is24Hour(),
"model" to Build.MODEL,
"brand" to Build.BRAND,
"buildId" to Build.ID,
"deviceId" to Build.BOARD
)
}
@ReactMethod
fun isDeviceRooted(callback: Callback) {
callback.invoke(rootedDevice)
}
@ReactMethod
fun deactivateKeepAwake() {
val activity = currentActivity
activity?.runOnUiThread {
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
}
@@ -0,0 +1,44 @@
package im.status.ethereum.module;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import statusgo.Statusgo;
public class StatusPackage implements ReactPackage {
private boolean rootedDevice;
public static String getImageTLSCert() {
return Statusgo.imageServerTLSCert();
}
public StatusPackage(boolean rootedDevice) {
this.rootedDevice = rootedDevice;
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new StatusModule(reactContext, this.rootedDevice));
modules.add(new RNSelectableTextInputModule(reactContext));
return modules;
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new RNSelectableTextInputViewManager()
);
}
}
@@ -1,39 +0,0 @@
package im.status.ethereum.module
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
import statusgo.Statusgo
class StatusPackage(private val rootedDevice: Boolean) : ReactPackage {
companion object {
fun getImageTLSCert(): String = Statusgo.imageServerTLSCert()
}
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
val modules = mutableListOf<NativeModule>()
modules.apply {
add(StatusModule(reactContext, rootedDevice))
add(AccountManager(reactContext))
add(EncryptionUtils(reactContext))
add(DatabaseManager(reactContext))
add(UIHelper(reactContext))
add(LogManager(reactContext))
add(Utils(reactContext))
add(NetworkManager(reactContext))
add(MailManager(reactContext))
add(RNSelectableTextInputModule(reactContext))
}
return modules
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return listOf(
RNSelectableTextInputViewManager()
)
}
}

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