Compare commits

..
127 changed files with 1357 additions and 1866 deletions
+3 -1
View File
@@ -215,13 +215,15 @@ 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-arm64-v8a-release-unsigned.apk
@scripts/sign-android.sh result/app-release-unsigned.apk
release-ios: export TARGET := ios
release-ios: export IOS_STATUS_GO_TARGETS := ios/arm64
+1 -1
View File
@@ -211,7 +211,7 @@ android {
reset()
enable getEnvOrConfig('ANDROID_ABI_SPLIT').toBoolean()
include getEnvOrConfig('ANDROID_ABI_INCLUDE').split(";")
universalApk false
universalApk true
}
}
signingConfigs {
+4 -4
View File
@@ -38,10 +38,10 @@ KEYSTORE_PASSWORD=password
KEYSTORE_ALIAS=status
KEYSTORE_KEY_PASSWORD=password
# 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
# 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
org.gradle.jvmargs=-Xmx8704M -XX:+UseParallelGC
+6 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
@@ -72,7 +72,11 @@ pipeline {
stage('Upload') {
steps { script {
def urls = apks.collect { s5cmd.upload(it) }
env.PKG_URL = urls.first()
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()
}
jenkins.setBuildDesc(APK: env.PKG_URL)
} }
}
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
import groovy.json.JsonBuilder
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
/* Options section can't access functions in objects. */
def isPRBuild = utils.isPRBuild()
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label 'macos' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label params.AGENT_LABEL }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent { label 'linux' }
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env groovy
library 'status-jenkins-lib@v1.9.3'
library 'status-jenkins-lib@v1.9.1'
pipeline {
agent {
+2 -2
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" "true",
androidAbiSplit ? lib.getEnvWithDefault "ANDROID_ABI_SPLIT" "false",
# Android architectures to build for
# Used to detect end-to-end builds
androidAbiInclude ? lib.getEnvWithDefault "ANDROID_ABI_INCLUDE" "arm64-v8a",
androidAbiInclude ? lib.getEnvWithDefault "ANDROID_ABI_INCLUDE" "armeabi-v7a;arm64-v8a;x86",
}:
let
Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

+1 -1
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-arm64-v8a-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
adb install -r ./result/app-debug.apk > "${ADB_INSTALL_LOG_FILE}" 2>&1
"${GIT_ROOT}/scripts/wait-for-metro-port.sh" 2>&1
# connected android devices need this port to be exposed for metro
adb reverse "tcp:${RCT_METRO_PORT}" "tcp:${RCT_METRO_PORT}"
@@ -1,8 +1,8 @@
(ns legacy.status-im.data-store.communities
(:require
[clojure.set :as set]
[status-im.constants :as constants]
[utils.transforms :as transforms]))
[clojure.walk :as walk]
[status-im.constants :as constants]))
(defn <-revealed-accounts-rpc
[accounts]
@@ -22,26 +22,19 @@
(reduce #(assoc %1 (key-fn %2) (<-request-to-join-community-rpc %2)) {} requests))
(defn <-chats-rpc
"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}))})))
[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))
(defn <-categories-rpc
[categ]
@@ -55,59 +48,49 @@
[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-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))))))
[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)))))
@@ -13,18 +13,15 @@
(native-module/logout)))
(rf/defn initialize-app-db
[{{:keys [keycard initials-avatar-font-file biometrics]
:network/keys [type status]
:wallet-connect/keys [web3-wallet]}
[{{:keys [keycard initials-avatar-font-file biometrics]
:network/keys [type]}
:db}]
{:db (assoc db/app-db
:network/type type
:network/status status
:initials-avatar-font-file initials-avatar-font-file
:keycard (dissoc keycard :secrets :pin :application-info)
:biometrics biometrics
:syncing nil
:wallet-connect/web3-wallet web3-wallet)})
:network/type type
:initials-avatar-font-file initials-avatar-font-file
:keycard (dissoc keycard :secrets :pin :application-info)
:biometrics biometrics
:syncing nil)})
(rf/defn logout-method
{:events [::logout-method]}
+29 -1
View File
@@ -4,6 +4,7 @@
[re-frame.core :as re-frame]
[react-native.platform :as utils.platform]
[status-im.common.json-rpc.events :as json-rpc]
[status-im.common.new-device-sheet.view :as new-device-sheet]
[status-im.config :as config]
[status-im.navigation.events :as navigation]
[taoensso.timbre :as log]
@@ -220,6 +221,12 @@
:name (:name metadata)
:device-type (:deviceType metadata))})
(defn should-show-syncing-pop-up?
[db installations]
(and (:syncing/pairing-process-initiated? db)
(first (filter #(not (get-in db [:pairing/installations (:id %)])) installations))))
(rf/defn handle-installations
[{:keys [db]} installations]
{:db (update db
@@ -228,7 +235,10 @@
(fn [acc {:keys [id] :as i}]
(update acc id merge (installation<-rpc i)))
%
installations))})
installations))
:fx [(when-let [new-installation (should-show-syncing-pop-up? db installations)]
[:dispatch
[:show-bottom-sheet {:content (fn [] [new-device-sheet/view (:id new-installation)])}]])]})
(rf/defn load-installations
{:events [:pairing.callback/get-our-installations-success]}
@@ -243,6 +253,24 @@
{}
installations))})
(rf/defn finish-seed-phrase-fallback-syncing
{:events [:pairing/finish-seed-phrase-fallback-syncing]}
[{:keys [db]}]
{:fx [[:dispatch [:show-bottom-sheet {:content (fn [] [new-device-sheet/view-2])}]]
[:json-rpc/call
[{:method "wakuext_finishPairingThroughSeedPhraseProcess"
:params [{:installationId (:syncing/installation-id db)}]
:js-response true
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])}]]]})
(rf/defn pair-and-sync
{:events [:pairing/pair-and-sync]}
[cofx installation-id]
{:fx [[:json-rpc/call
[{:method "wakuext_enableAndSyncInstallation"
:params [{:installationId installation-id}]
:on-success #(log/debug "successfully synced devices")}]]]})
(rf/defn enable-installation-success
{:events [:pairing.callback/enable-installation-success]}
[cofx installation-id]
@@ -5,7 +5,6 @@
[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]))
@@ -21,6 +20,8 @@
light-client-enabled?
store-confirmations-enabled?
current-fleet
test-networks-enabled?
is-goerli-enabled?
peer-syncing-enabled?]}]
(keep
identity
@@ -60,14 +61,14 @@
:on-press
#(re-frame/dispatch [:open-modal :peers-stats])
:chevron true}
(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 "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
@@ -86,6 +87,22 @@
[: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
@@ -107,7 +124,9 @@
(views/defview advanced-settings
[]
(views/letsubs [light-client-enabled? [:profile/light-client-enabled?]
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
is-goerli-enabled? [:profile/is-goerli-enabled?]
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]
@@ -128,6 +147,8 @@
: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}]]))
@@ -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 sorted-members
{:data (keys sorted-members)
:render-data {:community-id community-id
:my-public-key my-public-key
:can-kick-users? (and can-manage-users?
+1 -3
View File
@@ -332,9 +332,7 @@
(defn set-blank-preview-flag
[flag]
(log/debug "[native-module] set-blank-preview-flag")
;; Sometimes the app crashes during logout because `flag` is nil.
(when flag
(.setBlankPreviewFlag ^js (encryption) flag)))
(.setBlankPreviewFlag ^js (encryption) flag))
(defn get-device-model-info
[]
@@ -65,8 +65,9 @@
:style (style/container loading? theme size)}
[loading-view theme]]
[linear-gradient/linear-gradient
{:style (style/container loading? theme size)
:colors (linear-gradient-props theme customization-color)}
(assoc {:style (style/container loading? theme size)}
:colors
(linear-gradient-props theme customization-color))
[rn/pressable
{:accessibility-label :internal-link-card
:on-press on-press}
@@ -32,7 +32,8 @@
(def system-message-base-wrapper
{:flex-direction :row
:flex 1})
:flex 1
:align-items :center})
(def system-message-base-content-wrapper
{:align-self :center
@@ -127,14 +127,6 @@
(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)]
@@ -191,7 +183,6 @@
: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
@@ -4,7 +4,7 @@
(defn main
[{:keys [type customization-color]} theme]
{:justify-content :flex-start
{:justify-content :center
:align-items :center
:height 32
:padding-left 4
@@ -16,7 +16,6 @@
(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
@@ -58,19 +58,16 @@
- :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 container-style]
[{:keys [label customization-color type]
:as props
:or {customization-color colors/neutral-80-opa-5}}]
(let [theme (quo.theme/use-theme)]
[rn/view
{:accessibility-label :container
:style (merge (style/main (assoc props :customization-color customization-color)
theme)
container-style)}
:style (style/main (assoc props :customization-color customization-color) theme)}
[left-view props]
[text/text
{:style (style/label type theme)
:weight :semi-bold
:number-of-lines 1
:size :heading-1}
{:style (style/label type theme)
:weight :semi-bold
:size :heading-1}
label]]))
@@ -21,8 +21,3 @@
(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})
@@ -59,9 +59,7 @@
[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
+11 -23
View File
@@ -5,7 +5,7 @@
[react-native.platform :as platform]))
(def account-colors
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :pink :camel :copper])
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :flamingo :camel :copper])
(defn alpha
[value opacity]
@@ -44,13 +44,6 @@
(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
@@ -246,7 +239,7 @@
60 "#CC6438"}
:army {50 "#216266"
60 "#1A4E52"}
:pink {50 "#F66F8F"
:flamingo {50 "#F66F8F"
60 "#C55972"}
:purple {50 "#7140FD"
60 "#5A33CA"}
@@ -323,14 +316,13 @@
[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 fallback-color)]
(if (hex-string? color-without-suffix)
(let [color-without-suffix (get colors-map color)
resolved-color? (hex-string? color-without-suffix)]
(if resolved-color?
color-without-suffix
(get color-without-suffix suffix))))
(get-in colors-map [color suffix]))))
(defn- resolve-color*
([color theme]
@@ -364,15 +356,11 @@
([color suffix]
(custom-color color suffix nil))
([color suffix opacity]
(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)))]
(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]))]
(if opacity
(alpha resolved-color (/ opacity 100))
resolved-color))))))
+3 -29
View File
@@ -4,37 +4,11 @@
[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 [[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}))
(let [kb (.useKeyboard hooks)]
{:keyboard-shown (.-keyboardShown ^js kb)
:keyboard-height (.-keyboardHeight ^js kb)}))
(defn use-back-handler
[handler]
+2 -35
View File
@@ -1,39 +1,6 @@
(ns react-native.linear-gradient
(:require
["react-native-linear-gradient" :default LinearGradient]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[taoensso.timbre :as log]))
[reagent.core :as reagent]))
(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)))
(def linear-gradient (reagent/adapt-react-class LinearGradient))
@@ -3,23 +3,21 @@
[react-native.safe-area :as safe-area]))
(defn content-container
[blur? keyboard-shown? {:keys [padding-vertical padding-horizontal]}]
[blur? keyboard-shown?]
(let [margin-bottom (if keyboard-shown? 0 (safe-area/get-bottom))]
(cond-> {:margin-top :auto
:overflow :hidden
:margin-bottom margin-bottom
:padding-vertical (or padding-vertical 12)
:padding-horizontal (or padding-horizontal 20)}
:padding-vertical 12
:padding-horizontal 20}
blur? (dissoc :padding-vertical :padding-horizontal))))
(defn blur-inner-container
[{: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)})
[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})
@@ -6,25 +6,20 @@
[status-im.common.floating-button-page.floating-container.style :as style]))
(defn- blur-container
[shell-overlay? blur-options child]
[child shell-overlay?]
(let [theme (quo.theme/use-theme)]
[quo/blur
(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?))}
{:blur-amount 20
:blur-type :transparent
:overlay-color :transparent}
[rn/view {:style (style/blur-inner-container theme shell-overlay?)}
child]]))
(defn view
[{:keys [on-layout keyboard-shown? blur? shell-overlay? blur-options]} child]
[{:keys [on-layout keyboard-shown? blur? shell-overlay?]} child]
[rn/view
{:style (style/content-container blur? keyboard-shown? blur-options)
{:style (style/content-container blur? keyboard-shown?)
:on-layout on-layout}
(if blur?
[blur-container shell-overlay? blur-options child]
[blur-container child shell-overlay?]
child)])
@@ -13,13 +13,3 @@
: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})
@@ -30,15 +30,13 @@
(reset! ratom height))))
(defn- init-keyboard-listeners
[{:keys [on-did-show on-will-show scroll-view-ref]}]
[{:keys [on-did-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"
(fn [e]
(reset! keyboard-will-show? true)
(when on-will-show (on-will-show e))))
#(reset! keyboard-will-show? true))
did-show-listener (add-listener "keyboardDidShow"
(fn [e]
(reset! keyboard-did-show? true)
@@ -60,8 +58,7 @@
(defn view
[{:keys [header footer customization-color footer-container-padding header-container-style
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?
blur-options content-avoid-keyboard?]
content-container-style gradient-cover? keyboard-should-persist-taps shell-overlay?]
:or {footer-container-padding (safe-area/get-top)}}
& children]
(reagent/with-let [scroll-view-ref (atom nil)
@@ -72,34 +69,29 @@
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
(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)))
{:scroll-view-ref scroll-view-ref
:on-did-show
(fn [e]
(reset! keyboard-height
(oops/oget e "endCoordinates.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")))
bottom-safe-area (safe-area/get-bottom)]
(oops/oget event "nativeEvent.contentOffset.y")))]
(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}])
@@ -108,28 +100,20 @@
{:on-layout set-header-height
:style header-container-style}
header]
[(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)]]
[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)]
[rn/keyboard-avoiding-view
{:style style/keyboard-avoiding-view
:keyboard-vertical-offset (if platform/ios? footer-container-padding 0)
@@ -137,9 +121,8 @@
[floating-container/view
{:on-layout set-footer-container-height
:keyboard-shown? keyboard-shown?
:blur-options blur-options
:shell-overlay? shell-overlay?
:blur? show-background?}
:blur? show-background?
:shell-overlay? shell-overlay?}
footer]]]])
(finally
(remove-listeners))))
@@ -0,0 +1,24 @@
(ns status-im.common.new-device-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})
@@ -0,0 +1,82 @@
(ns status-im.common.new-device-sheet.view
(:require
[quo.core :as quo]
[status-im.common.new-device-sheet.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- dismiss-keyboard
[]
(rf/dispatch [:dismiss-keyboard]))
(defn- hide-bottom-sheet
[]
(rf/dispatch [:hide-bottom-sheet]))
(defn- pair-and-sync
[installation-id]
(rf/dispatch [:pairing/pair-and-sync installation-id])
(hide-bottom-sheet))
(defn view
[installation-id]
(dismiss-keyboard)
[:<>
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-sheet-heading
:style style/heading}
(i18n/label :t/pair-new-device-and-sync)]
[quo/text
{:weight :regular
:size :paragraph-1
:accessibility-label :new-device-sheet-message
:style style/message}
(i18n/label :t/new-device-detected)]
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-installation-id
:style style/heading}
installation-id]
[quo/bottom-actions
{:actions :two-actions
:blur? true
:container-style {:margin-top 12}
:button-two-label (i18n/label :t/cancel)
:button-two-props {:type :grey
:on-press hide-bottom-sheet}
:button-one-label (i18n/label :t/pair-and-sync)
:button-one-props {:on-press #(pair-and-sync installation-id)}}]])
(defn view-2
[]
(let [installation-id (rf/sub [:profile/installation-id])]
(dismiss-keyboard)
[:<>
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-sheet-heading
:style style/heading}
(i18n/label :t/pair-new-device-and-sync)]
[quo/text
{:weight :regular
:size :paragraph-1
:accessibility-label :new-device-sheet-message
:style style/message}
(i18n/label :t/check-new-device)]
[quo/text
{:weight :semi-bold
:size :heading-2
:accessibility-label :new-device-installation-id
:style style/heading}
installation-id]
[quo/bottom-actions
{:actions :one-action
:blur? true
:container-style {:margin-top 12}
:button-one-label (i18n/label :t/close)
:button-one-props {:type :grey
:on-press hide-bottom-sheet}}]]))
+1 -1
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]]
[:open-modal :screen/onboarding.syncing-progress])}
[:navigate-to :screen/onboarding.syncing-progress])}
(and completed-pairing? sender?)
{:dispatch [:syncing/clear-states]}
@@ -1,14 +1,14 @@
(ns status-im.common.raw-data-block.view
(:require [quo.core :as quo]
[react-native.gesture :as gesture]
[react-native.core :as rn]
[status-im.common.raw-data-block.style :as style]))
(defn view
[data]
[gesture/scroll-view
{:style style/container}
[rn/scroll-view
{:style style/container
:content-container-style style/content}
[quo/text
{:size :paragraph-2
:style style/content
:weight :code}
data]])
+1 -3
View File
@@ -27,9 +27,7 @@
: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")
:syncing-devices (js/require "../resources/images/ui2/syncing_devices.png")
:syncing-wrong (js/require "../resources/images/ui2/syncing_wrong.png")})
:nfc-success (js/require "../resources/images/ui2/nfc-success.png")})
(def ui-themed
{:angry-man
-9
View File
@@ -38,15 +38,6 @@
"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
@@ -3,35 +3,21 @@
[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]} [{:keys [on-auth-success keycard-supported?] :as args}]]
[{:keys [db]} [args]]
(let [key-uid (get-in db [:profile/profile :key-uid])
keycard? (get-in db [:profile/profile :keycard-pairing])]
{: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])}])]}))
{: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]))}]]}))
(schema/=> authorize events-schema/?authorize)
(rf/reg-event-fx :standard-auth/authorize authorize)
@@ -108,16 +94,6 @@
: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]]
@@ -134,9 +110,7 @@
(rf/reg-event-fx
:standard-auth/reset-login-password
(fn [{:keys [db]}]
{:db (-> db
(update :profile/login dissoc :password :error)
(update :keycard dissoc :pin))}))
{:db (update db :profile/login dissoc :password :error)}))
(rf/reg-fx
:standard-auth/on-close
@@ -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 keycard-supported?]
auth-button-icon-left size blur? container-style disabled? dependencies]
:or {container-style {:flex 1}}}]
(let [theme (quo.theme/use-theme)
auth-method (rf/sub [:auth-method])
@@ -21,7 +21,6 @@
: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
-1
View File
@@ -291,7 +291,6 @@
(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")
@@ -50,7 +50,7 @@
item])))))
(defn add-manage-members
[{:keys [on-scroll]}]
[{:keys [scroll-enabled? on-scroll]}]
(let [theme (quo.theme/use-theme)
selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])
@@ -71,6 +71,7 @@
(i18n/label (if admin? :t/manage-members :t/add-members))]
[gesture/section-list
{:key-fn :title
:scroll-enabled @scroll-enabled?
:on-scroll on-scroll
:sticky-section-headers-enabled false
:sections (rf/sub [:contacts/grouped-by-first-letter])
@@ -33,7 +33,3 @@
(def drawer-message-container
{:padding-top 4
:padding-bottom 4})
(def group-member-mention
{:flex-direction :row
:align-items :center})
@@ -126,60 +126,14 @@
: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
[group-system-message message-data :group]
[system.text/text-content message-data]
constants/content-type-system-pinned-message
[system.text/text-content message-data]
@@ -1,5 +1,7 @@
(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]))
@@ -33,6 +35,17 @@
{: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?
@@ -103,11 +103,11 @@
(models.contact/process-js-contacts cofx response-js)
(seq communities)
(do
(let [communities-clj (types/js->clj communities)]
(js-delete response-js "communities")
(rf/merge cofx
(process-next response-js sync-handler)
(communities/handle-communities communities)))
(communities/handle-communities communities-clj)))
(seq bookmarks)
(let [bookmarks-clj (types/js->clj bookmarks)]
@@ -26,7 +26,7 @@
"0xD" {:address "0xD"
:operable? false
:position 3
:color :pink
:color :flamingo
:emoji "🦩"}})
(def permissioned-accounts
@@ -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]))
wallet-accounts-count (count (rf/sub [:wallet/operable-accounts-without-watched-accounts]))
addresses-shared-text (if (= revealed-accounts-count wallet-accounts-count)
(i18n/label :t/all-addresses)
(i18n/label-pluralize
@@ -57,24 +57,19 @@
:index index})
(defn- members
[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}]))
[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}])
(defn view
[]
@@ -83,6 +78,8 @@
{: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])))
@@ -136,4 +133,4 @@
(if muted
(home.actions/unmute-chat-action chat-id)
(home.actions/mute-chat-action chat-id chat-type muted)))}]}]]]
[members community-id chat-id theme]]))
[members items theme]]))
@@ -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 (rf/sub [:communities/community-members id]))
community-members-keys (set (keys (rf/sub [:communities/community-members id])))
community-member? (boolean (community-members-keys public-key))
on-toggle (fn []
(when-not community-member?
+28 -25
View File
@@ -39,6 +39,17 @@
(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]
@@ -73,9 +84,10 @@
(rf/defn handle-communities
{:events [:community/fetch-success]}
[{:keys [db]} communities-js]
{:fx (map (fn [c] [:dispatch [:communities/handle-community c]])
communities-js)})
[{:keys [db]} communities]
{:fx
(->> communities
(map #(vector :dispatch [:communities/handle-community %])))})
(rf/reg-event-fx :communities/request-to-join-result
(fn [{:keys [db]} [community-id request-id response-js]]
@@ -124,30 +136,21 @@
{}
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 [_]
{: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]}]]]}))
{: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" %)}]}))
(defn update-previous-permission-addresses
[{:keys [db]} [community-id]]
@@ -151,7 +151,7 @@
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
(deftest handle-community-test
(let [community #js {:id community-id :clock 2}]
(let [community {:id community-id :clock 2}]
(testing "given a unjoined community"
(let [effects (events/handle-community {} [community])]
(is (match? community-id
@@ -163,7 +163,7 @@
(filter some? (:fx effects))))))
(testing "given a joined community"
(let [community #js {:id community-id :clock 2 :joined true}
(let [community (assoc community :joined true)
effects (events/handle-community {} [community])]
(is (match?
[[:dispatch
@@ -172,19 +172,16 @@
(filter some? (:fx effects))))))
(testing "given a community with token-permissions-check"
(let [community #js
{:id community-id :clock 2 :token-permissions-check :fake-token-permissions-check}
(let [community (assoc community :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 #js {:id community-id}
(let [community (dissoc community :clock)
effects (events/handle-community {} [community])]
(is (nil? effects))))))
@@ -75,51 +75,46 @@
: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 (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}]]))
(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}]]))))
@@ -109,22 +109,3 @@
[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)
@@ -3,8 +3,6 @@
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
@@ -57,19 +55,3 @@
(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"}])]})))))
@@ -3,6 +3,22 @@
[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
@@ -40,25 +56,28 @@
:key-uid key-uid}]]}))))
(rf/reg-event-fx :keycard.login/on-get-application-info-success
(fn [{:keys [db]} [application-info {:keys [key-uid on-read-fx]}]]
(let [error (keycard.utils/validate-application-info key-uid application-info)]
(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)]
(if error
{:effects.utils/show-popup {:title (str error)}}
{:db (-> db
(assoc-in [:keycard :application-info] application-info)
(assoc-in [:keycard :pin :status] :verifying))
:fx on-read-fx}))))
{: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 %])}}))))
(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
(fn [{:keys [db]} [args]]
(rf/reg-event-fx :keycard/read-card-and-login
(fn [{:keys [db]}]
(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 %
args])}]]
{:on-success #(rf/dispatch [:keycard.login/on-get-application-info-success %])}]]
(log/debug "[keycard] proceed-to-login")
{:db (assoc-in db [:keycard :on-card-connected-event-vector] event-vector)
:fx [[:dispatch
@@ -9,17 +9,13 @@
(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]]
(fn [{:keys [db]} [number max-numbers on-complete-event]]
(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 (and on-complete (= (dec max-numbers) (count pin)))
[:effects.keycard.pin/dispatch-on-complete [on-complete new-pin]])]}))))
:fx [(when (= (dec max-numbers) (count pin))
[:dispatch [on-complete-event]])]}))))
+2 -2
View File
@@ -6,7 +6,7 @@
[utils.re-frame :as rf]))
(defn auth
[{:keys [on-complete]}]
[callback-event-key]
(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
on-complete])}]]))
callback-event-key])}]]))
@@ -1,29 +0,0 @@
(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 %])}]]}]]]})))
+2 -2
View File
@@ -16,8 +16,8 @@
(re-matches #".*NFCError:100.*" error)))
(defn validate-application-info
[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))]
[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))]
(log/debug "[keycard] login-with-keycard"
"empty application info" (empty? application-info)
"no key-uid" (empty? key-uid)
@@ -17,3 +17,17 @@
{:events [:onboarding/overlay-dismiss]}
[_]
{:onboarding/overlay-dismiss-fx nil})
(re-frame/reg-fx
:onboarding/overlay-show-fx
(fn []
(when-let [blur-show-fn @overlay/blur-show-fn-atom]
(blur-show-fn))
(when-let [push-animation-fn @profiles/push-animation-fn-atom]
(push-animation-fn))))
(rf/defn overlay-show
{:events [:onboarding/overlay-show]}
[_]
{:onboarding/overlay-show-fx nil})
@@ -2,6 +2,8 @@
(: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))
@@ -12,15 +14,23 @@
(def space-between-inputs {:height 16})
(def password-tips
{:flex-direction :row
:justify-content :space-between
:padding-horizontal 20})
{:flex-direction :row
:justify-content :space-between
:margin-horizontal 20})
(def form-container
{:justify-content :space-between
:padding-top 12
:padding-horizontal 20})
(def top-part
{:margin-horizontal 20
:margin-top 12})
(def disclaimer-container {:padding-horizontal 20})
(def footer-container {:padding-bottom 12})
(def footer-button-container {:margin-top 20 :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})
@@ -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]
[status-im.common.floating-button-page.view :as floating-button]
[reagent.core :as reagent]
[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 validate-password
(defn password-validations
[password]
(let [validations (juxt utils.string/has-lower-case?
utils.string/has-upper-case?
@@ -111,25 +111,68 @@
(filter true?)
count))
(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]))
(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-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]))
[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 create-password-doc
[]
@@ -140,108 +183,38 @@
[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
[]
(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))}]]]))
(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"))))
+22 -16
View File
@@ -125,25 +125,31 @@
mnemonic key-uid]))
on-error]})
;; TODO: clear syncing data if key-uid does not match
(rf/defn seed-phrase-validated
{:events [:onboarding/seed-phrase-validated]}
[{:keys [db]} seed-phrase key-uid]
(if (contains? (:profile/profiles-overview db) key-uid)
{:effects.utils/show-confirmation
{:title (i18n/label :t/multiaccount-exists-title)
:content (i18n/label :t/multiaccount-exists-content)
:confirm-button-text (i18n/label :t/unlock)
:on-accept (fn []
(re-frame/dispatch [:pop-to-root :screen/profile.profiles])
(re-frame/dispatch
[:profile/profile-selected key-uid]))
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
{:db (assoc-in db [:onboarding/profile :seed-phrase] seed-phrase)
:dispatch [:navigate-to-within-stack
[:screen/onboarding.create-profile
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]}))
(let [next-screen (if (and (seq (:syncing/key-uid db))
(= (:syncing/key-uid db) key-uid))
:screen/onboarding.create-profile-password
:screen/onboarding.create-profile)]
(if (contains? (:profile/profiles-overview db) key-uid)
{:effects.utils/show-confirmation
{:title (i18n/label :t/multiaccount-exists-title)
:content (i18n/label :t/multiaccount-exists-content)
:confirm-button-text (i18n/label :t/unlock)
:on-accept (fn []
(re-frame/dispatch [:pop-to-root :screen/profile.profiles])
(re-frame/dispatch
[:profile/profile-selected key-uid]))
:on-cancel #(re-frame/dispatch [:pop-to-root :multiaccounts])}}
{:db (assoc-in db [:onboarding/profile :seed-phrase] seed-phrase)
:dispatch [:navigate-to-within-stack
[next-screen
(get db
:onboarding/navigated-to-enter-seed-phrase-from-screen
:screen/onboarding.new-to-status)]]})))
(rf/defn navigate-to-create-profile
{:events [:onboarding/navigate-to-create-profile]}
@@ -20,13 +20,14 @@
:padding-bottom 20
:background-color (when-not in-onboarding? colors/neutral-80-opa-80-blur)})
(defn page-illustration
[width]
{:flex 1
:width width
:align-items :center
:align-self :center
:justify-content :center})
(def page-illustration
{:flex 1
:background-color colors/danger-50
:align-items :center
:margin-horizontal 20
:border-radius 20
:margin-top 20
:justify-content :center})
(def try-again-button
{:margin-top 20
@@ -2,9 +2,10 @@
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.config :as config]
[status-im.contexts.onboarding.common.background.view :as background]
[status-im.contexts.onboarding.syncing.progress.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
@@ -25,40 +26,73 @@
:title-accessibility-label :progress-screen-title
:description-accessibility-label :progress-screen-sub-title}])
(defn try-again-button
[profile-color]
[quo/button
{:on-press (fn []
(rf/dispatch [:syncing/clear-states])
(rf/dispatch [:navigate-back]))
:accessibility-label :try-again-later-button
:customization-color profile-color
:size 40
:container-style style/try-again-button}
(i18n/label :t/try-again)])
(defn navigate-to-enter-seed-phrase
[view-id]
(if (= view-id :screen/onboarding.syncing-progress-intro)
(do
(rf/dispatch [:navigate-back-to :screen/onboarding.sync-or-recover-profile])
(debounce/debounce-and-dispatch
[:onboarding/navigate-to-sign-in-by-seed-phrase :screen/onboarding.sync-or-recover-profile]
300))
(do
(rf/dispatch [:navigate-back])
(debounce/debounce-and-dispatch [:onboarding/overlay-show] 100)
(debounce/debounce-and-dispatch [:open-modal :screen/onboarding.new-to-status] 200)
(debounce/debounce-and-dispatch
[:onboarding/navigate-to-sign-in-by-seed-phrase :screen/onboarding.new-to-status]
300))))
(defn- illustration
[pairing-progress?]
[rn/image
{:resize-mode :contain
:style (style/page-illustration (:width (rn/get-window)))
:source (resources/get-image (if pairing-progress? :syncing-devices :syncing-wrong))}])
(defn try-again-button
[profile-color in-onboarding? logged-in? view-id]
[rn/view
(when-not logged-in?
[quo/button
{:on-press #(navigate-to-enter-seed-phrase view-id)
:accessibility-label :try-seed-phrase-button
:customization-color profile-color
:container-style style/try-again-button}
(i18n/label :t/enter-seed-phrase)])
[quo/button
{:on-press (fn []
(rf/dispatch [:syncing/clear-states])
(cond
logged-in? (rf/dispatch [:navigate-back])
in-onboarding? (rf/dispatch [:navigate-back-to
:screen/onboarding.sign-in-intro])
:else (do
(rf/dispatch [:navigate-back])
(debounce/throttle-and-dispatch
[:open-modal
:screen/onboarding.sign-in]
1000))))
:accessibility-label :try-again-later-button
:customization-color profile-color
:container-style style/try-again-button}
(i18n/label :t/try-again)]])
(defn view
[in-onboarding?]
(let [pairing-status (rf/sub [:pairing/pairing-status])
pairing-progress? (pairing-progress pairing-status)
profile-color (or (:color (rf/sub [:onboarding/profile]))
(rf/sub [:profile/customization-color]))]
(let [pairing-status (rf/sub [:pairing/pairing-status])
profile-color (:color (rf/sub [:onboarding/profile]))
logged-in? (rf/sub [:multiaccount/logged-in?])
view-id (rf/sub [:view-id])]
[rn/view {:style (style/page-container in-onboarding?)}
(when-not in-onboarding?
[rn/view {:style style/absolute-fill}
[background/view true]])
[quo/page-nav {:type :no-title :background :blur}]
[page-title pairing-progress?]
[illustration pairing-progress?]
[page-title (pairing-progress pairing-status)]
(if config/show-not-implemented-features?
(if (pairing-progress pairing-status)
[rn/view {:style style/page-illustration}
[quo/text "[Success here]"]]
[rn/view {:style style/page-illustration}
[quo/text "[Error here]"]])
[rn/view {:flex 1}])
(when-not (pairing-progress pairing-status)
[try-again-button profile-color])]))
[try-again-button profile-color in-onboarding? logged-in? view-id])]))
(defn view-onboarding
[]
@@ -14,7 +14,7 @@
[]
(let [state (reagent/atom {:type :default
:customization-color :blue
:account-color :pink
:account-color :flamingo
:title "Alisher Yakupov"
:address "0x21a...49e"
:on-options-press #(js/alert "Options button pressed!")})]
@@ -28,7 +28,7 @@
{:image-source (quo.resources/get-network :ethereum)
:label "Mainnet"}
:saved-address
{:customization-color :pink
{:customization-color :flamingo
:label "Peter Lambo"}
:account
{:label "Account"
@@ -57,15 +57,14 @@
[{:method "wakuext_startMessenger"
:on-success [:profile.login/messenger-started]
:on-error #(log/error "failed to start messenger" %)}]]
[:dispatch [:universal-links/generate-profile-url]]
[:dispatch [:community/fetch]]
;; Wallet initialization can be delayed a little bit because we
;; need to free the queue for heavier events first, such as
;; loading chats and communities. This globally helps alleviate
;; stuttering immediately after login.
[:dispatch-later [{:ms 500 :dispatch [:wallet/initialize]}]]
[:push-notifications/load-preferences]
[:profile.config/get-node-config]
[:logs/set-level log-level]
[:activity-center.notifications/fetch-pending-contact-requests-fx]
[:activity-center/update-seen-state]
[:activity-center.notifications/fetch-unread-count]
;; Immediately try to open last chat. We can't wait until the
;; messenger has started and has processed all chats because
@@ -91,45 +90,24 @@
;; login phase 2: we want to load and show chats faster, so we split login into 2 phases
(rf/reg-event-fx :profile.login/get-chats-callback
(fn [{:keys [db]}]
(let [{:keys [notifications-enabled? key-uid]} (:profile/profile db)]
(let [{:keys [notifications-enabled? key-uid
preview-privacy?]} (:profile/profile db)]
{:db db
:fx [[:effects.profile/enable-local-notifications]
[:contacts/initialize-contacts]
;; The delay is arbitrary. We just want to give some time for the
;; thread to process more important events first, but we can't delay
;; too much otherwise the UX may degrade due to stale data.
[:dispatch-later [{:ms 1500 :dispatch [:profile.login/non-critical-initialization]}]]
[:browser/initialize-browser]
[:dispatch [:mobile-network/on-network-status-change]]
[:group-chats/get-group-chat-invitations]
[:profile.settings/get-profile-picture key-uid]
[:profile.settings/blank-preview-flag-changed preview-privacy?]
[:chat.ui/request-link-preview-whitelist]
[:visibility-status-updates/fetch]
[:switcher-cards/fetch]
(when (ff/enabled? ::ff/wallet.wallet-connect)
[:dispatch [:wallet-connect/init]])
(when notifications-enabled?
[:effects/push-notifications-enable])]})))
;; Login phase 3: events at this phase can wait a bit longer to be processed in
;; order to leave room for higher-priority or heavy weight events.
(rf/reg-event-fx :profile.login/non-critical-initialization
(fn [{:keys [db]}]
(let [{:keys [preview-privacy?]} (:profile/profile db)]
{:fx [[:browser/initialize-browser]
[:logging/initialize-web3-client-version]
[:group-chats/get-group-chat-invitations]
[:profile.settings/blank-preview-flag-changed preview-privacy?]
(when (ff/enabled? ::ff/shell.jump-to)
[:switcher-cards/fetch])
[:visibility-status-updates/fetch]
[:dispatch [:universal-links/generate-profile-url]]
[:push-notifications/load-preferences]
[:profile.config/get-node-config]
[:activity-center.notifications/fetch-pending-contact-requests-fx]
[:activity-center/update-seen-state]
[:activity-center.notifications/fetch-unread-count]
[:pairing/get-our-installations]
[:json-rpc/call
[{:method "admin_nodeInfo"
:on-success [:profile.login/node-info-fetched]
:on-error #(log/error "node-info: failed error" %)}]]]})))
(rf/reg-event-fx :profile.login/messenger-started
(fn [{:keys [db]} [{:keys [mailservers]}]]
(let [new-account? (get db :onboarding/new-account?)]
@@ -141,6 +119,13 @@
(rf/dispatch [:chats-list/load-success result])
(rf/dispatch [:communities/get-user-requests-to-join])
(rf/dispatch [:profile.login/get-chats-callback]))}]
[:json-rpc/call
[{:method "admin_nodeInfo"
:on-success [:profile.login/node-info-fetched]
:on-error #(log/error "node-info: failed error" %)}]]
[:pairing/get-our-installations]
(when (:syncing/installation-id db)
[:dispatch [:pairing/finish-seed-phrase-fallback-syncing]])
(when-not new-account?
[:dispatch [:universal-links/process-stored-event]])]})))
@@ -156,9 +141,11 @@
(if error
{:db (update db :profile/login #(-> % (dissoc :processing) (assoc :error error)))}
{:db (dissoc db :profile/login)
:fx [(when (and new-account? (not recovered-account?))
[:dispatch-later [{:ms 1000 :dispatch [:wallet-legacy/set-initial-blocks-range]}]])
[:dispatch-later [{:ms 2000 :dispatch [:ens/update-usernames ensUsernames]}]]
:fx [[:logging/initialize-web3-client-version]
(when (and new-account? (not recovered-account?))
[:dispatch [:wallet-legacy/set-initial-blocks-range]])
[:dispatch [:ens/update-usernames ensUsernames]]
[:dispatch [:wallet/initialize]]
[:dispatch [:profile.login/login-existing-profile settings account]]]})))
(rf/reg-event-fx
@@ -239,16 +239,7 @@
:profile-picture profile-picture
:card-style style/login-profile-card}]
(if keycard-pairing
[keycard.pin/auth
{:on-complete
(fn [pin-text]
(rf/dispatch
[:keycard/read-card
{:key-uid key-uid
:on-read-fx [[:effects.keycard/get-keys
{:pin pin-text
:on-success #(rf/dispatch [:keycard.login/on-get-keys-success %])
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}]))}]
[keycard.pin/auth :keycard/read-card-and-login]
[password-input])]
(when-not keycard-pairing
[quo/button
@@ -2,6 +2,7 @@
(:require
[native-module.core :as native-module]
[status-im.common.emoji-picker.utils :as emoji-picker.utils]
[status-im.constants :as constants]
[status-im.contexts.profile.config :as profile.config]
status-im.contexts.profile.recover.effects
[utils.re-frame :as rf]
@@ -17,11 +18,11 @@
(assoc-in [:syncing :login-sha3-password] login-sha3-password))
:effects.profile/restore-and-login
(merge (profile.config/create)
{:displayName display-name
:mnemonic (security/safe-unmask-data seed-phrase)
:password login-sha3-password
:imagePath (profile.config/strip-file-prefix image-path)
:customizationColor color
:emoji (emoji-picker.utils/random-emoji)
:fetchBackup true})}))
(assoc (profile.config/create)
:displayName display-name
:mnemonic (security/safe-unmask-data seed-phrase)
:password login-sha3-password
:imagePath (profile.config/strip-file-prefix image-path)
:customizationColor (or color constants/profile-default-color)
:emoji (emoji-picker.utils/random-emoji)
:fetchBackup true)}))
+20 -3
View File
@@ -46,13 +46,29 @@
(log/info "[local-pairing] input-connection-string-for-bootstrapping callback"
{:response res
:event :syncing/input-connection-string-for-bootstrapping})
(let [error (when (sync-utils/extract-error res)
(str "generic-error: " res))]
(when (some? error)
(let [response (transforms/json->clj res)
installation-id (:installationId response)
key-uid (:keyUID response)
error (:error response)]
(when (seq installation-id)
(rf/dispatch [:syncing/set-syncing-installation-id installation-id key-uid]))
(when (seq error)
(rf/dispatch [:toasts/upsert
{:type :negative
:text error}]))))
(rf/defn initiate-pairing-process
{:events [:syncing/initiate-pairing-process]}
[{:keys [db]}]
{:db (assoc db :syncing/pairing-process-initiated? true)})
(rf/defn set-syncing-installation-id
{:events [:syncing/set-syncing-installation-id]}
[{:keys [db]} installation-id key-uid]
{:db (assoc db
:syncing/key-uid key-uid
:syncing/installation-id installation-id)})
(rf/defn preflight-outbound-check-for-local-pairing
{:events [:syncing/preflight-outbound-check]}
[_ set-checks-passed]
@@ -96,6 +112,7 @@
(when (sync-utils/valid-connection-string? response)
(on-valid-connection-string response)
(rf/dispatch [:syncing/update-role constants/local-pairing-role-sender])
(rf/dispatch [:syncing/initiate-pairing-process])
(rf/dispatch [:hide-bottom-sheet])))]
(when-not (and error (string/blank? error))
(let [key-uid (get-in db [:profile/profile :key-uid])
@@ -73,7 +73,7 @@
[]
(let [compressed-key (rf/sub [:profile/compressed-key])
customization-color (rf/sub [:profile/customization-color])
keypairs (rf/sub [:wallet/fully-operable-keypairs-list])
keypairs (rf/sub [:wallet/keypairs-list])
selected-keypair (rf/sub [:wallet/selected-keypair-uid])
profile-picture (rf/sub [:profile/image])
[selected-key-uid set-selected-key-uid] (rn/use-state selected-keypair)]
@@ -9,7 +9,7 @@
(defn view
[]
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/stop-get-suggested-routes]))
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/clean-routes-calculation]))
[rn/view {:style style/bridge-send-wrapper}
[input-amount/view
{:current-screen-id :screen/wallet.bridge-input-amount
@@ -41,6 +41,7 @@
(not watch-only?))
{:icon-name :i/dapps
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])})
{:content-type :account-switcher
:customization-color color
:on-press #(on-dapps-press switcher-type)
@@ -1,11 +1,9 @@
(ns status-im.contexts.wallet.common.activity-tab.view
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.theme]
[react-native.core :as rn]
[status-im.common.resources :as resources]
[status-im.constants :as constants]
[status-im.contexts.shell.jump-to.constants :as jump-to.constants]
[status-im.contexts.wallet.common.empty-tab.view :as empty-tab]
[utils.i18n :as i18n]
@@ -82,10 +80,6 @@
; :network-logo network-logo}
; :blur? false}])
(defn- section-header
[{:keys [title]}]
[quo/divider-date title])
(defn activity-item
[{:keys [transaction] :as activity}]
(case transaction
@@ -94,63 +88,20 @@
;; :mint [mint-activity activity]
nil))
(defn- pressable-text
[{:keys [on-press text]}]
[rn/text
{:style {:text-decoration-line :underline}
:on-press on-press}
text])
(defn view
[]
(let [theme (quo.theme/use-theme)
address (rf/sub [:wallet/current-viewing-account-address])
activity-list (rf/sub [:wallet/activities-for-current-viewing-account])
open-eth-chain-explorer (rn/use-callback
#(rf/dispatch [:wallet/navigate-to-chain-explorer
{:address address
:network constants/mainnet-network-name}])
[address])
open-oeth-chain-explorer (rn/use-callback
#(rf/dispatch [:wallet/navigate-to-chain-explorer
{:address address
:network constants/optimism-network-name}])
[address])
open-arb-chain-explorer (rn/use-callback
#(rf/dispatch [:wallet/navigate-to-chain-explorer
{:address address
:network constants/arbitrum-network-name}])
[address])]
[:<>
[quo/information-box
{:type :informative
:icon :i/info
:closable? false
:style {:margin-horizontal 20 :margin-vertical 8}}
[:<>
(str (i18n/label :t/wallet-activity-beta-message) " ")
[pressable-text
{:on-press open-eth-chain-explorer
:text (i18n/label :t/etherscan)}]
", "
[pressable-text
{:on-press open-oeth-chain-explorer
:text (i18n/label :t/op-explorer)}]
(str ", " (string/lower-case (i18n/label :t/or)) " ")
[pressable-text
{:on-press open-arb-chain-explorer
:text (i18n/label :t/arbiscan)}]
"."]]
(if (empty? activity-list)
[empty-tab/view
{:title (i18n/label :t/no-activity)
:description (i18n/label :t/empty-tab-description)
:image (resources/get-themed-image :no-activity theme)}]
[rn/section-list
{:sections activity-list
:sticky-section-headers-enabled false
:style {:flex 1
:padding-horizontal 8}
:content-container-style {:padding-bottom jump-to.constants/floating-shell-button-height}
:render-fn activity-item
:render-section-header-fn section-header}])]))
(let [theme (quo.theme/use-theme)
activity-list (rf/sub [:wallet/activities-for-current-viewing-account])]
(if (empty? activity-list)
[empty-tab/view
{:title (i18n/label :t/no-activity)
:description (i18n/label :t/empty-tab-description)
:image (resources/get-themed-image :no-activity theme)}]
[rn/section-list
{:sections activity-list
:sticky-section-headers-enabled false
:style {:flex 1
:padding-horizontal 8}
:content-container-style {:padding-bottom jump-to.constants/floating-shell-button-height}
:render-fn activity-item
:render-section-header-fn (fn [{:keys [title]}] [quo/divider-date title])}])))
@@ -84,10 +84,10 @@
[]
(let [{:keys [bottom]} (safe-area/get-insets)
{:keys [color] :as wallet-account} (rf/sub [:wallet/current-viewing-account])
customization-color (rf/sub [:profile/customization-color])
sessions (rf/sub
[:wallet-connect/sessions-for-current-account-and-networks])
theme (quo.theme/use-theme)]
[:wallet-connect/sessions-for-current-account])
theme (quo.theme/use-theme)
customization-color (rf/sub [:profile/customization-color])]
[rn/view {:flex 1}
[header
{:title (i18n/label :t/connected-dapps)
@@ -5,7 +5,6 @@
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[utils.collection :as utils.collection]
[utils.money :as money]
[utils.number :as utils.number]
@@ -189,77 +188,3 @@
:removed-account-addresses removed-account-addresses
:updated-keypairs-by-id updated-keypairs-by-id
:updated-accounts-by-address updated-accounts-by-address}))
(defn- rename-keys-to-kebab-case
[m]
(set/rename-keys m (zipmap (keys m) (map transforms/->kebab-case-keyword (keys m)))))
(defn rpc->suggested-routes
[suggested-routes]
(cond
(map? suggested-routes)
(into {}
(for [[k v] (rename-keys-to-kebab-case suggested-routes)]
[k (rpc->suggested-routes v)]))
(vector? suggested-routes)
(map rpc->suggested-routes suggested-routes)
:else suggested-routes))
(def ^:private precision 6)
(defn new->old-route-path
[new-path]
(let [bonder-fees (:tx-bonder-fees new-path)
token-fees (+ (money/wei->ether bonder-fees)
(money/wei->ether
(:tx-token-fees new-path)))]
{:from (:from-chain new-path)
:amount-in-locked (:amount-in-locked new-path)
:amount-in (:amount-in new-path)
:max-amount-in "0x0"
:gas-fees {:gas-price "0"
:base-fee (send-utils/convert-to-gwei (:tx-base-fee
new-path)
precision)
:max-priority-fee-per-gas (send-utils/convert-to-gwei (:tx-priority-fee
new-path)
precision)
:max-fee-per-gas-low (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:low])
precision)
:max-fee-per-gas-medium (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:medium])
precision)
:max-fee-per-gas-high (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:high])
precision)
:l-1-gas-fee (send-utils/convert-to-gwei (:tx-l-1-fee
new-path)
precision)
:eip-1559-enabled true}
:bridge-name (:processor-name new-path)
:amount-out (:amount-out new-path)
:approval-contract-address (:approval-contract-address new-path)
:approval-required (:approval-required new-path)
:estimated-time (:estimated-time new-path)
:approval-gas-fees (* (money/wei->ether (get-in new-path
[:suggested-levels-for-max-fees-per-gas
:medium]))
(:approval-gas-amount new-path))
:to (:to-chain new-path)
:bonder-fees bonder-fees
:approval-amount-required (:approval-amount-required new-path)
;; :cost () ;; tbd not used on desktop
:token-fees token-fees
:gas-amount (:tx-gas-amount new-path)}))
+154 -190
View File
@@ -1,18 +1,19 @@
(ns status-im.contexts.wallet.send.events
(:require
[camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[native-module.core :as native-module]
[status-im.constants :as constants]
[status-im.contexts.wallet.collectible.utils :as collectible.utils]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.send.utils :as send-utils]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.money :as money]
[utils.number]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
(rf/reg-event-fx :wallet/clean-send-data
(fn [{:keys [db]}]
@@ -23,82 +24,86 @@
{:db (assoc-in db [:wallet :ui :send :select-address-tab] tab)}))
(rf/reg-event-fx :wallet/suggested-routes-success
(fn [{:keys [db]} [suggested-routes-data]]
(let [chosen-route (:best suggested-routes-data)
{:keys [token collectible token-display-name
receiver-networks
receiver-network-values
sender-network-values tx-type
disabled-from-chain-ids
from-locked-amounts]} (get-in db [:wallet :ui :send])
token-decimals (if collectible 0 (:decimals token))
native-token? (and token (= token-display-name "ETH"))
routes-available? (pos? (count chosen-route))
token-networks (:networks token)
token-networks-ids (when token-networks
(map #(:chain-id %) token-networks))
from-network-amounts-by-chain (send-utils/network-amounts-by-chain
{:route chosen-route
:token-decimals token-decimals
:native-token? native-token?
:receiver? false})
from-network-values-for-ui (send-utils/network-values-for-ui
from-network-amounts-by-chain)
to-network-amounts-by-chain (send-utils/network-amounts-by-chain
{:route chosen-route
:token-decimals token-decimals
:native-token? native-token?
:receiver? true})
to-network-values-for-ui (send-utils/network-values-for-ui
to-network-amounts-by-chain)
sender-possible-chain-ids (map :chain-id sender-network-values)
sender-network-values (if routes-available?
(send-utils/network-amounts
{:network-values
(if (= tx-type :tx/bridge)
from-network-values-for-ui
(send-utils/add-zero-values-to-network-values
from-network-values-for-ui
sender-possible-chain-ids))
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:from-locked-amounts from-locked-amounts
:tx-type tx-type
:receiver? false})
(send-utils/reset-loading-network-amounts-to-zero
sender-network-values))
receiver-network-values (if routes-available?
(send-utils/network-amounts
{:network-values to-network-values-for-ui
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type tx-type
:receiver? true})
(->
(fn [{:keys [db]} [suggested-routes timestamp]]
(when (= (get-in db [:wallet :ui :send :suggested-routes-call-timestamp]) timestamp)
(let [suggested-routes-data (cske/transform-keys transforms/->kebab-case-keyword
suggested-routes)
chosen-route (:best suggested-routes-data)
token (get-in db [:wallet :ui :send :token])
collectible (get-in db [:wallet :ui :send :collectible])
token-display-name (get-in db [:wallet :ui :send :token-display-name])
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
receiver-network-values (get-in db [:wallet :ui :send :receiver-network-values])
sender-network-values (get-in db [:wallet :ui :send :sender-network-values])
tx-type (get-in db [:wallet :ui :send :tx-type])
disabled-from-chain-ids (get-in db [:wallet :ui :send :disabled-from-chain-ids] [])
from-locked-amounts (get-in db [:wallet :ui :send :from-locked-amounts] {})
token-decimals (if collectible 0 (:decimals token))
native-token? (and token (= token-display-name "ETH"))
routes-available? (pos? (count chosen-route))
token-networks (:networks token)
token-networks-ids (when token-networks (mapv #(:chain-id %) token-networks))
from-network-amounts-by-chain (send-utils/network-amounts-by-chain {:route chosen-route
:token-decimals
token-decimals
:native-token?
native-token?
:receiver? false})
from-network-values-for-ui (send-utils/network-values-for-ui from-network-amounts-by-chain)
to-network-amounts-by-chain (send-utils/network-amounts-by-chain {:route chosen-route
:token-decimals
token-decimals
:native-token?
native-token?
:receiver? true})
to-network-values-for-ui (send-utils/network-values-for-ui to-network-amounts-by-chain)
sender-possible-chain-ids (mapv :chain-id sender-network-values)
sender-network-values (if routes-available?
(send-utils/network-amounts
{:network-values
(if (= tx-type :tx/bridge)
from-network-values-for-ui
(send-utils/add-zero-values-to-network-values
from-network-values-for-ui
sender-possible-chain-ids))
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:from-locked-amounts from-locked-amounts
:tx-type tx-type
:receiver? false})
(send-utils/reset-loading-network-amounts-to-zero
receiver-network-values)
vec
(conj {:type :edit})))
network-links (when routes-available?
(send-utils/network-links chosen-route
sender-network-values
receiver-network-values))]
{:db (update-in db
[:wallet :ui :send]
assoc
:suggested-routes suggested-routes-data
:route chosen-route
:from-values-by-chain from-network-values-for-ui
:to-values-by-chain to-network-values-for-ui
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values
:network-links network-links
:loading-suggested-routes? false)})))
sender-network-values))
receiver-network-values (if routes-available?
(send-utils/network-amounts
{:network-values to-network-values-for-ui
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type tx-type
:receiver? true})
(->
(send-utils/reset-loading-network-amounts-to-zero
receiver-network-values)
vec
(conj {:type :edit})))
network-links (when routes-available?
(send-utils/network-links chosen-route
sender-network-values
receiver-network-values))]
{:db (-> db
(assoc-in [:wallet :ui :send :suggested-routes] suggested-routes-data)
(assoc-in [:wallet :ui :send :route] chosen-route)
(assoc-in [:wallet :ui :send :from-values-by-chain] from-network-values-for-ui)
(assoc-in [:wallet :ui :send :to-values-by-chain] to-network-values-for-ui)
(assoc-in [:wallet :ui :send :sender-network-values] sender-network-values)
(assoc-in [:wallet :ui :send :receiver-network-values] receiver-network-values)
(assoc-in [:wallet :ui :send :network-links] network-links)
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))}))))
(rf/reg-event-fx :wallet/suggested-routes-error
(fn [{:keys [db]} [error-message]]
(fn [{:keys [db]} [error]]
(let [cleaned-sender-network-values (-> (get-in db [:wallet :ui :send :sender-network-values])
(send-utils/reset-loading-network-amounts-to-zero))
cleaned-receiver-network-values (-> (get-in db [:wallet :ui :send :receiver-network-values])
@@ -115,7 +120,7 @@
[:toasts/upsert
{:id :send-transaction-error
:type :negative
:text error-message}]]]})))
:text (:message error)}]]]})))
(rf/reg-event-fx :wallet/clean-suggested-routes
(fn [{:keys [db]}]
@@ -130,7 +135,8 @@
:sender-network-values
:receiver-network-values
:network-links
:loading-suggested-routes?)}))
:loading-suggested-routes?
:suggested-routes-call-timestamp)}))
(rf/reg-event-fx :wallet/clean-send-address
(fn [{:keys [db]}]
@@ -171,7 +177,7 @@
(assoc-in [:wallet :ui :send :receiver-preferred-networks] receiver-networks)
(assoc-in [:wallet :ui :send :receiver-networks] receiver-networks))
:fx [(when (and collectible-tx? one-collectible?)
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -183,7 +189,7 @@
(fn [{:keys [db]} [selected-networks]]
(let [amount (get-in db [:wallet :ui :send :amount])]
{:db (assoc-in db [:wallet :ui :send :receiver-networks] selected-networks)
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount amount}]]]})))
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]]})))
(rf/reg-event-fx
:wallet/set-token-to-send
@@ -294,7 +300,7 @@
one-collectible?
(assoc-in [:wallet :ui :send :amount] 1))
:fx [(when (and one-collectible? recipient-set?)
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen current-screen
@@ -305,7 +311,7 @@
:wallet/set-collectible-amount-to-send
(fn [{db :db} [{:keys [stack-id amount]}]]
{:db (assoc-in db [:wallet :ui :send :amount] amount)
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount amount}]]
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -341,7 +347,7 @@
(fn [{:keys [db]}]
(let [keys-to-remove [:to-values-by-chain :network-links :sender-network-values :route
:receiver-network-values :suggested-routes :from-values-by-chain
:loading-suggested-routes?]]
:loading-suggested-routes? :suggested-routes-call-timestamp]]
{:db (update-in db [:wallet :ui :send] #(apply dissoc % keys-to-remove))})))
(rf/reg-event-fx :wallet/disable-from-networks
@@ -376,67 +382,74 @@
(when (empty? sender-network-values) :sender-network-values)
(when (empty? receiver-network-values) :receiver-network-values)))})))
(rf/reg-event-fx :wallet/start-get-suggested-routes
(fn [{:keys [db]} [{:keys [amount amount-out updated-token] :as args :or {amount-out "0"}}]]
(rf/reg-event-fx :wallet/get-suggested-routes
(fn [{:keys [db now]} [{:keys [amount updated-token]}]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
{:keys [token tx-type collectible to-address
receiver-networks disabled-from-chain-ids
from-locked-amounts bridge-to-chain-id]
:or {token updated-token}} (get-in db [:wallet :ui :send])
token (or updated-token (get-in db [:wallet :ui :send :token]))
transaction-type (get-in db [:wallet :ui :send :tx-type])
collectible (get-in db [:wallet :ui :send :collectible])
to-address (get-in db [:wallet :ui :send :to-address])
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
disabled-from-chain-ids (or (get-in db [:wallet :ui :send :disabled-from-chain-ids]) [])
from-locked-amounts (or (get-in db [:wallet :ui :send :from-locked-amounts]) {})
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
networks ((if test-networks-enabled? :test :prod)
(get-in db [:wallet :networks]))
network-chain-ids (map :chain-id networks)
bridge-to-chain-id (get-in db [:wallet :ui :send :bridge-to-chain-id])
token-decimal (when token (:decimals token))
token-id (utils/format-token-id token collectible)
to-token-id ""
network-preferences (if token [] [(get-in collectible [:id :contract-id :chain-id])])
gas-rates constants/gas-rate-medium
to-hex (fn [v] (send-utils/amount-in-hex v (if token token-decimal 0)))
amount-in (to-hex amount)
amount-out (to-hex amount-out)
from-address wallet-address
disabled-to-chain-ids (if (= tx-type :tx/bridge)
disabled-from-chain-ids disabled-from-chain-ids
disabled-to-chain-ids (if (= transaction-type :tx/bridge)
(filter #(not= % bridge-to-chain-id) network-chain-ids)
(filter (fn [chain-id]
(not (some #(= chain-id %)
receiver-networks)))
network-chain-ids))
from-locked-amount (update-vals from-locked-amounts to-hex)
transaction-type (case tx-type
:tx/collectible-erc-721 constants/send-type-erc-721-transfer
:tx/collectible-erc-1155 constants/send-type-erc-1155-transfer
:tx/bridge constants/send-type-bridge
constants/send-type-transfer)
transaction-type-param (case transaction-type
:tx/collectible-erc-721 constants/send-type-erc-721-transfer
:tx/collectible-erc-1155 constants/send-type-erc-1155-transfer
:tx/bridge constants/send-type-bridge
constants/send-type-transfer)
balances-per-chain (when token (:balances-per-chain token))
sender-token-available-networks-for-suggested-routes
(when token
(send-utils/token-available-networks-for-suggested-routes
{:balances-per-chain balances-per-chain
:disabled-chain-ids disabled-from-chain-ids
:only-with-balance? true}))
(send-utils/token-available-networks-for-suggested-routes {:balances-per-chain
balances-per-chain
:disabled-chain-ids
disabled-from-chain-ids
:only-with-balance? true}))
receiver-token-available-networks-for-suggested-routes
(when token
(send-utils/token-available-networks-for-suggested-routes
{:balances-per-chain balances-per-chain
:disabled-chain-ids disabled-from-chain-ids
:only-with-balance? false}))
token-networks-ids (when token (map #(:chain-id %) (:networks token)))
(send-utils/token-available-networks-for-suggested-routes {:balances-per-chain
balances-per-chain
:disabled-chain-ids
disabled-from-chain-ids
:only-with-balance? false}))
token-networks-ids (when token (mapv #(:chain-id %) (:networks token)))
sender-network-values (when sender-token-available-networks-for-suggested-routes
(send-utils/loading-network-amounts
{:valid-networks
(if (= tx-type :tx/bridge)
(if (= transaction-type :tx/bridge)
(remove #(= bridge-to-chain-id %)
sender-token-available-networks-for-suggested-routes)
sender-token-available-networks-for-suggested-routes)
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type tx-type
:tx-type transaction-type
:receiver? false}))
receiver-network-values (when receiver-token-available-networks-for-suggested-routes
(send-utils/loading-network-amounts
{:valid-networks
(if (= tx-type :tx/bridge)
(if (= transaction-type :tx/bridge)
(filter
#(= bridge-to-chain-id %)
receiver-token-available-networks-for-suggested-routes)
@@ -444,70 +457,40 @@
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type tx-type
:tx-type transaction-type
:receiver? true}))
params [{:uuid (str (random-uuid))
:sendType transaction-type
:addrFrom from-address
:addrTo to-address
:amountIn amount-in
:amountOut amount-out
:tokenID token-id
:toTokenID to-token-id
:disabledFromChainIDs disabled-from-chain-ids
:disabledToChainIDs disabled-to-chain-ids
:gasFeeMode gas-rates
:fromLockedAmount from-locked-amount
:username (:username args)
:publicKey (:publicKey args)
:packID (:packID args)}]]
(when (and to-address from-address amount-in token-id)
{:db (update-in db
[:wallet :ui :send]
#(-> %
(assoc :amount amount
:loading-suggested-routes? true
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values)
(dissoc :network-links)
(cond-> token (assoc :token token))))
:json-rpc/call [{:method "wallet_getSuggestedRoutesV2Async"
:params params
:on-error (fn [error]
request-params [transaction-type-param
from-address
to-address
amount-in
token-id
to-token-id
disabled-from-chain-ids
disabled-to-chain-ids
network-preferences
gas-rates
from-locked-amount]]
{:db (cond-> db
:always (assoc-in [:wallet :ui :send :amount] amount)
:always (assoc-in [:wallet :ui :send :loading-suggested-routes?] true)
:always (assoc-in [:wallet :ui :send :sender-network-values]
sender-network-values)
:always (assoc-in [:wallet :ui :send :receiver-network-values]
receiver-network-values)
:always (assoc-in [:wallet :ui :send :suggested-routes-call-timestamp] now)
:always (update-in [:wallet :ui :send] dissoc :network-links)
token (assoc-in [:wallet :ui :send :token] token))
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
:params request-params
:on-success (fn [suggested-routes]
(rf/dispatch [:wallet/suggested-routes-success suggested-routes
now]))
:on-error (fn [error]
(rf/dispatch [:wallet/suggested-routes-error error])
(log/error "failed to get suggested routes (async)"
{:event :wallet/start-get-suggested-routes
:error (:message error)
:params params}))}]}))))
(rf/reg-event-fx :wallet/stop-get-suggested-routes
(fn []
{:fx [[:dispatch [:wallet/clean-routes-calculation]]]
:json-rpc/call [{:method "wallet_stopSuggestedRoutesV2AsyncCalcualtion"
:params []
:on-error (fn [error]
(log/error "failed to stop suggested routes calculation"
{:event :wallet/stop-get-suggested-routes
:error error}))}]}))
(rf/reg-event-fx :wallet/handle-suggested-routes
(fn [_ data]
(if-let [error (some-> data
first
:ErrorResponse
(#(if (= (:code %) "0") "An error occurred" (:details %))))]
(do
(log/error "failed to get suggested routes (async)"
{:event :wallet/handle-suggested-routes
:error error})
{:fx [[:dispatch [:wallet/suggested-routes-error error]]]})
(let [suggested-routes-new-data (data-store/rpc->suggested-routes data)
suggested-routes (-> suggested-routes-new-data
first
(update :best #(map data-store/new->old-route-path %))
(update :candidates #(map data-store/new->old-route-path %)))]
{:fx [[:dispatch
[:wallet/suggested-routes-success suggested-routes]]]}))))
(log/error "failed to get suggested routes"
{:event :wallet/get-suggested-routes
:error error
:params request-params}))}]})))
(rf/reg-event-fx :wallet/add-authorized-transaction
(fn [{:keys [db]} [transaction]]
@@ -694,13 +677,11 @@
:transfer-type transaction-type-param})
transaction-paths
sha3-pwd]]
(log/info "multi transaction called")
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success (fn [result]
(when result
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet])))
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet]))
:on-error (fn [error]
(log/error "failed to send transaction"
{:event :wallet/send-transaction
@@ -711,23 +692,6 @@
:type :negative
:text (:message error)}]))}]})))
(rf/reg-event-fx :wallet/proceed-with-transactions-signatures
(fn [_ [signatures]]
{:json-rpc/call [{:method "wallet_proceedWithTransactionsSignatures"
:params [signatures]
:on-success (fn [result]
(when result
(rf/dispatch [:wallet/add-authorized-transaction result])
(rf/dispatch [:hide-bottom-sheet])))
:on-error (fn [error]
(log/error "failed to proceed-with-transactions-signatures"
{:event :wallet/proceed-with-transactions-signatures
:error error})
(rf/dispatch [:toasts/upsert
{:id :send-transaction-error
:type :negative
:text (:message error)}]))}]}))
(rf/reg-event-fx
:wallet/select-from-account
(fn [{db :db} [{:keys [address stack-id network-details start-flow?]}]]
@@ -141,7 +141,7 @@
(h/deftest-event :wallet/set-collectible-amount-to-send
[event-id dispatch]
(let [initial-db {:wallet {:ui {:send nil}}}
expected-fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 10}]]
expected-fx [[:dispatch [:wallet/get-suggested-routes {:amount 10}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen nil :flow-id :wallet-send-flow}]]]
@@ -273,18 +273,19 @@
[event-id dispatch]
(reset! rf-db/app-db
{:wallet {:ui {:send
{:other-props :value
:suggested-routes ["1" "2"]
:route "1"
:amount 10
:from-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:to-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:sender-network-values [:eth :arb1]
:receiver-network-values [:eth :arb1]
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]
:loading-suggested-routes? false}}}})
{:other-props :value
:suggested-routes ["1" "2"]
:route "1"
:amount 10
:from-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:to-values-by-chain [{:chain-id 1} {:chain-id 10} {:chain-id 42161}]
:sender-network-values [:eth :arb1]
:receiver-network-values [:eth :arb1]
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]
:loading-suggested-routes? false
:suggested-routes-call-timestamp ["1" "2"]}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :suggested-routes)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :route)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :amount)))
@@ -295,6 +296,8 @@
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :network-links)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:loading-suggested-routes?)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:suggested-routes-call-timestamp)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/suggested-routes-error
@@ -321,7 +324,7 @@
:receiver-network-values receiver-network-amounts
:route :values
:loading-suggested-routes? true}}}})
(is (match? expected-result (dispatch [event-id "error"])))))
(is (match? expected-result (dispatch [event-id {:message "error"}])))))
(h/deftest-event :wallet/reset-network-amounts-to-zero
[event-id dispatch]
@@ -435,7 +438,7 @@
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]]
:fx [[:dispatch [:wallet/get-suggested-routes {:amount 1}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@@ -129,7 +129,7 @@
[{:keys [amount bounce-duration-ms token valid-input?]}]
(if valid-input?
(debounce/debounce-and-dispatch
[:wallet/start-get-suggested-routes
[:wallet/get-suggested-routes
{:amount amount
:updated-token token}]
bounce-duration-ms)
@@ -396,7 +396,7 @@
(and (not should-try-again?) confirm-disabled?))
:on-press (cond
should-try-again?
#(rf/dispatch [:wallet/start-get-suggested-routes
#(rf/dispatch [:wallet/get-suggested-routes
{:amount amount-in-crypto
:updated-token token-by-symbol}])
sending-to-unpreferred-networks?
@@ -257,8 +257,7 @@
:transaction-type transaction-type}]
(when (and (not loading-suggested-routes?) route (seq route))
[standard-auth/slide-button
{:keycard-supported? true
:size :size-48
{:size :size-48
:track-text (if (= transaction-type :tx/bridge)
(i18n/label :t/slide-to-bridge)
(i18n/label :t/slide-to-send))
@@ -266,7 +265,8 @@
:customization-color account-color
:on-auth-success #(rf/dispatch
[:wallet/send-transaction
(security/safe-unmask-data %)])
(security/safe-unmask-data
%)])
:auth-button-label (i18n/label :t/confirm)}])]
:gradient-cover? true
:customization-color (:color account)}
@@ -242,10 +242,3 @@
(defn tx-type-collectible?
[tx-type]
(contains? collectible-tx-set tx-type))
(defn convert-to-gwei
[n precision]
(-> n
money/wei->gwei
(money/with-precision precision)
(str)))
@@ -134,7 +134,6 @@
:iconUrl (get-in session [:peer :metadata :icons 0])
:url (get-in session [:peer :metadata :url])
:accounts (get-in session [:namespaces :eip155 :accounts])
:chains (get-in session [:namespaces :eip155 :chains])
:disconnected false})
(defn filter-operable-accounts
@@ -14,20 +14,17 @@
(rf/reg-event-fx
:wallet-connect/init
(fn [{:keys [db]}]
(let [network-status (:network/status db)
web3-wallet-missing? (-> db :wallet-connect/web3-wallet boolean not)]
(if (and (= network-status :online) web3-wallet-missing?)
(do (log/info "Initialising WalletConnect SDK")
{:fx [[:effects.wallet-connect/init
{:on-success #(rf/dispatch [:wallet-connect/on-init-success %])
:on-fail #(rf/dispatch [:wallet-connect/on-init-fail %])}]]})
(let [network-status (:network/status db)]
(if (= network-status :online)
{:fx [[:effects.wallet-connect/init
{:on-success #(rf/dispatch [:wallet-connect/on-init-success %])
:on-fail #(rf/dispatch [:wallet-connect/on-init-fail %])}]]}
;; NOTE: when offline, fetching persistent sessions only
{:fx [[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))))
(rf/reg-event-fx
:wallet-connect/on-init-success
(fn [{:keys [db]} [web3-wallet]]
(log/info "WalletConnect SDK initialisation successful")
{:db (assoc db :wallet-connect/web3-wallet web3-wallet)
:fx [[:dispatch [:wallet-connect/register-event-listeners]]
[:dispatch [:wallet-connect/fetch-persisted-sessions]]]}))
@@ -35,9 +32,9 @@
(rf/reg-event-fx
:wallet-connect/reload-on-network-change
(fn [{:keys [db]} [is-connected?]]
(let [logged-in? (-> db :profile/profile boolean)]
(when (and is-connected? logged-in?)
(log/info "Re-Initialising WalletConnect SDK due to network change")
(let [logged-in? (-> db :profile/profile boolean)
web3-wallet-missing? (-> db :wallet-connect/web3-wallet boolean not)]
(when (and is-connected? logged-in? web3-wallet-missing?)
{:fx [[:dispatch [:wallet-connect/init]]]}))))
(rf/reg-event-fx
@@ -88,30 +85,23 @@
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch
[:wallet-connect/show-session-networks-unsupported-toast proposal]]
[:dispatch
[:wallet-connect/reject-session-proposal proposal]]]}))))
[:wallet-connect/session-networks-unsupported proposal]]]}))))
(rf/reg-event-fx
:wallet-connect/show-session-networks-unsupported-toast
:wallet-connect/session-networks-unsupported
(fn [{:keys [db]} [proposal]]
(let [{:keys [name url]} (wallet-connect-core/get-session-dapp-metadata proposal)]
(let [{:keys [name]} (wallet-connect-core/get-session-dapp-metadata proposal)]
{:fx [[:dispatch
[:toasts/upsert
{:type :negative
:theme (:theme db)
:text (i18n/label :t/wallet-connect-networks-not-supported
{:dapp (wallet-connect-core/compute-dapp-name name url)})}]]]})))
:text (i18n/label :t/wallet-connect-networks-not-supported {:dapp name})}]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-request
(fn [{:keys [db]} [event]]
(if (wallet-connect-core/event-should-be-handled? db event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]}
{:fx [[:dispatch
[:wallet-connect/send-response
{:error (wallet-connect/get-sdk-error
constants/wallet-connect-user-rejected-chains-error-key)}]]]})))
(when (wallet-connect-core/event-should-be-handled? db event)
{:fx [[:dispatch [:wallet-connect/process-session-request event]]]})))
(rf/reg-event-fx
:wallet-connect/on-session-delete
@@ -174,32 +164,23 @@
current-address (get-in db [:wallet-connect/current-proposal :address])
accounts (-> (partial wallet-connect-core/format-eip155-address current-address)
(map session-networks))
network-status (:network/status db)
expiry (get-in current-proposal [:params :expiryTimestamp])]
network-status (:network/status db)]
(if (= network-status :online)
{:db (assoc-in db [:wallet-connect/current-proposal :response-sent?] true)
:fx [(if (wc-utils/timestamp-expired? expiry)
[:dispatch
[:toasts/upsert
{:id :wallet-connect-proposal-expired
:type :negative
:text (i18n/label :t/wallet-connect-proposal-expired)}]]
[:effects.wallet-connect/approve-session
{:web3-wallet web3-wallet
:proposal current-proposal
:networks session-networks
:accounts accounts
:on-success (fn [approved-session]
(log/info "Wallet Connect session approved")
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
(rf/dispatch [:wallet-connect/persist-session
approved-session]))
:on-fail (fn [error]
(log/error "Wallet Connect session approval failed"
{:error error
:event :wallet-connect/approve-session})
(rf/dispatch
[:wallet-connect/reset-current-session-proposal]))}])
{:fx [[:effects.wallet-connect/approve-session
{:web3-wallet web3-wallet
:proposal current-proposal
:networks session-networks
:accounts accounts
:on-success (fn [approved-session]
(log/info "Wallet Connect session approved")
(rf/dispatch [:wallet-connect/reset-current-session-proposal])
(rf/dispatch [:wallet-connect/persist-session approved-session]))
:on-fail (fn [error]
(log/error "Wallet Connect session approval failed"
{:error error
:event :wallet-connect/approve-session})
(rf/dispatch
[:wallet-connect/reset-current-session-proposal]))}]
[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
@@ -233,10 +214,7 @@
(not version-supported?)
(i18n/label :t/wallet-connect-version-not-supported
{:version version})
:else
(i18n/label :t/something-went-wrong))}]]]}
{:version version}))}]]]}
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
;; We first load sessions from database, then we initiate a call to Wallet Connect SDK and
@@ -1,23 +1,10 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.style
(:require [quo.foundations.typography :as typography]))
(def ^:private line-height (:line-height typography/heading-1))
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.style)
(def header-container
{:padding-vertical 12
:justify-content :flex-start
:align-items :center
:flex-direction :row
:flex-wrap :wrap
:row-gap 2})
{:padding-vertical 12})
(def word-container
{:height line-height
:justify-content :center})
(def header-dapp-name
{:margin-top -4})
(def dapp-container
{:margin-top 0
:height line-height})
(def account-container
{:height line-height})
(def header-account-name
{:padding-top 4})
@@ -1,31 +1,30 @@
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.view
(:require [clojure.string :as string]
[quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.wallet.wallet-connect.core :as core]
[status-im.contexts.wallet.wallet-connect.modals.common.header.style :as style]))
(:require
[quo.core :as quo]
[react-native.core :as rn]
[status-im.contexts.wallet.wallet-connect.core :as core]
[status-im.contexts.wallet.wallet-connect.modals.common.header.style :as style]
[utils.string]))
(defn view
[{:keys [label dapp account]}]
[rn/view {:style style/header-container}
(let [{:keys [name iconUrl url]} dapp
image-source (core/compute-dapp-icon-path iconUrl url)]
[rn/view {:style style/dapp-container}
[quo/summary-tag
{:type :dapp
:label name
:image-source image-source}]])
(for [word (string/split label #" ")]
^{:key word}
[rn/view {:style style/word-container}
[quo/text
{:size :heading-1
:weight :semi-bold}
(str " " word)]])
(let [{:keys [emoji customization-color name]} account]
[rn/view {:style style/account-container}
[quo/summary-tag
{:type :account
:emoji emoji
:label name
:customization-color customization-color}]])])
[rn/view
{:style style/header-container}
[quo/text
{:size :heading-1
:weight :semi-bold}
(let [{:keys [name iconUrl url]} dapp
image-source (core/compute-dapp-icon-path iconUrl url)]
[rn/view {:style style/header-dapp-name}
[quo/summary-tag
{:type :dapp
:label name
:image-source image-source}]])
(str " " label " ")
(let [{:keys [emoji customization-color name]} account]
[rn/view {:style style/header-account-name}
[quo/summary-tag
{:type :account
:emoji emoji
:label name
:customization-color customization-color}]])]])
@@ -7,5 +7,6 @@
[quo/page-nav
{:icon-name :i/close
:background :blur
:on-press #(rf/dispatch [:wallet-connect/dismiss-request-modal])
:on-press #(do (rf/dispatch [:wallet-connect/dismiss-request-modal])
(rf/dispatch [:wallet-connect/reject-session-request]))
:accessibility-label accessibility-label}])
@@ -22,7 +22,6 @@
network (rf/sub [:wallet-connect/current-request-network])
{:keys [max-fees-fiat-formatted
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
(rn/use-unmount #(rf/dispatch [:wallet-connect/on-request-modal-dismissed]))
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[page-nav/view
@@ -18,7 +18,6 @@
{:keys [customization-color]
:as account} (rf/sub [:wallet-connect/current-request-account-details])
dapp (rf/sub [:wallet-connect/current-request-dapp])]
(rn/use-unmount #(rf/dispatch [:wallet-connect/on-request-modal-dismissed]))
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[page-nav/view
@@ -21,7 +21,6 @@
network (rf/sub [:wallet-connect/current-request-network])
{:keys [max-fees-fiat-formatted
error-state]} (rf/sub [:wallet-connect/current-request-transaction-information])]
(rn/use-unmount #(rf/dispatch [:wallet-connect/on-request-modal-dismissed]))
[rn/view {:style (style/container bottom)}
[quo/gradient-cover {:customization-color customization-color}]
[page-nav/view

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