Update release branch 2.30.x (#20903)

Revisions from develop:

- 59ceddbaa develop origin/develop fix(wallet): fix bridge transactions (#20902)
- 99ccbc338 Cover wallet send events with tests Part 2 #20411 #20533 (#20721)
- 8c2d5398b Enabling WalletConnect feature flag (#20906)
- 67c83b13e fix(wallet): remove edit routes button in bridging (#20874)
- 11a84ba14 feat(wallet): disable complex routing (#20901)
- 1f5bb579c chore(wallet): disable bridging on unsupported tokens (#20846)
- 4586f8007 Add toggle in advanced settings for mobile data
- 55c620e59 fix: create password for small screen (#20645)
- 525609f0a Wallet Activity: transactions are not sorted by time #20808 (#20862)
- 90653955a chore(settings): Disable telemetry option (#20881)
- d27ab756d fix_:display group message using the new ui (#20787)
- c6a1db633 ci: enable split apks & build only for arm64-v8a (#20683)
- 73777e052 Ensure keycard account can send transaction after upgrading from v1 to v2 #20552 (#20845)
- a6d3fc374 [#20524] fix: the missed keypairs are shown in the key pair list screen (#20888)
- a671c7083 fix broken screen and navigation when syncing fails (#20887)
- a45991b6d 🥅 Filter connected dapps based on testnet mode, reject proposals and requests gracefully (#20799)
- 2e9fa22e4 feat: wallet router v2 (#20631)
- 737d8c4d5 rename sub to fix error when requesting to join community (#20868)
- 3aa7e103f Sync process is blocked on Enabled notifications screen (#20883)
- c1d2d44da perf: Fix app freeze after login (#20729)
- 0fed8113d e2e: updated testnet switching and added one test into smoke
- 53c35cb55 fix(wallet): Linear gradient exception on invalid colors for watched account cards (#20854)
- be8236554 chore(settings)_: Remove testnet toggle from legacy advanced settings (#20875)
- eae8a6559 feat(wallet)_: Add beta info box in activity tab (#20873)
- fe54a25a3 fix: not clearing network & web3-wallet on logout (#20886)
- 15a4219ef Reject wallet-connect request by dragging the modal down (#20763) (#20836)
- 2ffbdac89 WalletConnect show expired toast (#20857)
- 402eb8397 fix Issue with scrolling WalletConnect transaction on Android (#20867)
- ff88049a0 Fix WalletConnect header alignment on Android (#20860)
- cee21241d WalletConnect no internet edge-cases (#20826)
- 60ad7c8a2 chore(tests): New match-strict? cljs.test directive (#20825)
- 4989c9278 fix_: Adding own address as saved addresses (#20839)
This commit is contained in:
Icaro Motta 2024-07-30 11:28:07 -03:00 committed by GitHub
parent a1784c5e1f
commit 0f15c0192d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
175 changed files with 2973 additions and 2297 deletions

View File

@ -74,7 +74,8 @@
;; https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number
legacy.status-im.test-helpers/restore-app-db]}
legacy.status-im.test-helpers/restore-app-db
(cljs.test/is [match-strict?])]}
:unresolved-var {:level :error}
:unsorted-required-namespaces {:level :error}
:unused-alias {:level :warning}

1
.env
View File

@ -35,3 +35,4 @@ FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
SHOW_NOT_IMPLEMENTED_FEATURES=0
ENABLE_ALERT_BANNER=0
FLAG_WALLET_CONNECT_ENABLED=1

View File

@ -38,3 +38,5 @@ SHOW_NOT_IMPLEMENTED_FEATURES=1
DELETE_MESSAGE_FOR_ME_UNDO_TIME_LIMIT=10000
DELETE_MESSAGE_UNDO_TIME_LIMIT=10000
ENABLE_ALERT_BANNER=0
FLAG_WALLET_CONNECT_ENABLED=1
MOBILE_DATA_SYNCING_TOGGLE_ENABLE=0

View File

@ -36,3 +36,4 @@ LOCAL_PAIRING_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=1
TEST_NETWORKS_ENABLED=1
ENABLE_ALERT_BANNER=1
FLAG_WALLET_CONNECT_ENABLED=1

View File

@ -23,3 +23,4 @@ DELETE_MESSAGE_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
ENABLE_ALERT_BANNER=1
FLAG_WALLET_CONNECT_ENABLED=1

View File

@ -19,3 +19,4 @@ MAX_IMAGES_BATCH=1
DELETE_MESSAGE_ENABLED=1
FAST_CREATE_COMMUNITY_ENABLED=0
TEST_NETWORKS_ENABLED=0
FLAG_WALLET_CONNECT_ENABLED=1

View File

@ -215,15 +215,13 @@ build-fdroid: ##@build Build release for F-Droid
build-android: export BUILD_ENV ?= prod
build-android: export BUILD_TYPE ?= nightly
build-android: export ORG_GRADLE_PROJECT_versionCode ?= $(TMP_BUILD_NUMBER)
build-android: export ANDROID_ABI_SPLIT ?= false
build-android: export ANDROID_ABI_INCLUDE ?= armeabi-v7a;arm64-v8a;x86
build-android: ##@build Build unsigned Android APK
@scripts/build-android.sh
release-android: export TARGET := keytool
release-android: export KEYSTORE_PATH ?= $(HOME)/.gradle/status-im.keystore
release-android: keystore build-android ##@build Build signed Android APK
@scripts/sign-android.sh result/app-release-unsigned.apk
@scripts/sign-android.sh result/app-arm64-v8a-release-unsigned.apk
release-ios: export TARGET := ios
release-ios: export IOS_STATUS_GO_TARGETS := ios/arm64

View File

@ -211,7 +211,7 @@ android {
reset()
enable getEnvOrConfig('ANDROID_ABI_SPLIT').toBoolean()
include getEnvOrConfig('ANDROID_ABI_INCLUDE').split(";")
universalApk true
universalApk false
}
}
signingConfigs {

View File

@ -38,10 +38,10 @@ KEYSTORE_PASSWORD=password
KEYSTORE_ALIAS=status
KEYSTORE_KEY_PASSWORD=password
# By default we build a mostly universal APK
ANDROID_ABI_SPLIT=false
# Some platforms are excluded though
ANDROID_ABI_INCLUDE=armeabi-v7a;arm64-v8a;x86;x86_64
# Splitting by CPU Architecture produces smaller APKs.
ANDROID_ABI_SPLIT=true
# By default its better to only build apk for most recent devices.
ANDROID_ABI_INCLUDE=arm64-v8a
org.gradle.jvmargs=-Xmx8704M -XX:+UseParallelGC

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@ -72,11 +72,7 @@ pipeline {
stage('Upload') {
steps { script {
def urls = apks.collect { s5cmd.upload(it) }
if (urls.size() > 1) { /* Return only the universal APK. */
env.PKG_URL = urls.find { it.contains('universal') }
} else { /* If no universal is available pick first. */
env.PKG_URL = urls.first()
}
env.PKG_URL = urls.first()
jenkins.setBuildDesc(APK: env.PKG_URL)
} }
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
import groovy.json.JsonBuilder

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label 'linux' }

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label 'macos' }

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label params.AGENT_LABEL }

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent { label 'linux' }

View File

@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.1'
library 'status-jenkins-lib@v1.9.3'
pipeline {
agent {

View File

@ -711,11 +711,11 @@
},
{
"path": "nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8",
"path": "nubank/matcher-combinators/3.9.1/matcher-combinators-3.9.1",
"host": "https://repo.clojars.org",
"jar": {
"sha1": "4c94bd510f0c18a20191e46dd6becedebc640bbd",
"sha256": "0wpla2hx0s4mda58ndyd8938zmnz1gyhgfr6pzfphy27xfbvsssl"
"sha1": "f0830a112cae8ee931a90d9f39214a0ed4d44150",
"sha256": "1rjcgqhms84xmnhs7sqcd3b2dpa37mmzgz2yz33yz2rdb9skl96g"
}
},

View File

@ -77,7 +77,7 @@ net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar
net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar
nrepl/bencode/1.1.0/bencode-1.1.0.jar
nrepl/nrepl/1.0.0/nrepl-1.0.0.jar
nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.jar
nubank/matcher-combinators/3.9.1/matcher-combinators-3.9.1.jar
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar
org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar

View File

@ -18,10 +18,10 @@
buildUrl ? lib.getEnvWithDefault "ORG_GRADLE_PROJECT_buildUrl" null,
statusGoSrcOverride ? lib.getEnvWithDefault "STATUS_GO_SRC_OVERRIDE" null,
# If APKs should be split based on architectures
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "false",
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "true",
# Android architectures to build for
# Used to detect end-to-end builds
androidAbiInclude ? lib.getEnvWithDefault "ANDROID_ABI_INCLUDE" "armeabi-v7a;arm64-v8a;x86",
androidAbiInclude ? lib.getEnvWithDefault "ANDROID_ABI_INCLUDE" "arm64-v8a",
}:
let

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -13,7 +13,7 @@ export BUILD_TYPE=debug
# Install the APK on running emulator or android device.
installAndLaunchApp() {
adb install -r ./result/app-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
adb install -r ./result/app-arm64-v8a-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
"${GIT_ROOT}/scripts/wait-for-metro-port.sh" 2>&1
# connected android devices need this port to be exposed for metro
adb reverse "tcp:${RCT_METRO_PORT}" "tcp:${RCT_METRO_PORT}"

View File

@ -19,7 +19,7 @@
[cider/piggieback "0.4.1"]
[org.slf4j/slf4j-nop "2.0.9"]
[re-frisk-remote "1.6.0"]
[nubank/matcher-combinators "3.8.8"]
[nubank/matcher-combinators "3.9.1"]
;; Use the same version specified in the Nix dependency.
[clj-kondo/clj-kondo "2024.03.13"]

View File

@ -1,8 +1,8 @@
(ns legacy.status-im.data-store.communities
(:require
[clojure.set :as set]
[clojure.walk :as walk]
[status-im.constants :as constants]))
[status-im.constants :as constants]
[utils.transforms :as transforms]))
(defn <-revealed-accounts-rpc
[accounts]
@ -22,19 +22,26 @@
(reduce #(assoc %1 (key-fn %2) (<-request-to-join-community-rpc %2)) {} requests))
(defn <-chats-rpc
[chats]
(reduce-kv (fn [acc k v]
(assoc acc
(name k)
(-> v
(assoc :token-gated? (:tokenGated v)
:can-post? (:canPost v)
:can-view? (:canView v)
:hide-if-permissions-not-met? (:hideIfPermissionsNotMet v))
(dissoc :canPost :tokenGated :canView :hideIfPermissionsNotMet)
(update :members walk/stringify-keys))))
{}
chats))
"This transformation from RPC is optimized differently because there can be
thousands of members in all chats and we don't want to transform them from JS
to CLJS because they will only be used to list community members or community
chat members."
[chats-js]
(let [chat-key-fn (fn [k]
(case k
"tokenGated" :token-gated?
"canPost" :can-post?
"can-view" :can-view?
"hideIfPermissionsNotMet" :hide-if-permissions-not-met?
(keyword k)))
chat-val-fn (fn [k v]
(if (= "members" k)
v
(transforms/js->clj v)))]
(transforms/<-js-map
chats-js
{:val-fn (fn [_ v]
(transforms/<-js-map v {:key-fn chat-key-fn :val-fn chat-val-fn}))})))
(defn <-categories-rpc
[categ]
@ -48,49 +55,59 @@
[token-permission]
(= (:type token-permission) constants/community-token-permission-become-member))
(defn- rename-community-key
[k]
(case k
"canRequestAccess" :can-request-access?
"canManageUsers" :can-manage-users?
"canDeleteMessageForEveryone" :can-delete-message-for-everyone?
;; This flag is misleading based on its name alone
;; because it should not be used to decide if the user
;; is *allowed* to join. Allowance is based on token
;; permissions. Still, the flag can be used to know
;; whether or not the user will have to wait until an
;; admin approves a join request.
"canJoin" :can-join?
"requestedToJoinAt" :requested-to-join-at
"isMember" :is-member?
"outroMessage" :outro-message
"adminSettings" :admin-settings
"tokenPermissions" :token-permissions
"communityTokensMetadata" :tokens-metadata
"introMessage" :intro-message
"muteTill" :muted-till
"lastOpenedAt" :last-opened-at
"joinedAt" :joined-at
(keyword k)))
(defn <-rpc
[c]
(-> c
(set/rename-keys
{:canRequestAccess :can-request-access?
:canManageUsers :can-manage-users?
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
;; This flag is misleading based on its name alone
;; because it should not be used to decide if the user
;; is *allowed* to join. Allowance is based on token
;; permissions. Still, the flag can be used to know
;; whether or not the user will have to wait until an
;; admin approves a join request.
:canJoin :can-join?
:requestedToJoinAt :requested-to-join-at
:isMember :is-member?
:outroMessage :outro-message
:adminSettings :admin-settings
:tokenPermissions :token-permissions
:communityTokensMetadata :tokens-metadata
:introMessage :intro-message
:muteTill :muted-till
:lastOpenedAt :last-opened-at
:joinedAt :joined-at})
(update :admin-settings
set/rename-keys
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
(update :members walk/stringify-keys)
(update :chats <-chats-rpc)
(update :token-permissions seq)
(update :categories <-categories-rpc)
(assoc :role-permissions?
(->> c
:tokenPermissions
vals
(some role-permission?)))
(assoc :membership-permissions?
(->> c
:tokenPermissions
vals
(some membership-permission?)))
(assoc :token-images
(reduce (fn [acc {sym :symbol image :image}]
(assoc acc sym image))
{}
(:communityTokensMetadata c)))))
[c-js]
(let [community (transforms/<-js-map
c-js
{:key-fn rename-community-key
:val-fn (fn [k v]
(case k
"members" v
"chats" (<-chats-rpc v)
(transforms/js->clj v)))})]
(-> community
(update :admin-settings
set/rename-keys
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
(update :token-permissions seq)
(update :categories <-categories-rpc)
(assoc :role-permissions?
(->> community
:tokenPermissions
vals
(some role-permission?)))
(assoc :membership-permissions?
(->> community
:tokenPermissions
vals
(some membership-permission?)))
(assoc :token-images
(reduce (fn [acc {sym :symbol image :image}]
(assoc acc sym image))
{}
(:communityTokensMetadata community))))))

View File

@ -11,14 +11,10 @@
legacy.status-im.fleet.core
legacy.status-im.group-chats.core
legacy.status-im.log-level.core
legacy.status-im.mailserver.constants
[legacy.status-im.mailserver.core :as mailserver]
legacy.status-im.mobile-sync-settings.core
legacy.status-im.multiaccounts.login.core
legacy.status-im.multiaccounts.logout.core
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
legacy.status-im.multiaccounts.update.core
legacy.status-im.network.net-info
legacy.status-im.pairing.core
legacy.status-im.profile.core
legacy.status-im.search.core
@ -135,7 +131,6 @@
(rf/merge cofx
{:db (dissoc db :app-in-background-since)
:effects.biometric/get-supported-type nil}
(mailserver/process-next-messages-request)
(when-not new-account?
(universal-links/process-stored-event))
#(when-let [chat-id (:current-chat-id db)]

View File

@ -1,437 +0,0 @@
(ns ^{:doc "Mailserver events and API"} legacy.status-im.mailserver.core
(:require
[clojure.string :as string]
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.node.core :as node]
[legacy.status-im.utils.mobile-sync :as mobile-network-utils]
[re-frame.core :as re-frame]
[status-im.common.json-rpc.events :as json-rpc]
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
;; How do mailserver work ?
;;
;; - We send a request to the mailserver, we are only interested in the
;; messages since `last-request` up to the last seven days
;; and the last 24 hours for topics that were just joined
;; - The mailserver doesn't directly respond to the request and
;; instead we start receiving messages in the filters for the requested
;; topics.
;; - If the mailserver was not ready when we tried for instance to request
;; the history of a topic after joining a chat, the request will be done
;; as soon as the mailserver becomes available
(defn connected?
[db id]
(= (:mailserver/current-id db) id))
(defn fetch
[db id]
(get-in db [:mailserver/mailservers (node/current-fleet-key db) id]))
(defn fetch-current
[db]
(fetch db (:mailserver/current-id db)))
(defn preferred-mailserver-id
[db]
(get-in db [:profile/profile :pinned-mailservers (node/current-fleet-key db)]))
(defn connection-error-dismissed
[db]
(get-in db [:mailserver/connection-error-dismissed]))
(defn mailserver-address->id
[db address]
(let [current-fleet (node/current-fleet-key db)]
(:id (some #(when (= address (:address %))
%)
(-> db
:mailserver/mailservers
current-fleet
vals)))))
(rf/defn disconnect-from-mailserver
{:events [::disconnect-from-mailserver]}
[{:keys [db] :as cofx}]
{:db (-> db
(assoc :mailserver/state nil)
(dissoc :mailserver/current-request :mailserver/fetching-gaps-in-progress))})
(defn fetch-use-mailservers?
[db]
(get-in db [:profile/profile :use-mailservers?]))
(defonce showing-connection-error-popup? (atom false))
(defn cancel-connection-popup!
[]
(reset! showing-connection-error-popup? false)
(re-frame/dispatch [:mailserver.ui/dismiss-connection-error true]))
(re-frame/reg-fx
::cancel-connection-popup
cancel-connection-popup!)
(rf/defn show-connection-error!
[cofx current-fleet preferred-mailserver]
(reset! showing-connection-error-popup? true)
{:ui/show-confirmation
{:title (i18n/label :t/mailserver-error-title)
:content (i18n/label :t/mailserver-error-content)
:confirm-button-text (i18n/label :t/mailserver-pick-another)
:on-cancel cancel-connection-popup!
:on-accept #(do
(reset! showing-connection-error-popup? false)
(re-frame/dispatch [:mailserver.ui/dismiss-connection-error true])
(re-frame/dispatch [:navigate-to :offline-messaging-settings]))
:extra-options [{:text (i18n/label :t/mailserver-retry)
:onPress #(do
(reset! showing-connection-error-popup? false)
(re-frame/dispatch
[:mailserver.ui/connect-confirmed
current-fleet
preferred-mailserver]))
:style "default"}]}})
(rf/defn handle-successful-request
{:events [::request-success]}
[{:keys [db] :as cofx} response-js]
{:db (dissoc db :mailserver/current-request)
:dispatch [:sanitize-messages-and-process-response response-js]})
(rf/defn handle-mailserver-not-working
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
error-dismissed? (connection-error-dismissed db)
pinned-mailserver (get-in db [:profile/profile :pinned-mailservers current-fleet])]
(when (and pinned-mailserver
(not error-dismissed?)
(not @showing-connection-error-popup?))
(show-connection-error! cofx current-fleet pinned-mailserver))))
(rf/defn handle-request-error
{:events [::request-error]}
[{:keys [db] :as cofx}]
{:db (dissoc db :mailserver/current-request)})
(defn needs-to-fetch-historic-messages?
[db]
(and
(:messenger/started? db)
(mobile-network-utils/syncing-allowed? db)
(fetch-use-mailservers? db)
(not (:mailserver/current-request db))))
(rf/defn process-next-messages-request
{:events [::request-messages]}
[{:keys [db]}]
(when (needs-to-fetch-historic-messages? db)
{:db (assoc db :mailserver/current-request true)
:mailserver/request-all-historic-messages nil}))
(re-frame/reg-fx :mailserver/request-all-historic-messages
(fn []
(json-rpc/call {:method "wakuext_requestAllHistoricMessagesWithRetries"
:params [false]
:js-response true
:on-success #(do
(log/info "fetched historical messages")
(re-frame/dispatch [::request-success %]))
:on-error #(do
(log/error "failed retrieve historical messages" %)
(re-frame/dispatch [::request-error]))})))
(rf/defn handle-mailserver-changed
[{:keys [db] :as cofx} ms]
(if (seq ms)
{:db (assoc db
:mailserver/state :connecting
:mailserver/current-id (keyword ms))}
{:db (assoc db :mailserver/state nil)}))
(rf/defn handle-mailserver-available
[{:keys [db] :as cofx} ms]
{::cancel-connection-popup []
:db (assoc db
:mailserver/state :connected
:mailserver/current-id (keyword ms))})
(rf/defn connected-to-mailserver
[{:keys [db] :as cofx}]
(let [{:keys [address]} (fetch-current db)]
(rf/merge
cofx
{:mailserver/update-mailservers [[address] #(re-frame/dispatch [::request-messages])]})))
(rf/defn handle-request-success
{:events [:mailserver.callback/request-success]}
[{{:keys [chats] :as db} :db} {:keys [request-id topics]}]
(when (:mailserver/current-request db)
{:db (assoc-in db
[:mailserver/current-request :request-id]
request-id)}))
(rf/defn toggle-use-mailservers
[cofx value]
{:json-rpc/call
[{:method "wakuext_toggleUseMailservers"
:params [value]
:on-success #(log/info "successfully toggled use-mailservers" value)
:on-failure #(log/error "failed to toggle use-mailserver" value %)}]})
(rf/defn update-use-mailservers
{:events [:mailserver.ui/use-history-switch-pressed]}
[cofx use-mailservers?]
(rf/merge cofx
(multiaccounts.update/optimistic :use-mailservers? use-mailservers?)
(toggle-use-mailservers use-mailservers?)
(when use-mailservers?
(disconnect-from-mailserver))))
(rf/defn retry-next-messages-request
{:events [:mailserver.ui/retry-request-pressed]}
[{:keys [db] :as cofx}]
(rf/merge cofx
{:db (dissoc db :mailserver/request-error)}
(process-next-messages-request)))
(rf/defn show-request-error-popup
{:events [:mailserver.ui/request-error-pressed]}
[{:keys [db]}]
(let [mailserver-error (:mailserver/request-error db)]
{:effects.utils/show-confirmation
{:title (i18n/label :t/mailserver-request-error-title)
:content (i18n/label :t/mailserver-request-error-content
{:error mailserver-error})
:on-accept #(re-frame/dispatch [:mailserver.ui/retry-request-pressed])
:confirm-button-text (i18n/label :t/mailserver-request-retry)}}))
(def enode-url-regex
#"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})")
(defn- extract-url-components
[address]
(rest (re-matches #"enode://(.*)@(.*)" address)))
(defn valid-enode-url?
[address]
(re-matches enode-url-regex address))
(defn build-url
[address]
(let [[initial host] (extract-url-components address)]
(str "enode://" initial "@" host)))
(rf/defn set-input
{:events [:mailserver.ui/input-changed]}
[{:keys [db]} input-key value]
{:db (update
db
:mailserver.edit/mailserver
assoc
input-key
{:value value
:error (case input-key
:id false
:name (string/blank? value)
:url (not (valid-enode-url? value)))})})
(defn- address->mailserver
[address]
(let [[enode url :as response] (extract-url-components address)]
{:address (if (seq response)
(str "enode://" enode "@" url)
address)
:custom true}))
(defn- build
[id mailserver-name address]
(assoc (address->mailserver address)
:id id
:name mailserver-name))
(def default? (comp not :custom fetch))
(rf/defn edit
{:events [:mailserver.ui/custom-mailserver-selected]}
[{:keys [db] :as cofx} id]
(let [{:keys [id address name]} (fetch db id)
url (when address (build-url address))]
(rf/merge cofx
(set-input :id id)
(set-input :url (str url))
(set-input :name (str name))
(navigation/navigate-to :edit-mailserver nil))))
(defn mailserver->rpc
[mailserver current-fleet]
(-> mailserver
(assoc :fleet (name current-fleet))
(update :id name)))
(rf/defn upsert
{:events [:mailserver.ui/save-pressed]
:interceptors [(re-frame/inject-cofx :random-id-generator)]}
[{{:mailserver.edit/keys [mailserver] :profile/keys [profile] :as db} :db
random-id-generator :random-id-generator
:as cofx}]
(let [{:keys [name url id]} mailserver
current-fleet (node/current-fleet-key db)]
(when (and (not (string/blank? (:value name)))
(valid-enode-url? (:value url)))
(let [mailserver (build
(or (:value id)
(keyword (string/replace (random-id-generator) "-" "")))
(:value name)
(:value url))
current (connected? db (:id mailserver))]
{:db (-> db
(dissoc :mailserver.edit/mailserver)
(assoc-in [:mailserver/mailservers current-fleet (:id mailserver)]
mailserver))
:json-rpc/call
[{:method "mailservers_addMailserver"
:params [(mailserver->rpc mailserver current-fleet)]
:on-success (fn []
;; we naively logout if the user is connected to the edited mailserver
(when current
(re-frame/dispatch
[:multiaccounts.logout.ui/logout-confirmed]))
(log/debug "saved mailserver" id "successfuly"))
:on-failure #(log/error "failed to save mailserver" id %)}]
:dispatch [:navigate-back]}))))
(defn can-delete?
[db id]
(not (or (default? db id)
(connected? db id))))
(rf/defn delete
{:events [:mailserver.ui/delete-confirmed]}
[{:keys [db] :as cofx} id]
(if (can-delete? db id)
{:db (-> db
(update-in
[:mailserver/mailservers (node/current-fleet-key db)]
dissoc
id)
(dissoc :mailserver.edit/mailserver))
:json-rpc/call
[{:method "mailservers_deleteMailserver"
:params [(name id)]
:on-success #(log/debug "deleted mailserver" id)
:on-failure #(log/error "failed to delete mailserver" id %)}]
:dispatch [:navigate-back]}
{:dispatch [:navigate-back]}))
(rf/defn show-connection-confirmation
{:events [:mailserver.ui/default-mailserver-selected :mailserver.ui/connect-pressed]}
[{:keys [db]} mailserver-id]
(let [current-fleet (node/current-fleet-key db)]
{:ui/show-confirmation
{:title (i18n/label :t/close-app-title)
:content
(i18n/label :t/connect-mailserver-content
{:name (get-in db
[:mailserver/mailservers
current-fleet mailserver-id :name])})
:confirm-button-text (i18n/label :t/close-app-button)
:on-accept
#(re-frame/dispatch
[:mailserver.ui/connect-confirmed current-fleet mailserver-id])
:on-cancel nil}}))
(rf/defn show-delete-confirmation
{:events [:mailserver.ui/delete-pressed]}
[{:keys [db]} mailserver-id]
{:ui/show-confirmation
{:title (i18n/label :t/delete-mailserver-title)
:content (i18n/label :t/delete-mailserver-are-you-sure)
:confirm-button-text (i18n/label :t/delete-mailserver)
:on-accept #(re-frame/dispatch
[:mailserver.ui/delete-confirmed mailserver-id])}})
(rf/defn set-url-from-qr
{:events [:mailserver.callback/qr-code-scanned]}
[cofx url]
(assoc (set-input cofx :url url)
:dispatch
[:navigate-back]))
(rf/defn dismiss-connection-error
{:events [:mailserver.ui/dismiss-connection-error]}
[{:keys [db]} new-state]
{:db (assoc db :mailserver/connection-error-dismissed new-state)})
(rf/defn pin-mailserver
{:events [:mailserver.ui/connect-confirmed]}
[{:keys [db] :as cofx} current-fleet mailserver-id]
(let [pinned-mailservers (-> db
(get-in [:profile/profile :pinned-mailservers])
(assoc current-fleet mailserver-id))]
(rf/merge cofx
{:db (assoc db :mailserver/current-id mailserver-id)
:json-rpc/call [{:method "wakuext_setPinnedMailservers"
:params [pinned-mailservers]
:on-success #(log/info "successfully pinned mailserver")
:on-error #(log/error "failed to pin mailserver" %)}]}
(multiaccounts.update/optimistic :pinned-mailservers pinned-mailservers))))
(rf/defn unpin
{:events [:mailserver.ui/unpin-pressed]}
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
pinned-mailservers (-> db
(get-in [:profile/profile :pinned-mailservers])
(dissoc current-fleet))]
(rf/merge cofx
{:json-rpc/call [{:method "wakuext_setPinnedMailservers"
:params [pinned-mailservers]
:on-success #(log/info "successfully unpinned mailserver")
:on-error #(log/error "failed to unpin mailserver" %)}]}
(multiaccounts.update/optimistic
:pinned-mailservers
pinned-mailservers)
(dismiss-connection-error false))))
(rf/defn pin
{:events [:mailserver.ui/pin-pressed]}
[{:keys [db] :as cofx}]
(let [current-fleet (node/current-fleet-key db)
mailserver-id (:mailserver/current-id db)
pinned-mailservers (get-in db [:profile/profile :pinned-mailservers])]
(rf/merge cofx
(multiaccounts.update/multiaccount-update
:pinned-mailservers
(assoc pinned-mailservers
current-fleet
mailserver-id)
{})
(dismiss-connection-error false))))
(rf/defn mailserver-ui-add-pressed
{:events [:mailserver.ui/add-pressed]}
[{:keys [db] :as cofx}]
(rf/merge cofx
{:db (dissoc db :mailserver.edit/mailserver)}
(navigation/navigate-to :edit-mailserver nil)))
(defn add-mailservers
[db mailservers]
(reduce (fn [db {:keys [fleet id name] :as mailserver}]
(let [updated-mailserver
(-> mailserver
(update :id keyword)
(assoc :name (if (seq name) name id))
(dissoc :fleet))]
(assoc-in db
[:mailserver/mailservers (keyword fleet) (keyword id)]
updated-mailserver)))
db
mailservers))

View File

@ -1,109 +0,0 @@
(ns legacy.status-im.mobile-sync-settings.core
(:require
[legacy.status-im.mailserver.core :as mailserver]
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
[legacy.status-im.multiaccounts.update.core :as multiaccounts.update]
[legacy.status-im.utils.mobile-sync :as utils]
[re-frame.core :as re-frame]
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/defn sheet-defaults
[{:keys [db]}]
(let [remember-choice? (get-in db [:profile/profile :remember-syncing-choice?])]
{:db (assoc db
:mobile-network/remember-choice?
(or (nil? remember-choice?)
remember-choice?))}))
(re-frame/reg-event-fx :mobile-network/on-network-status-change
(fn [{:keys [db]}]
(let [previously-initialized? (get db :network-status/initialized?)
logged-in? (multiaccounts.model/logged-in? db)
fetch-historic-messages? (mailserver/needs-to-fetch-historic-messages? db)]
(if logged-in?
{:db (cond-> (-> db
(assoc :network-status/initialized? true)
(assoc :bottom-sheet/show? false))
fetch-historic-messages?
(assoc :mailserver/current-request true))
:fx [(when fetch-historic-messages?
[:mailserver/request-all-historic-messages])
[:dispatch [:hide-bottom-sheet]]
(when previously-initialized?
(let [new-identity-input (get-in db [:contacts/new-identity :input])]
[:dispatch [:contacts/set-new-identity {:input new-identity-input}]]))]}
{:db (assoc db :network-status/initialized? true)}))))
(defn apply-settings
([sync?] (apply-settings sync? :default))
([sync? remember?]
(fn [{:keys [db] :as cofx}]
(let [network (:network/type db)
remember-choice?
(if (not= :default remember?)
remember?
(:mobile-network/remember-choice? db))
cellular? (utils/cellular? network)]
(log/info "apply mobile network settings"
"sunc?" sync?
"remember?" remember?
"cellular?" cellular?)
(rf/merge
cofx
(multiaccounts.update/multiaccount-update
:syncing-on-mobile-network?
(boolean sync?)
{})
(multiaccounts.update/multiaccount-update
:remember-syncing-choice?
(boolean remember-choice?)
{})
(when (and cellular? sync?)
(mailserver/process-next-messages-request)))))))
(rf/defn mobile-network-continue-syncing
{:events [:mobile-network/continue-syncing]}
[cofx]
((apply-settings true) cofx))
(rf/defn mobile-network-stop-syncing
{:events [:mobile-network/stop-syncing]}
[cofx]
((apply-settings false) cofx))
(rf/defn mobile-network-set-syncing
{:events [:mobile-network/set-syncing]}
[{:keys [db] :as cofx} syncing?]
(let [{:keys [remember-syncing-choice?]} (:profile/profile db)]
((apply-settings syncing? remember-syncing-choice?) cofx)))
(rf/defn mobile-network-ask-on-mobile-network?
{:events [:mobile-network/ask-on-mobile-network?]}
[{:keys [db] :as cofx} ask?]
(let [{:keys [syncing-on-mobile-network?]} (:profile/profile db)]
((apply-settings syncing-on-mobile-network? (not ask?)) cofx)))
(rf/defn mobile-network-restore-defaults
{:events [:mobile-network/restore-defaults]}
[cofx]
((apply-settings false false) cofx))
(rf/defn mobile-network-remember-choice?
{:events [:mobile-network/remember-choice?]}
[{:keys [db]} remember-choice?]
{:db (assoc db :mobile-network/remember-choice? remember-choice?)})
(rf/defn mobile-network-navigate-to-settings
{:events [:mobile-network/navigate-to-settings]}
[cofx]
(rf/merge
cofx
(navigation/hide-bottom-sheet)
(navigation/navigate-to :mobile-network-settings nil)))
(rf/defn mobile-network-show-offline-sheet
{:events [:mobile-network/show-offline-sheet]}
[cofx]
(navigation/hide-bottom-sheet cofx))

View File

@ -14,10 +14,12 @@
(rf/defn initialize-app-db
[{{:keys [keycard initials-avatar-font-file biometrics]
:network/keys [type]}
:network/keys [type status expensive?]}
:db}]
{:db (assoc db/app-db
:network/type type
:network/status status
:network/expensive? expensive?
:initials-avatar-font-file initials-avatar-font-file
:keycard (dissoc keycard :secrets :pin :application-info)
:biometrics biometrics

View File

@ -1,56 +0,0 @@
(ns legacy.status-im.network.net-info
(:require
["@react-native-community/netinfo" :default net-info]
[native-module.core :as native-module]
[re-frame.core :as re-frame]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/defn change-network-status
[{:keys [db] :as cofx} is-connected?]
(rf/merge cofx
{:db (assoc db :network-status (if is-connected? :online :offline))}))
(rf/defn change-network-type
[{:keys [db] :as cofx} network-type expensive?]
(rf/merge cofx
{:db (assoc db :network/type network-type)
:network/notify-status-go [network-type expensive?]
:dispatch [:mobile-network/on-network-status-change]}))
(rf/defn handle-network-info-change
{:events [::network-info-changed]}
[{:keys [db] :as cofx} {:keys [isConnected type details] :as state}]
(let [old-network-status (:network-status db)
old-network-type (:network/type db)
connectivity-status (if isConnected :online :offline)
status-changed? (= connectivity-status old-network-status)
type-changed? (= type old-network-type)]
(log/debug "[net-info]"
"old-network-status" old-network-status
"old-network-type" old-network-type
"connectivity-status" connectivity-status
"type" type
"details" details)
(rf/merge cofx
(when-not status-changed?
(change-network-status isConnected))
(when-not type-changed?
(change-network-type type (:is-connection-expensive details))))))
(defn add-net-info-listener
[]
(when net-info
(.addEventListener ^js net-info
#(re-frame/dispatch [::network-info-changed
(js->clj % :keywordize-keys true)]))))
(re-frame/reg-fx
:network/listen-to-network-info
(fn []
(add-net-info-listener)))
(re-frame/reg-fx
:network/notify-status-go
(fn [[network-type expensive?]]
(native-module/connection-change network-type expensive?)))

View File

@ -15,8 +15,6 @@
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
(reg-root-key-sub :fleets/custom-fleets :custom-fleets)
(reg-root-key-sub :ui/search :ui/search)
(reg-root-key-sub :network/type :network/type)
(reg-root-key-sub :network-status :network-status)
(reg-root-key-sub :peer-stats/count :peer-stats/count)
(reg-root-key-sub :peers-summary :peers-summary)
(reg-root-key-sub :web3-node-version :web3-node-version)

View File

@ -5,6 +5,7 @@
[legacy.status-im.ui.components.list.views :as list]
[quo.core :as quo]
[re-frame.core :as re-frame]
[status-im.feature-flags :as ff]
[utils.i18n :as i18n]
[utils.re-frame :as rf])
(:require-macros [legacy.status-im.utils.views :as views]))
@ -20,8 +21,6 @@
light-client-enabled?
store-confirmations-enabled?
current-fleet
test-networks-enabled?
is-goerli-enabled?
peer-syncing-enabled?]}]
(keep
identity
@ -61,14 +60,14 @@
:on-press
#(re-frame/dispatch [:open-modal :peers-stats])
:chevron true}
{:size :small
:title "Telemetry"
:accessibility-label :telemetry-enabled
:container-margin-bottom 8
:on-press
#(re-frame/dispatch [:profile.settings/toggle-telemetry])
:accessory :switch
:active telemetry-enabled?}
(when (ff/enabled? ::ff/settings.telemetry)
{:size :small
:title "Telemetry"
:accessibility-label :telemetry-enabled
:container-margin-bottom 8
:on-press #(re-frame/dispatch [:profile.settings/toggle-telemetry])
:accessory :switch
:active telemetry-enabled?})
{:size :small
:title (i18n/label :t/light-client-enabled)
:accessibility-label :light-client-enabled
@ -87,22 +86,6 @@
[:wakuv2.ui/toggle-store-confirmations (not store-confirmations-enabled?)])
:accessory :switch
:active store-confirmations-enabled?}
{:size :small
:title "Testnet mode"
:accessibility-label :test-networks-enabled
:container-margin-bottom 8
:on-press
#(re-frame/dispatch [:profile.settings/toggle-test-networks])
:accessory :switch
:active test-networks-enabled?}
{:size :small
:title "Enable Goerli as test network"
:accessibility-label :enable-sepolia-as-test-network
:container-margin-bottom 8
:on-press
#(re-frame/dispatch [:profile.settings/toggle-goerli-test-network])
:accessory :switch
:active is-goerli-enabled?}
{:size :small
:title "Peer syncing"
:accessibility-label :peer-syncing
@ -124,9 +107,7 @@
(views/defview advanced-settings
[]
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
is-goerli-enabled? [:profile/is-goerli-enabled?]
light-client-enabled? [:profile/light-client-enabled?]
(views/letsubs [light-client-enabled? [:profile/light-client-enabled?]
store-confirmations-enabled? [:profile/store-confirmations-enabled?]
telemetry-enabled? [:profile/telemetry-enabled?]
current-log-level [:log-level/current-log-level]
@ -147,8 +128,6 @@
:store-confirmations-enabled? store-confirmations-enabled?
:current-fleet current-fleet
:dev-mode? false
:test-networks-enabled? test-networks-enabled?
:is-goerli-enabled? is-goerli-enabled?
:peer-syncing-enabled? peer-syncing-enabled?})
:key-fn (fn [_ i] (str i))
:render-fn render-item}]]))

View File

@ -127,7 +127,7 @@
(when (and can-manage-users? (= constants/community-on-request-access (:access permissions)))
[requests-to-join community-id])
[rn/flat-list
{:data (keys sorted-members)
{:data sorted-members
:render-data {:community-id community-id
:my-public-key my-public-key
:can-kick-users? (and can-manage-users?

View File

@ -1,51 +0,0 @@
(ns legacy.status-im.ui.screens.mobile-network-settings.sheets
(:require-macros [legacy.status-im.utils.views :as views])
(:require [legacy.status-im.ui.components.list.item :as list.item]
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.mobile-network-settings.sheets-styles :as styles]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]))
(defn title
[label]
[react/view {:style styles/title}
[react/text
{:style styles/title-text}
(i18n/label label)]])
(defn details
[label]
[react/view
{:style styles/details}
[react/text
{:style styles/details-text}
(i18n/label label)]])
(defn separator
[]
[react/view {:style styles/separator}])
(defn go-to-settings
[]
[react/view
{:style styles/go-to-settings-container}
[react/text
{:style styles/go-to-settings
:on-press #(re-frame/dispatch [:mobile-network/navigate-to-settings])}
(i18n/label :t/mobile-network-go-to-settings)]])
(views/defview offline-sheet
[]
[react/view {:flex 1}
[react/view {:align-items :center}
[title :t/mobile-network-sheet-offline]
[details :t/mobile-network-sheet-offline-details]]
[list.item/list-item
{:theme :accent
:title (i18n/label :t/mobile-network-start-syncing)
:subtitle (i18n/label :t/mobile-network-continue-syncing-details)
:subtitle-max-lines 2
:icon :main-icons/network
:on-press #(re-frame/dispatch [:mobile-network/continue-syncing])}]
[separator]
[go-to-settings]])

View File

@ -1,73 +0,0 @@
(ns legacy.status-im.ui.screens.mobile-network-settings.sheets-styles
(:require
[legacy.status-im.ui.components.colors :as colors]))
(def title
{:height 21
:margin-top 8})
(def title-text
{:typography :title-bold})
(def details
{:width 311
:margin-left 32
:margin-right 32
:margin-top 6
:margin-bottom 10})
(def details-text
{:color colors/gray
:text-align :center})
(def separator
{:background-color colors/gray-lighter
:margin-left 72
:align-self :stretch
:height 1
:margin-top 8})
(def checkbox-line-container
{:margin-left 71
:margin-top 13
:height 29
:flex-direction :row
:justify-content :center})
(def checkbox
{:padding 0
:justify-content :center
:align-items :center
:width 18
:height 18
:border-radius 2
:margin-top 6})
(def checkbox-icon
{:tint-color colors/white})
(def checkbox-text-container
{:justify-content :center
:flex 1
:margin-left 13})
(def settings-container
{:margin-left 69
:height 44
:margin-top 6
:align-items :flex-start})
(def settings-text
{:color colors/gray})
(def settings-link
{:color colors/blue})
(def go-to-settings-container
{:height 52
:margin-left 72
:justify-content :center
:align-self :stretch})
(def go-to-settings
{:color colors/blue})

View File

@ -1,32 +0,0 @@
(ns legacy.status-im.ui.screens.mobile-network-settings.style
(:require
[legacy.status-im.ui.components.colors :as colors]))
(def container
{:flex 1})
(def switch-container
{:height 52})
(def details
{:margin-right 16
:margin-left 16
:margin-top 8
:margin-bottom 16})
(def use-mobile-data-text
{:color colors/gray})
(defn settings-separator
[]
{:align-self :stretch
:height 1
:background-color colors/gray-lighter})
(def defaults-container
{:height 52
:justify-content :center
:padding-left 16})
(def defaults
{:color colors/blue})

View File

@ -1,57 +0,0 @@
(ns legacy.status-im.ui.screens.mobile-network-settings.view
(:require-macros [legacy.status-im.utils.views :as views])
(:require
legacy.status-im.mobile-sync-settings.core
[legacy.status-im.ui.components.react :as react]
[legacy.status-im.ui.screens.mobile-network-settings.sheets :as sheets]
[legacy.status-im.ui.screens.mobile-network-settings.style :as styles]
[legacy.status-im.ui.screens.profile.components.views :as profile.components]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]))
(defn hide-sheet-and-dispatch
[event]
(re-frame/dispatch [:bottom-sheet/hide-old])
(re-frame/dispatch event))
(defn settings-separator
[]
[react/view
{:style (styles/settings-separator)}])
;; TODO(Ferossgp): To refactor, uses outdated components
(views/defview mobile-network-settings
[]
(views/letsubs
[{:keys [syncing-on-mobile-network?
remember-syncing-choice?]}
[:profile/profile]]
[:<>
[react/view
{:style styles/switch-container
:accessibility-label "mobile-network-use-mobile"}
[profile.components/settings-switch-item
{:label-kw :t/mobile-network-use-mobile
:value syncing-on-mobile-network?
:action-fn #(hide-sheet-and-dispatch [:mobile-network/set-syncing %])}]]
[react/view {:style styles/details}
[react/text {:style styles/use-mobile-data-text}
(i18n/label :t/mobile-network-use-mobile-data)]]
[react/view
{:style styles/switch-container
:accessibility-label "mobile-network-ask-me"}
[profile.components/settings-switch-item
{:label-kw :t/mobile-network-ask-me
:value (not remember-syncing-choice?)
:action-fn #(hide-sheet-and-dispatch [:mobile-network/ask-on-mobile-network? %])}]]
[settings-separator]
[react/view
{:style styles/defaults-container}
[react/text
{:style styles/defaults
:accessibility-label "restore-defaults"
:on-press #(hide-sheet-and-dispatch [:mobile-network/restore-defaults])}
(i18n/label :t/restore-defaults)]]]))
(def offline-sheet
{:content sheets/offline-sheet})

View File

@ -13,7 +13,6 @@
[legacy.status-im.ui.screens.glossary.view :as glossary]
[legacy.status-im.ui.screens.help-center.views :as help-center]
[legacy.status-im.ui.screens.log-level-settings.views :as log-level-settings]
[legacy.status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[legacy.status-im.ui.screens.notifications-settings.views :as notifications-settings]
[legacy.status-im.ui.screens.offline-messaging-settings.edit-mailserver.views :as edit-mailserver]
[legacy.status-im.ui.screens.offline-messaging-settings.views :as offline-messaging-settings]
@ -145,10 +144,6 @@
:options {:topBar (topbar-options :t/fleet-settings)
:insets {:top? true}}
:component fleet-settings/fleet-settings}
{:name :mobile-network-settings
:options {:topBar (topbar-options :t/mobile-network-settings)
:insets {:top? true}}
:component mobile-network-settings/mobile-network-settings}
{:name :backup-settings
:options {:topBar (topbar-options :t/backup-settings)
:insets {:top? true}}

View File

@ -127,7 +127,7 @@
[:app-state
:current-chat-id
:network
:network-status
:network/status
:peers-summary
:sync-state
:view-id

View File

@ -171,7 +171,7 @@
#js
{:getEnforcing {}})
(def net-info #js {})
(def net-info #js {:addEventListener identity})
(def react-native-biometrics #js {:default {}})
(def react-native-static-safe-area-insets #js {:default {}})

View File

@ -332,7 +332,9 @@
(defn set-blank-preview-flag
[flag]
(log/debug "[native-module] set-blank-preview-flag")
(.setBlankPreviewFlag ^js (encryption) flag))
;; Sometimes the app crashes during logout because `flag` is nil.
(when flag
(.setBlankPreviewFlag ^js (encryption) flag)))
(defn get-device-model-info
[]
@ -385,6 +387,11 @@
(log/debug "[native-module] encode-transfer")
(.encodeTransfer ^js (encryption) to-norm amount-hex))
(defn encode-function-call
[method params]
(log/debug "[native-module] encode-function-call")
(.encodeFunctionCall ^js (encryption) method (types/clj->json params)))
(defn decode-parameters
[bytes-string types]
(log/debug "[native-module] decode-parameters")

View File

@ -60,7 +60,7 @@
(defn icon-color
[{:keys [theme blur? type]}]
(let [theme-with-blur (if blur? :blue theme)
(let [theme-with-blur (if blur? :blur theme)
matcher [theme-with-blur type]]
(case matcher
([:dark :main] [:light :main]) (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)

View File

@ -65,9 +65,8 @@
:style (style/container loading? theme size)}
[loading-view theme]]
[linear-gradient/linear-gradient
(assoc {:style (style/container loading? theme size)}
:colors
(linear-gradient-props theme customization-color))
{:style (style/container loading? theme size)
:colors (linear-gradient-props theme customization-color)}
[rn/pressable
{:accessibility-label :internal-link-card
:on-press on-press}

View File

@ -11,5 +11,5 @@
[:networks [:* [:map [:source :schema.common/image-source]]]]
[:on-press {:optional true} [:maybe fn?]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:state {:optional true} [:maybe [:enum :default :active :selected]]]]]
[:state {:optional true} [:maybe [:enum :default :active :selected :disabled]]]]]
:any])

View File

@ -18,6 +18,7 @@
:padding-vertical 8
:border-radius 12
:height 56
:opacity (when (= state :disabled) 0.3)
:background-color (background-color state customization-color theme)})
(defn check-color

View File

@ -62,6 +62,7 @@
:on-press-in on-press-in
:on-press-out on-press-out
:on-press on-press
:disabled (= state :disabled)
:accessibility-label :token-network}
[info props]
[values props]]))

View File

@ -32,8 +32,7 @@
(def system-message-base-wrapper
{:flex-direction :row
:flex 1
:align-items :center})
:flex 1})
(def system-message-base-content-wrapper
{:align-self :center

View File

@ -127,6 +127,14 @@
(when incoming? [split-text "sent you a contact request" theme true])
[sm-timestamp timestamp theme]]]))
(defn system-message-group
[{:keys [customization-color child]}]
[system-message-base
{:icon {:icon :i/add-user
:color (or customization-color :primary)
:opacity 5}}
[rn/view child]])
(defn system-message-pinned
[{:keys [pinned-by child customization-color timestamp]}]
(let [theme (quo.theme/use-theme)]
@ -183,6 +191,7 @@
:contact-request [system-message-contact-request data]
:added [system-message-added data]
:removed [system-message-removed data]
:group [system-message-group data]
nil)]))
(defn system-message

View File

@ -4,7 +4,7 @@
(defn main
[{:keys [type customization-color]} theme]
{:justify-content :center
{:justify-content :flex-start
:align-items :center
:height 32
:padding-left 4
@ -16,6 +16,7 @@
(defn label
[type theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)
:flex-shrink 1
:margin-left (if (= type :address) 6 4)})
(def collectible-image

View File

@ -58,16 +58,19 @@
- :emoji - string - emoji used for displaying account avatar
- :image-source - resource - image to display on :network, :collectible and :user
- :theme - :light / :dark"
[{:keys [label customization-color type]
[{:keys [label customization-color type container-style]
:as props
:or {customization-color colors/neutral-80-opa-5}}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:accessibility-label :container
:style (style/main (assoc props :customization-color customization-color) theme)}
:style (merge (style/main (assoc props :customization-color customization-color)
theme)
container-style)}
[left-view props]
[text/text
{:style (style/label type theme)
:weight :semi-bold
:size :heading-1}
{:style (style/label type theme)
:weight :semi-bold
:number-of-lines 1
:size :heading-1}
label]]))

View File

@ -21,3 +21,8 @@
(if blur?
(colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(def text
{:flex 1
;; NOTE: assures the ellipses are not cut off when text is too long
:padding-right 2})

View File

@ -59,7 +59,9 @@
[rn/view {:style (merge style/container container-style)}
[text/text
{:size :heading-1
:number-of-lines 1
:weight :semi-bold
:style style/text
:accessibility-label accessibility-label}
title]
(case right

View File

@ -5,7 +5,7 @@
[react-native.platform :as platform]))
(def account-colors
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :flamingo :camel :copper])
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :pink :camel :copper])
(defn alpha
[value opacity]
@ -44,6 +44,13 @@
(alpha light-color light-opacity)
(alpha dark-color dark-opacity))))))
(defn valid-color?
[color]
(or (keyword? color)
(and (string? color)
(or (string/starts-with? color "#")
(string/starts-with? color "rgb")))))
;;;;Neutral
@ -239,7 +246,7 @@
60 "#CC6438"}
:army {50 "#216266"
60 "#1A4E52"}
:flamingo {50 "#F66F8F"
:pink {50 "#F66F8F"
60 "#C55972"}
:purple {50 "#7140FD"
60 "#5A33CA"}
@ -316,13 +323,14 @@
[s]
(and (string? s) (string/starts-with? s "#")))
(def fallback-color (customization :blue))
(defn- get-from-colors-map
[color suffix]
(let [color-without-suffix (get colors-map color)
resolved-color? (hex-string? color-without-suffix)]
(if resolved-color?
(let [color-without-suffix (get colors-map color fallback-color)]
(if (hex-string? color-without-suffix)
color-without-suffix
(get-in colors-map [color suffix]))))
(get color-without-suffix suffix))))
(defn- resolve-color*
([color theme]
@ -356,11 +364,15 @@
([color suffix]
(custom-color color suffix nil))
([color suffix opacity]
(let [hex? (not (keyword? color))
resolved-color (cond hex? color
(hex-string? (get colors-map color)) (get colors-map color)
:else (get-in colors-map
[color suffix]))]
(let [resolved-color (cond
(not (keyword? color))
color
(hex-string? (get colors-map color))
(get colors-map color fallback-color)
:else
(get-in colors-map [color suffix] (get fallback-color suffix)))]
(if opacity
(alpha resolved-color (/ opacity 100))
resolved-color))))))

View File

@ -4,11 +4,37 @@
[oops.core :as oops]
[react-native.core :as rn]))
(defn- add-keyboard-listener
[listener callback]
(oops/ocall rn/keyboard "addListener" listener callback))
(defn use-keyboard
[]
(let [kb (.useKeyboard hooks)]
{:keyboard-shown (.-keyboardShown ^js kb)
:keyboard-height (.-keyboardHeight ^js kb)}))
(let [[keyboard-height set-keyboard-height] (rn/use-state 0)
[did-show? set-did-show] (rn/use-state false)
[will-show? set-will-show] (rn/use-state false)]
(rn/use-mount
(fn []
(let [will-show-listener (add-keyboard-listener "keyboardWillShow" #(set-will-show true))
did-show-listener (add-keyboard-listener "keyboardDidShow"
(fn [e]
(set-did-show true)
(set-keyboard-height
(oops/oget e "endCoordinates.height"))))
will-hide-listener (add-keyboard-listener "keyboardWillHide" #(set-will-show false))
did-hide-listener (add-keyboard-listener "keyboardDidHide"
(fn [e]
(set-did-show false)
(when e
(oops/oget e "endCoordinates.height"))))]
(fn []
(oops/ocall will-show-listener "remove")
(oops/ocall did-show-listener "remove")
(oops/ocall will-hide-listener "remove")
(oops/ocall did-hide-listener "remove")))))
{:keyboard-shown did-show?
:keyboard-will-show? will-show?
:keyboard-height keyboard-height}))
(defn use-back-handler
[handler]

View File

@ -1,6 +1,39 @@
(ns react-native.linear-gradient
(:require
["react-native-linear-gradient" :default LinearGradient]
[reagent.core :as reagent]))
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[taoensso.timbre :as log]))
(def linear-gradient (reagent/adapt-react-class LinearGradient))
(def ^:private linear-gradient* (reagent/adapt-react-class LinearGradient))
(defn- split-valid-colors
[acc idx color]
(let [color? (colors/valid-color? color)]
(cond-> acc
:always (update :safe-colors conj (if color? color "transparent"))
(not color?) (update :wrong-colors conj [idx color]))))
(defn- wrong-colors-str
[colors]
(reduce-kv (fn [s idx color]
(str s "Index: " idx ", color: " (prn-str color)))
"Invalid color values in vector passed to Linear Gradient:\n"
colors))
(defn linear-gradient
[props & children]
(when ^boolean js/goog.DEBUG
(assert (vector? (:colors props))))
(let [{:keys [wrong-colors safe-colors]} (rn/use-memo
(fn []
(reduce-kv split-valid-colors
{:safe-colors []
:wrong-colors {}}
(:colors props)))
[(:colors props)])]
(when (seq wrong-colors)
(log/error (wrong-colors-str wrong-colors)))
(into [linear-gradient* (assoc props :colors safe-colors)]
children)))

View File

@ -0,0 +1,8 @@
(ns react-native.net-info
(:require
["@react-native-community/netinfo" :default net-info]))
(defn add-net-info-listener
[callback]
(when net-info
(.addEventListener ^js net-info callback)))

View File

@ -23,7 +23,7 @@
(oops/ocall wc-utils
"buildApprovedNamespaces"
(bean/->js {:proposal proposal
:supportedNamespaces supported-namespaces})))
:supportedNamespaces (clj->js supported-namespaces)})))
;; Get an error from this list:
;; https://github.com/WalletConnect/walletconnect-monorepo/blob/c6e9529418a0c81d4efcc6ac4e61f242a50b56c5/packages/utils/src/errors.ts

View File

@ -0,0 +1,24 @@
(ns status-im.common.data-confirmation-sheet.style
(:require [quo.foundations.colors :as colors]))
(def heading
{:padding-left 20
:padding-bottom 8})
(def message
{:padding-horizontal 20
:padding-top 4})
(def warning
{:margin-horizontal 20
:margin-top 10})
(def drawer-container
{:padding-horizontal 13
:padding-top 16})
(def settings-subtext
{:color colors/white-opa-70
:align-self :center
:margin-bottom 12})

View File

@ -0,0 +1,73 @@
(ns status-im.common.data-confirmation-sheet.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.data-confirmation-sheet.style :as style]
[utils.i18n :as i18n]
[utils.navigation :as navigation]
[utils.re-frame :as rf]))
(defn on-choice-callback
[syncing-on-mobile-network?]
(rf/dispatch [:network/set-syncing-on-mobile-network syncing-on-mobile-network?])
(navigation/hide-bottom-sheet))
(def on-wifi-only (partial on-choice-callback false))
(def on-mobile-and-wifi (partial on-choice-callback true))
(defn view
[]
(let [settings-drawer? (= (rf/sub [:view-id]) :screen/settings.syncing)
syncing-on-mobile-network? (rf/sub [:profile/syncing-on-mobile-network?])]
(rn/use-mount navigation/dismiss-keyboard)
[:<>
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :data-confirmation-sheet-heading
:style style/heading}
(i18n/label (if settings-drawer? :t/sync-and-backup :t/which-connection-to-use))]
[quo/text
{:weight :regular
:size :paragraph-1
:accessibility-label :data-confirmation-sheet-message
:style style/message}
(i18n/label :t/syncing-connection-message)]
[quo/information-box
{:type :default
:icon :i/info
:blur? true
:style style/warning}
(i18n/label :t/syncing-wifi-connection-warning)]
(if settings-drawer?
[rn/view {:style style/drawer-container}
[quo/drawer-action
{:title (i18n/label :t/mobile-data-and-wifi)
:state (when syncing-on-mobile-network? :selected)
:blur? true
:accessibility-label :mobile-data-and-wifi-action
:icon :i/connection
:on-press on-mobile-and-wifi}]
[quo/drawer-action
{:title (i18n/label :t/wifi-only)
:state (when-not syncing-on-mobile-network? :selected)
:blur? true
:accessibility-label :wifi-only-action
:icon :i/placeholder
:on-press on-wifi-only}]]
[quo/bottom-actions
{:actions :two-actions
:blur? true
:container-style {:margin-top 12}
:button-one-label (i18n/label :t/wifi-only)
:button-one-props {:type :grey
:on-press on-wifi-only}
:button-two-label (i18n/label :t/mobile-and-wifi)
:button-two-props {:on-press on-mobile-and-wifi}}])
(if settings-drawer?
[quo/divider-line {:container-style {:padding-vertical 8}}]
[quo/text
{:weight :regular
:size :paragraph-2
:style style/settings-subtext}
(i18n/label :t/you-can-change-later-in-settings)])]))

View File

@ -3,21 +3,23 @@
[react-native.safe-area :as safe-area]))
(defn content-container
[blur? keyboard-shown?]
[blur? keyboard-shown? {:keys [padding-vertical padding-horizontal]}]
(let [margin-bottom (if keyboard-shown? 0 (safe-area/get-bottom))]
(cond-> {:margin-top :auto
:overflow :hidden
:margin-bottom margin-bottom
:padding-vertical 12
:padding-horizontal 20}
:padding-vertical (or padding-vertical 12)
:padding-horizontal (or padding-horizontal 20)}
blur? (dissoc :padding-vertical :padding-horizontal))))
(defn blur-inner-container
[theme shell-overlay?]
{:background-color (colors/theme-colors colors/white-70-blur
(if shell-overlay?
colors/neutral-80-opa-80-blur
colors/neutral-95-opa-70-blur)
theme)
:padding-vertical 12
:padding-horizontal 20})
[{:keys [theme shell-overlay? padding-vertical padding-horizontal background-color]}]
{:background-color (or background-color
(colors/theme-colors
colors/white-70-blur
(if shell-overlay?
colors/neutral-80-opa-80-blur
colors/neutral-95-opa-70-blur)
theme))
:padding-vertical (or padding-vertical 12)
:padding-horizontal (or padding-horizontal 20)})

View File

@ -6,20 +6,25 @@
[status-im.common.floating-button-page.floating-container.style :as style]))
(defn- blur-container
[child shell-overlay?]
[shell-overlay? blur-options child]
(let [theme (quo.theme/use-theme)]
[quo/blur
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent}
[rn/view {:style (style/blur-inner-container theme shell-overlay?)}
(or blur-options
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent})
[rn/view
{:style (style/blur-inner-container (assoc
blur-options
:theme theme
:shell-overlay? shell-overlay?))}
child]]))
(defn view
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
[{:keys [on-layout keyboard-shown? blur? shell-overlay? blur-options]} child]
[rn/view
{:style (style/content-container blur? keyboard-shown?)
{:style (style/content-container blur? keyboard-shown? blur-options)
:on-layout on-layout}
(if blur?
[blur-container child shell-overlay?]
[blur-container shell-overlay? blur-options child]
child)])

View File

@ -13,3 +13,13 @@
:bottom 0
:left 0
:right 0})
(defn content-keyboard-avoiding-view
[{:keys [top bottom]}]
{:position :absolute
:top top
:left 0
:right 0
:bottom bottom})
(def scroll-view-container {:flex 1})

View File

@ -30,13 +30,15 @@
(reset! ratom height))))
(defn- init-keyboard-listeners
[{:keys [on-did-show scroll-view-ref]}]
[{:keys [on-did-show on-will-show scroll-view-ref]}]
(let [keyboard-will-show? (reagent/atom false)
keyboard-did-show? (reagent/atom false)
add-listener (fn [listener callback]
(oops/ocall rn/keyboard "addListener" listener callback))
will-show-listener (add-listener "keyboardWillShow"
#(reset! keyboard-will-show? true))
(fn [e]
(reset! keyboard-will-show? true)
(when on-will-show (on-will-show e))))
did-show-listener (add-listener "keyboardDidShow"
(fn [e]
(reset! keyboard-did-show? true)
@ -58,7 +60,8 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?
blur-options content-avoid-keyboard?]
:or {footer-container-padding (safe-area/get-top)}}
& children]
(reagent/with-let [scroll-view-ref (atom nil)
@ -69,29 +72,34 @@
content-container-height (reagent/atom 0)
content-scroll-y (reagent/atom 0)
keyboard-height (reagent/atom 0)
reset-keyboard-height #(reset! keyboard-height (oops/oget
%
"endCoordinates.height"))
{:keys [keyboard-will-show?
keyboard-did-show?
remove-listeners]} (init-keyboard-listeners
{:scroll-view-ref scroll-view-ref
:on-did-show
(fn [e]
(reset! keyboard-height
(oops/oget e "endCoordinates.height")))})
(cond-> {:scroll-view-ref scroll-view-ref}
platform/ios?
(assoc :on-will-show reset-keyboard-height)
(not platform/ios?)
(assoc :on-did-show reset-keyboard-height)))
set-header-height (set-height-on-layout header-height)
set-content-container-height (set-height-on-layout content-container-height)
set-footer-container-height (set-height-on-layout footer-container-height)
set-content-y-scroll (fn [event]
(reset! content-scroll-y
(oops/oget event "nativeEvent.contentOffset.y")))]
(oops/oget event "nativeEvent.contentOffset.y")))
bottom-safe-area (safe-area/get-bottom)]
(let [keyboard-shown? (if platform/ios? @keyboard-will-show? @keyboard-did-show?)
footer-container-padding (+ footer-container-padding (rf/sub [:alert-banners/top-margin]))
show-background? (show-background {:window-height window-height
:footer-container-height @footer-container-height
:keyboard-height @keyboard-height
:content-scroll-y @content-scroll-y
:content-container-height @content-container-height
:header-height @header-height
:keyboard-shown? keyboard-shown?})]
show-background? (show-background
{:window-height window-height
:footer-container-height @footer-container-height
:keyboard-height @keyboard-height
:content-scroll-y @content-scroll-y
:content-container-height @content-container-height
:header-height @header-height
:keyboard-shown? keyboard-shown?})]
[:<>
(when gradient-cover?
[quo/gradient-cover {:customization-color customization-color}])
@ -100,20 +108,28 @@
{:on-layout set-header-height
:style header-container-style}
header]
[gesture/scroll-view
{:ref set-scroll-ref
:on-scroll set-content-y-scroll
:scroll-event-throttle 64
:content-container-style {:flex-grow 1
:padding-bottom (when @keyboard-did-show?
@footer-container-height)}
:always-bounce-vertical @keyboard-did-show?
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps keyboard-should-persist-taps}
(into [rn/view
{:style content-container-style
:on-layout set-content-container-height}]
children)]
[(if content-avoid-keyboard? rn/keyboard-avoiding-view rn/view)
{:style
(if content-avoid-keyboard?
(style/content-keyboard-avoiding-view
{:top @header-height
:bottom (if keyboard-shown?
@footer-container-height
(+ bottom-safe-area @footer-container-height))})
style/scroll-view-container)}
[gesture/scroll-view
{:ref set-scroll-ref
:on-scroll set-content-y-scroll
:scroll-event-throttle 64
:content-container-style {:flex-grow 1}
:always-bounce-vertical @keyboard-did-show?
:automatically-adjust-keyboard-insets true
:shows-vertical-scroll-indicator false
:keyboard-should-persist-taps keyboard-should-persist-taps}
(into [rn/view
{:style content-container-style
:on-layout set-content-container-height}]
children)]]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view
:keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
@ -121,8 +137,9 @@
[floating-container/view
{:on-layout set-footer-container-height
:keyboard-shown? keyboard-shown?
:blur? show-background?
:shell-overlay? shell-overlay?}
:blur-options blur-options
:shell-overlay? shell-overlay?
:blur? show-background?}
footer]]]])
(finally
(remove-listeners))))

View File

@ -55,7 +55,7 @@
{:dispatch (if user-in-sign-in-intro-screen?
[:navigate-to-within-stack
[:screen/onboarding.syncing-progress-intro :screen/onboarding.sign-in-intro]]
[:navigate-to :screen/onboarding.syncing-progress])}
[:open-modal :screen/onboarding.syncing-progress])}
(and completed-pairing? sender?)
{:dispatch [:syncing/clear-states]}

View File

@ -1,14 +1,14 @@
(ns status-im.common.raw-data-block.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[status-im.common.raw-data-block.style :as style]))
(defn view
[data]
[rn/scroll-view
{:style style/container
:content-container-style style/content}
[gesture/scroll-view
{:style style/container}
[quo/text
{:size :paragraph-2
:style style/content
:weight :code}
data]])

View File

@ -27,7 +27,9 @@
:welcome-illustration (js/require "../resources/images/ui2/welcome_illustration.png")
:notifications (js/require "../resources/images/ui2/notifications.png")
:nfc-prompt (js/require "../resources/images/ui2/nfc-prompt.png")
:nfc-success (js/require "../resources/images/ui2/nfc-success.png")})
:nfc-success (js/require "../resources/images/ui2/nfc-success.png")
:syncing-devices (js/require "../resources/images/ui2/syncing_devices.png")
:syncing-wrong (js/require "../resources/images/ui2/syncing_wrong.png")})
(def ui-themed
{:angry-man

View File

@ -1,7 +1,6 @@
(ns status-im.common.signals.events
(:require
[legacy.status-im.chat.models.message :as models.message]
[legacy.status-im.mailserver.core :as mailserver]
[legacy.status-im.visibility-status-updates.core :as visibility-status-updates]
[oops.core :as oops]
[status-im.common.pairing.events :as pairing]
@ -38,6 +37,15 @@
"wallet"
{:fx [[:dispatch [:wallet/signal-received event-js]]]}
"wallet.sign.transactions"
{:fx [[:dispatch
[:standard-auth/authorize-with-keycard
{:on-complete #(rf/dispatch [:keycard/sign-hash %
(first (transforms/js->clj event-js))])}]]]}
"wallet.suggested.routes"
{:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}
"envelope.sent"
(messages.transport/update-envelopes-status
cofx
@ -57,15 +65,6 @@
"messages.new"
(messages.transport/sanitize-messages-and-process-response cofx event-js true)
"mailserver.changed"
(mailserver/handle-mailserver-changed cofx (oops/oget event-js :id))
"mailserver.available"
(mailserver/handle-mailserver-available cofx (oops/oget event-js :id))
"mailserver.not.working"
(mailserver/handle-mailserver-not-working cofx)
"discovery.summary"
(summary cofx (transforms/js->clj event-js))

View File

@ -3,21 +3,35 @@
[schema.core :as schema]
[status-im.common.standard-authentication.enter-password.view :as enter-password]
[status-im.common.standard-authentication.events-schema :as events-schema]
[status-im.contexts.keycard.pin.view :as keycard.pin]
[taoensso.timbre :as log]
[utils.address]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
[utils.security.core :as security]))
(rf/reg-fx :effects.keycard/call-on-auth-success
(fn [on-auth-success]
(when on-auth-success (on-auth-success ""))))
(defn authorize
[{:keys [db]} [args]]
[{:keys [db]} [{:keys [on-auth-success keycard-supported?] :as args}]]
(let [key-uid (get-in db [:profile/profile :key-uid])
keycard? (get-in db [:profile/profile :keycard-pairing])]
{:fx [[:effects.biometric/check-if-available
{:key-uid key-uid
:on-success #(rf/dispatch [:standard-auth/authorize-with-biometric args])
:on-fail (if keycard?
#(rf/dispatch [:standard-auth/authorize-with-keycard args])
#(rf/dispatch [:standard-auth/authorize-with-password args]))}]]}))
{:fx
[(if keycard?
(if keycard-supported?
[:effects.keycard/call-on-auth-success on-auth-success]
[:effects.utils/show-popup
{:title "This feature is not supported yet "
:content
"Keycard support is limited to logging in
and signing the sending transaction.
Use Status Desktop to access all functions."}])
[:effects.biometric/check-if-available
{:key-uid key-uid
:on-success #(rf/dispatch [:standard-auth/authorize-with-biometric args])
:on-fail #(rf/dispatch [:standard-auth/authorize-with-password args])}])]}))
(schema/=> authorize events-schema/?authorize)
(rf/reg-event-fx :standard-auth/authorize authorize)
@ -94,6 +108,16 @@
:button-icon-left auth-button-icon-left
:button-label auth-button-label}])))
(defn authorize-with-keycard
[_ [{:keys [on-complete]}]]
{:fx [[:dispatch
[:show-bottom-sheet
{:hide-on-background-press? false
:on-close #(rf/dispatch [:standard-auth/reset-login-password])
:content (fn []
[keycard.pin/auth {:on-complete on-complete}])}]]]})
(rf/reg-event-fx :standard-auth/authorize-with-keycard authorize-with-keycard)
(defn authorize-with-password
[_ [{:keys [on-close theme blur?] :as args}]]
{:fx [[:dispatch [:standard-auth/reset-login-password]]
@ -110,7 +134,9 @@
(rf/reg-event-fx
:standard-auth/reset-login-password
(fn [{:keys [db]}]
{:db (update db :profile/login dissoc :password :error)}))
{:db (-> db
(update :profile/login dissoc :password :error)
(update :keycard dissoc :pin))}))
(rf/reg-fx
:standard-auth/on-close

View File

@ -8,7 +8,7 @@
(defn view
[{:keys [track-text customization-color auth-button-label on-auth-success on-auth-fail
auth-button-icon-left size blur? container-style disabled? dependencies]
auth-button-icon-left size blur? container-style disabled? dependencies keycard-supported?]
:or {container-style {:flex 1}}}]
(let [theme (quo.theme/use-theme)
auth-method (rf/sub [:auth-method])
@ -21,6 +21,7 @@
:auth-button-icon-left auth-button-icon-left
:theme theme
:blur? blur?
:keycard-supported? keycard-supported?
:biometric-auth? biometric-auth?
:on-auth-success on-auth-success
:on-auth-fail on-auth-fail

View File

@ -125,6 +125,9 @@
(def fetch-messages-enabled? (enabled? (get-config :FETCH_MESSAGES_ENABLED "1")))
(def test-networks-enabled? (enabled? (get-config :TEST_NETWORKS_ENABLED "0")))
(def mobile-data-syncing-toggle-enabled?
(enabled? (get-config :MOBILE_DATA_SYNCING_TOGGLE_ENABLE "1")))
;; Alert banners are disabled for debug builds because alert banners overlay
;; interfere with react-native debug tools, such as inspector and Perf monitor
(def enable-alert-banner? (enabled? (get-config :ENABLE_ALERT_BANNER "0")))

View File

@ -291,6 +291,7 @@
(def ^:const wallet-connect-session-delete-event "session_delete")
(def ^:const wallet-connect-user-rejected-error-key "USER_REJECTED")
(def ^:const wallet-connect-user-disconnected-reason-key "USER_DISCONNECTED")
(def ^:const wallet-connect-user-rejected-chains-error-key "USER_REJECTED_CHAINS")
(def ^:const transaction-pending-type-wallet-connect-transfer "WalletConnectTransfer")
@ -553,11 +554,21 @@
(def ^:const send-type-erc-721-transfer 6)
(def ^:const send-type-erc-1155-transfer 7)
(def ^:const multi-transaction-type-send 0)
(def ^:const multi-transaction-type-approve 1)
(def ^:const multi-transaction-type-bridge 2)
(def ^:const multi-transaction-type-swap 3)
(def ^:const multi-transaction-type-unknown 255)
(def ^:const contract-function-signature-erc20-approve "approve(address,uint256)")
(def ^:const bridge-name-transfer "Transfer")
(def ^:const bridge-name-erc-721-transfer "ERC721Transfer")
(def ^:const bridge-name-erc-1155-transfer "ERC1155Transfer")
(def ^:const bridge-name-hop "Hop")
(def ^:const bridge-assets #{"ETH" "USDT" "USDC" "DAI"})
(def ^:const wallet-contract-type-uknown 0)
(def ^:const wallet-contract-type-erc-20 1)
(def ^:const wallet-contract-type-erc-721 2)

View File

@ -33,3 +33,7 @@
(def drawer-message-container
{:padding-top 4
:padding-bottom 4})
(def group-member-mention
{:flex-direction :row
:align-items :center})

View File

@ -126,14 +126,60 @@
:photo-path photo-path
:incoming? (not= public-key from)}]))
(defn group-member
[literal]
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity literal])
photo-path (rf/sub [:chats/photo-path literal])]
[rn/view {:style style/group-member-mention}
[quo/user-avatar
{:full-name primary-name
:profile-picture photo-path
:status-indicator? false
:size :xxxs
:ring? false}]
[quo/text
{:weight :semi-bold
:style {:margin-left 4}}
primary-name]]))
(defn resolve-group-system-message
[{:keys [children]}]
(reduce (fn [acc {:keys [type literal]}]
(if (= type "mention")
(conj acc [group-member literal])
(conj acc
[rn/view
[quo/text literal]])))
[:<>]
children))
(defn render-parsed-text
[content]
(reduce (fn [acc e]
(conj acc (resolve-group-system-message e)))
[quo/text]
(:parsed-text content)))
(defn group-system-message
[{:keys [chat-id timestamp-str content]} type]
(let [{:keys [customization-color]} (rf/sub [:contacts/contact-by-address chat-id])]
[quo/system-message
{:type type
:timestamp timestamp-str
:customization-color customization-color
:child (render-parsed-text content)}]))
(defn system-message-content
[{:keys [content-type quoted-message] :as message-data}]
(if quoted-message
[pin/pinned-message message-data]
(condp = content-type
constants/content-type-system-text
[system.text/text-content message-data]
[group-system-message message-data :group]
constants/content-type-system-pinned-message
[system.text/text-content message-data]

View File

@ -1,7 +1,5 @@
(ns status-im.contexts.chat.messenger.messages.link-preview.events
(:require [camel-snake-kebab.core :as csk]
[status-im.common.json-rpc.events :as json-rpc]
[taoensso.timbre :as log]
[utils.collection]
[utils.re-frame :as rf]))
@ -35,17 +33,6 @@
{:fx [[:dispatch
[:profile.settings/profile-update :link-preview-request-enabled (boolean enabled?)]]]}))
(rf/reg-event-fx :chat.ui/link-preview-whitelist-received
(fn [{:keys [db]} [whitelist]]
{:db (assoc db :link-previews-whitelist whitelist)}))
(rf/reg-fx :chat.ui/request-link-preview-whitelist
(fn []
(json-rpc/call {:method "wakuext_getLinkPreviewWhitelist"
:params []
:on-success [:chat.ui/link-preview-whitelist-received]
:on-error #(log/error "Failed to get link preview whitelist")})))
(rf/reg-event-fx :chat.ui/enable-link-previews
(fn [{{:profile/keys [profile]} :db} [site enabled?]]
(let [enabled-sites (if enabled?

View File

@ -103,11 +103,11 @@
(models.contact/process-js-contacts cofx response-js)
(seq communities)
(let [communities-clj (types/js->clj communities)]
(do
(js-delete response-js "communities")
(rf/merge cofx
(process-next response-js sync-handler)
(communities/handle-communities communities-clj)))
(communities/handle-communities communities)))
(seq bookmarks)
(let [bookmarks-clj (types/js->clj bookmarks)]

View File

@ -26,7 +26,7 @@
"0xD" {:address "0xD"
:operable? false
:position 3
:color :flamingo
:color :pink
:emoji "🦩"}})
(def permissioned-accounts

View File

@ -22,7 +22,7 @@
airdrop-account (rf/sub [:communities/airdrop-account id])
revealed-accounts (rf/sub [:communities/accounts-to-reveal id])
revealed-accounts-count (count revealed-accounts)
wallet-accounts-count (count (rf/sub [:wallet/operable-accounts-without-watched-accounts]))
wallet-accounts-count (count (rf/sub [:wallet/operable-accounts]))
addresses-shared-text (if (= revealed-accounts-count wallet-accounts-count)
(i18n/label :t/all-addresses)
(i18n/label-pluralize

View File

@ -57,19 +57,24 @@
:index index})
(defn- members
[items theme]
[rn/section-list
{:key-fn :public-key
:content-container-style {:padding-bottom 20}
:get-item-layout get-item-layout
:content-inset-adjustment-behavior :never
:sections items
:sticky-section-headers-enabled false
:render-section-header-fn contact-list/contacts-section-header
:render-section-footer-fn footer
:render-data {:theme theme}
:render-fn contact-item
:scroll-event-throttle 32}])
[community-id chat-id theme]
(let [online-members (rf/sub [:communities/chat-members-sorted community-id chat-id :online])
offline-members (rf/sub [:communities/chat-members-sorted community-id chat-id :offline])]
[rn/section-list
{:key-fn :public-key
:content-container-style {:padding-bottom 20}
:get-item-layout get-item-layout
:content-inset-adjustment-behavior :never
:sections [{:title (i18n/label :t/online)
:data online-members}
{:title (i18n/label :t/offline)
:data offline-members}]
:sticky-section-headers-enabled false
:render-section-header-fn contact-list/contacts-section-header
:render-section-footer-fn footer
:render-data {:theme theme}
:render-fn contact-item
:scroll-event-throttle 32}]))
(defn view
[]
@ -78,8 +83,6 @@
{:keys [description chat-name emoji muted chat-type color]
:as chat} (rf/sub [:chats/chat-by-id chat-id])
pins-count (rf/sub [:chats/pin-messages-count chat-id])
items (rf/sub [:communities/sorted-community-members-section-list
community-id chat-id])
theme (quo.theme/use-theme)]
(rn/use-mount (fn []
(rf/dispatch [:pin-message/load-pin-messages chat-id])))
@ -133,4 +136,4 @@
(if muted
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id chat-type muted)))}]}]]]
[members items theme]]))
[members community-id chat-id theme]]))

View File

@ -54,7 +54,7 @@
:as item}]
(let [user-selected? (rf/sub [:is-contact-selected? public-key])
{:keys [id]} (rf/sub [:get-screen-params])
community-members-keys (set (keys (rf/sub [:communities/community-members id])))
community-members-keys (set (rf/sub [:communities/community-members id]))
community-member? (boolean (community-members-keys public-key))
on-toggle (fn []
(when-not community-member?

View File

@ -2,7 +2,6 @@
(:require
[clojure.string :as string]
[legacy.status-im.data-store.communities :as data-store.communities]
[legacy.status-im.mailserver.core :as mailserver]
[schema.core :as schema]
[status-im.constants :as constants]
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
@ -39,17 +38,6 @@
(rf/reg-event-fx :communities/handle-community handle-community)
(schema/=> handle-community
[:=>
[:catn
[:cofx :schema.re-frame/cofx]
[:args
[:schema [:catn [:community-js map?]]]]]
[:maybe
[:map
[:db [:map [:communities map?]]]
[:fx vector?]]]])
(rf/defn handle-removed-chats
[{:keys [db]} chat-ids]
{:db (reduce (fn [db chat-id]
@ -84,10 +72,9 @@
(rf/defn handle-communities
{:events [:community/fetch-success]}
[{:keys [db]} communities]
{:fx
(->> communities
(map #(vector :dispatch [:communities/handle-community %])))})
[{:keys [db]} communities-js]
{:fx (map (fn [c] [:dispatch [:communities/handle-community c]])
communities-js)})
(rf/reg-event-fx :communities/request-to-join-result
(fn [{:keys [db]} [community-id request-id response-js]]
@ -136,21 +123,30 @@
{}
categories))}))
(rf/reg-event-fx :community/fetch-low-priority
(fn []
{:fx [[:json-rpc/call
[{:method "wakuext_checkAndDeletePendingRequestToJoinCommunity"
:params []
:js-response true
:on-success [:sanitize-messages-and-process-response]
:on-error #(log/info "failed to fetch communities" %)}
{:method "wakuext_collapsedCommunityCategories"
:params []
:on-success [:communities/fetched-collapsed-categories-success]
:on-error #(log/error "failed to fetch collapsed community categories" %)}]]]}))
(rf/reg-event-fx :community/fetch
(fn [_]
{:json-rpc/call [{:method "wakuext_serializedCommunities"
:params []
:on-success #(rf/dispatch [:community/fetch-success %])
:on-error #(log/error "failed to fetch communities" %)}
{:method "wakuext_checkAndDeletePendingRequestToJoinCommunity"
:params []
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
:on-error #(log/info "failed to fetch communities" %)}
{:method "wakuext_collapsedCommunityCategories"
:params []
:on-success #(rf/dispatch [:communities/fetched-collapsed-categories-success %])
:on-error #(log/error "failed to fetch collapsed community categories" %)}]}))
{:fx [[:json-rpc/call
[{:method "wakuext_serializedCommunities"
:params []
:on-success [:community/fetch-success]
:js-response true
:on-error #(log/error "failed to fetch communities" %)}]]
;; Dispatch a little after 1000ms because other higher-priority events
;; after login are being processed at the 1000ms mark.
[:dispatch-later [{:ms 1200 :dispatch [:community/fetch-low-priority]}]]]}))
(defn update-previous-permission-addresses
[{:keys [db]} [community-id]]
@ -291,8 +287,7 @@
(when-let [community (first communities)]
{:db (-> db
(assoc-in [:communities (:id community) :spectated] true))
:fx [[:dispatch [:communities/handle-community community]]
[:dispatch [::mailserver/request-messages]]]}))
:fx [[:dispatch [:communities/handle-community community]]]}))
(rf/reg-event-fx :chat.ui/spectate-community-success spectate-community-success)

View File

@ -1,6 +1,5 @@
(ns status-im.contexts.communities.events-test
(:require [cljs.test :refer [deftest is testing]]
[legacy.status-im.mailserver.core :as mailserver]
matcher-combinators.test
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
[status-im.contexts.communities.events :as events]))
@ -112,7 +111,7 @@
(testing "dispatch fxs for first community"
(is (match?
{:fx [[:dispatch [:communities/handle-community {:id community-id}]]
[:dispatch [::mailserver/request-messages]]]}
]}
(events/spectate-community-success {} [{:communities [{:id community-id}]}])))))
(testing "given empty community"
(testing "do nothing"
@ -151,7 +150,7 @@
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
(deftest handle-community-test
(let [community {:id community-id :clock 2}]
(let [community #js {:id community-id :clock 2}]
(testing "given a unjoined community"
(let [effects (events/handle-community {} [community])]
(is (match? community-id
@ -163,7 +162,7 @@
(filter some? (:fx effects))))))
(testing "given a joined community"
(let [community (assoc community :joined true)
(let [community #js {:id community-id :clock 2 :joined true}
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch
@ -172,16 +171,19 @@
(filter some? (:fx effects))))))
(testing "given a community with token-permissions-check"
(let [community (assoc community :token-permissions-check :fake-token-permissions-check)
(let [community #js
{:id community-id :clock 2 :token-permissions-check :fake-token-permissions-check}
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch
[:communities/check-permissions-to-join-community-with-all-addresses community-id]]]
(filter some? (:fx effects))))))
(testing "given a community with lower clock"
(let [effects (events/handle-community {:db {:communities {community-id {:clock 3}}}} [community])]
(is (nil? effects))))
(testing "given a community without clock"
(let [community (dissoc community :clock)
(let [community #js {:id community-id}
effects (events/handle-community {} [community])]
(is (nil? effects))))))

View File

@ -75,46 +75,51 @@
:banner (resources/get-image :discover)
:accessibility-label :communities-home-discover-card}})
(defn on-tab-change
[tab]
(rf/dispatch [:communities/select-tab tab]))
(defn view
[]
(let [flat-list-ref (atom nil)
set-flat-list-ref #(reset! flat-list-ref %)]
(fn []
(let [theme (quo.theme/use-theme)
customization-color (rf/sub [:profile/customization-color])
selected-tab (or (rf/sub [:communities/selected-tab]) :joined)
{:keys [joined pending opened]} (rf/sub [:communities/grouped-by-status])
selected-items (case selected-tab
:joined joined
:pending pending
:opened opened)
scroll-shared-value (reanimated/use-shared-value 0)]
[:<>
(if (empty? selected-items)
[common.empty-state/view
{:selected-tab selected-tab
:tab->content (empty-state-content theme)}]
[reanimated/flat-list
{:ref set-flat-list-ref
:key-fn :id
:content-inset-adjustment-behavior :never
:header [common.header-spacing/view]
:render-fn item-render
:style {:margin-top -1}
:data selected-items
:scroll-event-throttle 8
:content-container-style {:padding-bottom
jump-to.constants/floating-shell-button-height}
:on-scroll #(common.banner/set-scroll-shared-value
{:scroll-input (oops/oget
%
"nativeEvent.contentOffset.y")
:shared-value scroll-shared-value})}])
[:f> common.banner/animated-banner
{:content banner-data
:customization-color customization-color
:scroll-ref flat-list-ref
:tabs tabs-data
:selected-tab selected-tab
:on-tab-change (fn [tab] (rf/dispatch [:communities/select-tab tab]))
:scroll-shared-value scroll-shared-value}]]))))
(let [flat-list-ref (rn/use-ref-atom nil)
set-flat-list-ref (rn/use-callback #(reset! flat-list-ref %))
theme (quo.theme/use-theme)
customization-color (rf/sub [:profile/customization-color])
selected-tab (or (rf/sub [:communities/selected-tab]) :joined)
{:keys [joined pending opened]} (rf/sub [:communities/grouped-by-status])
selected-items (case selected-tab
:joined joined
:pending pending
:opened opened)
scroll-shared-value (reanimated/use-shared-value 0)
on-scroll (rn/use-callback
(fn [event]
(common.banner/set-scroll-shared-value
{:scroll-input (oops/oget event
"nativeEvent.contentOffset.y")
:shared-value scroll-shared-value})))]
[:<>
(if (empty? selected-items)
[common.empty-state/view
{:selected-tab selected-tab
:tab->content (empty-state-content theme)}]
[reanimated/flat-list
{:ref set-flat-list-ref
:key-fn :id
:content-inset-adjustment-behavior :never
:header [common.header-spacing/view]
:render-fn item-render
:style {:margin-top -1}
:data selected-items
:scroll-event-throttle 8
:content-container-style {:padding-bottom
jump-to.constants/floating-shell-button-height}
:on-scroll on-scroll}])
[common.banner/animated-banner
{:content banner-data
:customization-color customization-color
:scroll-ref flat-list-ref
:tabs tabs-data
:selected-tab selected-tab
:on-tab-change on-tab-change
:scroll-shared-value scroll-shared-value}]]))

View File

@ -109,3 +109,22 @@
[pairings]
(keycard/set-pairings pairings))
(rf/reg-fx :effects.keycard/set-pairing-to-keycard set-pairing-to-keycard)
(defn sign
[{:keys [on-success on-failure] :as args}]
(log/debug "[keycard] sign")
(keycard/sign
(assoc
args
:on-success
(fn [response]
(log/debug "[keycard response succ] sign")
(when on-success
(on-success (transforms/js->clj response))))
:on-failure
(fn [response]
(log/warn "[keycard response fail] sign"
(error-object->map response))
(when on-failure
(on-failure (error-object->map response)))))))
(rf/reg-fx :effects.keycard/sign sign)

View File

@ -3,6 +3,8 @@
status-im.contexts.keycard.login.events
status-im.contexts.keycard.pin.events
status-im.contexts.keycard.sheet.events
status-im.contexts.keycard.sign.events
[status-im.contexts.keycard.utils :as keycard.utils]
[taoensso.timbre :as log]))
(rf/reg-event-fx :keycard/on-check-nfc-enabled-success
@ -55,3 +57,19 @@
(fn [{:keys [db]} [{:keys [on-cancel-event-vector]}]]
(log/debug "[keycard] nfc started success")
{:db (assoc-in db [:keycard :on-nfc-cancelled-event-vector] on-cancel-event-vector)}))
(rf/reg-event-fx :keycard/on-action-with-pin-error
(fn [{:keys [db]} [error]]
(log/debug "[keycard] get keys error: " error)
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
pin-retries-count (keycard.utils/pin-retries (:error error))]
(if tag-was-lost?
{:db (assoc-in db [:keycard :pin :status] nil)}
(if (nil? pin-retries-count)
{:effects.utils/show-popup {:title "wrong-keycard"}}
{:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(update-in [:keycard :pin] assoc :status :error))
:fx [[:dispatch [:keycard/hide-connection-sheet]]
(when (zero? pin-retries-count)
[:effects.utils/show-popup {:title "frozen-keycard"}])]})))))

View File

@ -3,22 +3,6 @@
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/reg-event-fx :keycard.login/on-get-keys-error
(fn [{:keys [db]} [error]]
(log/debug "[keycard] get keys error: " error)
(let [tag-was-lost? (keycard.utils/tag-lost? (:error error))
pin-retries-count (keycard.utils/pin-retries (:error error))]
(if tag-was-lost?
{:db (assoc-in db [:keycard :pin :status] nil)}
(if (nil? pin-retries-count)
{:effects.utils/show-popup {:title "wrong-keycard"}}
{:db (-> db
(assoc-in [:keycard :application-info :pin-retry-counter] pin-retries-count)
(update-in [:keycard :pin] assoc :status :error))
:fx [[:dispatch [:keycard/hide-connection-sheet]]
(when (zero? pin-retries-count)
[:effects.utils/show-popup {:title "frozen-keycard"}])]})))))
(rf/reg-event-fx :keycard.login/on-get-keys-success
(fn [{:keys [db]} [data]]
(let [{:keys [key-uid encryption-public-key
@ -56,28 +40,25 @@
:key-uid key-uid}]]}))))
(rf/reg-event-fx :keycard.login/on-get-application-info-success
(fn [{:keys [db]} [application-info]]
(let [profile (get-in db [:profile/profiles-overview (get-in db [:profile/login :key-uid])])
pin (get-in db [:keycard :pin :text])
error (keycard.utils/validate-application-info profile application-info)]
(fn [{:keys [db]} [application-info {:keys [key-uid on-read-fx]}]]
(let [error (keycard.utils/validate-application-info key-uid application-info)]
(if error
{:effects.utils/show-popup {:title (str error)}}
{:db (-> db
(assoc-in [:keycard :application-info] application-info)
(assoc-in [:keycard :pin :status] :verifying))
:effects.keycard/get-keys {:pin pin
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
:on-failure #(rf/dispatch [:keycard.login/on-get-keys-error %])}}))))
{:db (-> db
(assoc-in [:keycard :application-info] application-info)
(assoc-in [:keycard :pin :status] :verifying))
:fx on-read-fx}))))
(rf/reg-event-fx :keycard.login/cancel-reading-card
(fn [{:keys [db]}]
{:db (assoc-in db [:keycard :on-card-connected-event-vector] nil)}))
(rf/reg-event-fx :keycard/read-card-and-login
(fn [{:keys [db]}]
(rf/reg-event-fx :keycard/read-card
(fn [{:keys [db]} [args]]
(let [connected? (get-in db [:keycard :card-connected?])
event-vector [:keycard/get-application-info
{:on-success #(rf/dispatch [:keycard.login/on-get-application-info-success %])}]]
{:on-success #(rf/dispatch [:keycard.login/on-get-application-info-success %
args])}]]
(log/debug "[keycard] proceed-to-login")
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
:fx [[:dispatch

View File

@ -9,13 +9,17 @@
(assoc-in [:keycard :pin :text] (.slice pin 0 -1))
(assoc-in [:keycard :pin :status] nil))}))))
(rf/reg-fx :effects.keycard.pin/dispatch-on-complete
(fn [[on-complete new-pin]]
(on-complete new-pin)))
(rf/reg-event-fx :keycard.pin/number-pressed
(fn [{:keys [db]} [number max-numbers on-complete-event]]
(fn [{:keys [db]} [number max-numbers on-complete]]
(let [pin (get-in db [:keycard :pin :text])
new-pin (str pin number)]
(when (<= (count new-pin) max-numbers)
{:db (-> db
(assoc-in [:keycard :pin :text] new-pin)
(assoc-in [:keycard :pin :status] nil))
:fx [(when (= (dec max-numbers) (count pin))
[:dispatch [on-complete-event]])]}))))
:fx [(when (and on-complete (= (dec max-numbers) (count pin)))
[:effects.keycard.pin/dispatch-on-complete [on-complete new-pin]])]}))))

View File

@ -6,7 +6,7 @@
[utils.re-frame :as rf]))
(defn auth
[callback-event-key]
[{:keys [on-complete]}]
(let [{:keys [text status]} (rf/sub [:keycard/pin])
pin-retry-counter (rf/sub [:keycard/pin-retry-counter])
error? (= status :error)]
@ -23,4 +23,4 @@
{:delete-key? true
:on-delete #(rf/dispatch [:keycard.pin/delete-pressed])
:on-press #(rf/dispatch [:keycard.pin/number-pressed % constants/pincode-length
callback-event-key])}]]))
on-complete])}]]))

View File

@ -0,0 +1,29 @@
(ns status-im.contexts.keycard.sign.events
(:require [utils.address]
[utils.re-frame :as rf]))
(defn get-signature-map
[tx-hash signature]
{tx-hash {:r (subs signature 0 64)
:s (subs signature 64 128)
:v (str (js/parseInt (subs signature 128 130) 16))}})
(rf/reg-event-fx :keycard/sign-hash
(fn [{:keys [db]} [pin-text tx-hash]]
(let [current-address (get-in db [:wallet :current-viewing-account-address])
path (get-in db [:wallet :accounts current-address :path])
key-uid (get-in db [:profile/profile :key-uid])]
{:fx [[:dispatch
[:keycard/read-card
{:key-uid key-uid
:on-read-fx [[:effects.keycard/sign
{:pin pin-text
:path path
:hash (utils.address/naked-address tx-hash)
:on-success
#(do
(rf/dispatch [:keycard/hide-connection-sheet])
(rf/dispatch
[:wallet/proceed-with-transactions-signatures
(get-signature-map tx-hash %)]))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}]]]})))

View File

@ -16,8 +16,8 @@
(re-matches #".*NFCError:100.*" error)))
(defn validate-application-info
[profile {:keys [key-uid paired? pin-retry-counter puk-retry-counter] :as application-info}]
(let [profile-mismatch? (or (nil? profile) (not= (:key-uid profile) key-uid))]
[profile-key-uid {:keys [key-uid paired? pin-retry-counter puk-retry-counter] :as application-info}]
(let [profile-mismatch? (or (nil? profile-key-uid) (not= profile-key-uid key-uid))]
(log/debug "[keycard] login-with-keycard"
"empty application info" (empty? application-info)
"no key-uid" (empty? key-uid)

View File

@ -0,0 +1,17 @@
(ns status-im.contexts.network.effects
(:require
[native-module.core :as native-module]
[react-native.net-info :as net-info]
[utils.re-frame :as rf]))
(rf/reg-fx
:effects.network/listen-to-network-info
(fn []
(net-info/add-net-info-listener
#(rf/dispatch [:network/on-state-change
(js->clj % :keywordize-keys true)]))))
(rf/reg-fx
:effects.network/notify-status-go
(fn [network-type expensive?]
(native-module/connection-change network-type expensive?)))

View File

@ -0,0 +1,76 @@
(ns status-im.contexts.network.events
(:require
[status-im.common.data-confirmation-sheet.view :as data-confirmation-sheet]
[status-im.config :as config]
[status-im.feature-flags :as ff]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(rf/reg-event-fx :network/set-syncing-on-mobile-network
(fn [{:keys [db]} [syncing-on-mobile-network?]]
(when config/mobile-data-syncing-toggle-enabled?
{:db (update db
:profile/profile
assoc
:syncing-on-mobile-network?
syncing-on-mobile-network?
:remember-syncing-choice?
true)
:fx [[:json-rpc/call
[{:method "wakuext_setSyncingOnMobileNetwork"
:params [{:enabled syncing-on-mobile-network?}]
:on-success #(log/debug "successfully set syncing-on-mobile-network"
syncing-on-mobile-network?)
:on-error #(log/error "could not set syncing-on-mobile-network" %)}]]]})))
(rf/reg-event-fx :network/check-expensive-connection
(fn [{:keys [db]}]
(when
(and (:network/expensive? db)
config/mobile-data-syncing-toggle-enabled?
(:profile/profile db)
(not (get-in db [:profile/profile :remember-syncing-choice?])))
;; Note here we are only updating :remember-syncing-choice? temporarily to avoid opening
;; multiple bottom sheets and the user might again see the sheet on the next login. Unless the
;; user makes a syncing choice that will persist this key in the status-go
{:db (assoc-in db [:profile/profile :remember-syncing-choice?] true)
:fx [[:dispatch
[:show-bottom-sheet
{:content (fn [] [data-confirmation-sheet/view])
:shell? true
:theme :dark}]]]})))
(rf/reg-event-fx
:network/on-state-change
(fn [{:keys [db]} [{:keys [isConnected type details]}]]
(let [old-network-status (:network/status db)
old-network-type (:network/type db)
connectivity-status (if isConnected :online :offline)
status-changed? (not= connectivity-status old-network-status)
type-changed? (not= type old-network-type)
expensive? (:isConnectionExpensive details)]
(log/debug "[net-info]"
"old-network-status" old-network-status
"old-network-type" old-network-type
"connectivity-status" connectivity-status
"type" type
"details" details)
{:db (assoc db :network/expensive? expensive?)
:fx [[:dispatch [:network/check-expensive-connection]]
(when status-changed?
[:dispatch [:network/on-network-status-change connectivity-status]])
(when type-changed?
[:dispatch [:network/on-network-type-change type expensive?]])]})))
(rf/reg-event-fx
:network/on-network-type-change
(fn [{:keys [db]} [network-type expensive?]]
{:db (assoc db :network/type network-type)
:fx [[:effects.network/notify-status-go network-type expensive?]]}))
(rf/reg-event-fx
:network/on-network-status-change
(fn [{:keys [db]} [connectivity-status]]
{:db (assoc db :network/status connectivity-status)
:fx [(when (ff/enabled? ::ff/wallet.wallet-connect)
[:dispatch [:wallet-connect/reload-on-network-change (= :online connectivity-status)]])]}))

View File

@ -2,8 +2,6 @@
(:require
[quo.foundations.colors :as colors]))
(def flex-fill {:flex 1})
(def heading {:margin-bottom 20})
(def heading-subtitle {:color colors/white})
(def heading-title (assoc heading-subtitle :margin-bottom 8))
@ -14,23 +12,15 @@
(def space-between-inputs {:height 16})
(def password-tips
{:flex-direction :row
:justify-content :space-between
:margin-horizontal 20})
{:flex-direction :row
:justify-content :space-between
:padding-horizontal 20})
(def top-part
{:margin-horizontal 20
:margin-top 12})
(def form-container
{:justify-content :space-between
:padding-top 12
:padding-horizontal 20})
(def bottom-part
{:flex 1
:margin-top 12
:justify-content :flex-end})
(def disclaimer-container
{:margin-horizontal 20
:margin-vertical 4})
(def button-container
{:margin-horizontal 20
:margin-vertical 12})
(def disclaimer-container {:padding-horizontal 20})
(def footer-container {:padding-bottom 12})
(def footer-button-container {:margin-top 20 :padding-horizontal 20})

View File

@ -1,11 +1,11 @@
(ns status-im.contexts.onboarding.create-password.view
(:require
[oops.core :refer [ocall]]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.floating-button-page.view :as floating-button]
[status-im.constants :as constants]
[status-im.contexts.onboarding.create-password.style :as style]
[utils.i18n :as i18n]
@ -94,7 +94,7 @@
[quo/tips {:completed? symbols?}
(i18n/label :t/password-creation-tips-4)]]])
(defn password-validations
(defn validate-password
[password]
(let [validations (juxt utils.string/has-lower-case?
utils.string/has-upper-case?
@ -111,68 +111,25 @@
(filter true?)
count))
(defn password-form
[]
(let [password (reagent/atom "")
repeat-password (reagent/atom "")
accepts-disclaimer? (reagent/atom false)
focused-input (reagent/atom nil)
show-password-validation? (reagent/atom false)
same-password-length? #(and (seq @password)
(= (count @password) (count @repeat-password)))]
(fn []
(let [{user-color :color} (rf/sub [:onboarding/profile])
{:keys [long-enough?]
:as validations} (password-validations @password)
password-strength (calc-password-strength validations)
empty-password? (empty? @password)
same-passwords? (and (not empty-password?) (= @password @repeat-password))
meet-requirements? (and (not empty-password?)
(utils.string/at-least-n-chars? @password 10)
same-passwords?
@accepts-disclaimer?)]
[:<>
[rn/view {:style style/top-part}
[header]
[password-inputs
{:password-long-enough? long-enough?
:passwords-match? same-passwords?
:empty-password? empty-password?
:show-password-validation? @show-password-validation?
:on-input-focus #(reset! focused-input :password)
:on-change-password (fn [new-value]
(reset! password new-value)
(when (same-password-length?)
(reset! show-password-validation? true)))
:on-change-repeat-password (fn [new-value]
(reset! repeat-password new-value)
(when (same-password-length?)
(reset! show-password-validation? true)))
:on-blur-repeat-password #(if empty-password?
(reset! show-password-validation? false)
(reset! show-password-validation? true))}]]
(defn- use-password-checks
[password]
(rn/use-memo
(fn []
(let [{:keys [long-enough?]
:as validations} (validate-password password)]
{:password-long-enough? long-enough?
:password-validations validations
:password-strength (calc-password-strength validations)
:empty-password? (empty? password)}))
[password]))
[rn/view {:style style/bottom-part}
(when same-passwords?
[rn/view {:style style/disclaimer-container}
[quo/disclaimer
{:blur? true
:on-change #(swap! accepts-disclaimer? not)
:checked? @accepts-disclaimer?}
(i18n/label :t/password-creation-disclaimer)]])
(when (and (= @focused-input :password) (not same-passwords?))
[help
{:validations validations
:password-strength password-strength}])
[rn/view {:style style/button-container}
[quo/button
{:disabled? (not meet-requirements?)
:customization-color user-color
:on-press #(rf/dispatch
[:onboarding/password-set
(security/mask-data @password)])}
(i18n/label :t/password-creation-confirm)]]]]))))
(defn- use-repeat-password-checks
[password repeat-password]
(rn/use-memo
(fn []
{:same-password-length? (and (seq password) (= (count password) (count repeat-password)))
:same-passwords? (and (seq password) (= password repeat-password))})
[password repeat-password]))
(defn create-password-doc
[]
@ -183,38 +140,108 @@
[quo/text {:size :paragraph-2}
(i18n/label :t/create-profile-password-info-box-description)]]])
(defn- on-press-info
[]
(rn/dismiss-keyboard!)
(rf/dispatch [:show-bottom-sheet
{:content create-password-doc
:shell? true}]))
(defn- navigate-back
[]
(rf/dispatch [:navigate-back]))
(defn- page-nav
[]
(let [{:keys [top]} (safe-area/get-insets)]
[quo/page-nav
{:margin-top top
:background :blur
:icon-name :i/arrow-left
:on-press navigate-back
:right-side [{:icon-name :i/info
:on-press on-press-info}]}]))
(defn create-password
[]
(reagent/with-let [keyboard-shown? (reagent/atom false)
{:keys [top bottom]} (safe-area/get-insets)
will-show-listener (ocall rn/keyboard
"addListener"
"keyboardWillShow"
#(reset! keyboard-shown? true))
will-hide-listener (ocall rn/keyboard
"addListener"
"keyboardWillHide"
#(reset! keyboard-shown? false))
on-press-info (fn []
(rn/dismiss-keyboard!)
(rf/dispatch [:show-bottom-sheet
{:content create-password-doc
:shell? true}]))]
[:<>
[rn/touchable-without-feedback
{:on-press rn/dismiss-keyboard!
:accessible false}
[rn/view {:style style/flex-fill}
[rn/keyboard-avoiding-view {:style style/flex-fill}
[quo/page-nav
{:margin-top top
:background :blur
:icon-name :i/arrow-left
:on-press #(rf/dispatch [:navigate-back])
:right-side [{:icon-name :i/info
:on-press on-press-info}]}]
[password-form]
[rn/view {:style {:height (if-not @keyboard-shown? bottom 0)}}]]]]]
(finally
(ocall will-show-listener "remove")
(ocall will-hide-listener "remove"))))
(let [[password set-password] (rn/use-state "")
[repeat-password set-repeat-password] (rn/use-state "")
[accepts-disclaimer? set-accepts-disclaimer?] (rn/use-state false)
[focused-input set-focused-input] (rn/use-state nil)
[show-password-validation?
set-show-password-validation?] (rn/use-state false)
{user-color :color} (rf/sub [:onboarding/profile])
{:keys [password-long-enough?
password-validations password-strength
empty-password?]} (use-password-checks password)
{:keys [same-password-length? same-passwords?]} (use-repeat-password-checks password
repeat-password)
meet-requirements? (rn/use-memo
#(and (not empty-password?)
(utils.string/at-least-n-chars? password
10)
same-passwords?
accepts-disclaimer?)
[password repeat-password
accepts-disclaimer?])]
[floating-button/view
{:header [page-nav]
:keyboard-should-persist-taps :handled
:content-avoid-keyboard? true
:blur-options
{:blur-amount 34
:blur-radius 20
:blur-type :transparent
:overlay-color :transparent
:background-color (if platform/android? colors/neutral-100 colors/neutral-80-opa-1-blur)
:padding-vertical 0
:padding-horizontal 0}
:footer-container-padding 0
:footer
[rn/view
{:style style/footer-container}
(when same-passwords?
[rn/view {:style style/disclaimer-container}
[quo/disclaimer
{:blur? true
:on-change (partial set-accepts-disclaimer? not)
:checked? accepts-disclaimer?}
(i18n/label :t/password-creation-disclaimer)]])
(when (and (= focused-input :password) (not same-passwords?))
[help
{:validations password-validations
:password-strength password-strength}])
[quo/button
{:container-style style/footer-button-container
:disabled? (not meet-requirements?)
:customization-color user-color
:on-press #(rf/dispatch
[:onboarding/password-set
(security/mask-data password)])}
(i18n/label :t/password-creation-confirm)]]}
[rn/view {:style style/form-container}
[header]
[password-inputs
{:password-long-enough? password-long-enough?
:passwords-match? same-passwords?
:empty-password? empty-password?
:show-password-validation? show-password-validation?
:on-input-focus #(set-focused-input :password)
:on-change-password (fn [new-value]
(set-password new-value)
(when same-password-length?
(set-show-password-validation? true)))
:on-change-repeat-password (fn [new-value]
(set-repeat-password new-value)
(when same-password-length?
(set-show-password-validation? true)))
:on-blur-repeat-password #(if empty-password?
(set-show-password-validation? false)
(set-show-password-validation? true))}]]]))

View File

@ -38,7 +38,7 @@
(rf/dispatch [:push-notifications/switch true])
(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.welcome
:screen/onboarding.generating-keys]]))
:screen/onboarding.enable-notifications]]))
:type :primary
:icon-left :i/notifications
:accessibility-label :enable-notifications-button
@ -52,7 +52,7 @@
nil)
(rf/dispatch [:navigate-to-within-stack
[:screen/onboarding.welcome
:screen/onboarding.generating-keys]]))
:screen/onboarding.enable-notifications]]))
:accessibility-label :enable-notifications-later-button
:type :grey
:background :blur

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