Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
387d3818c5 | ||
|
|
849330dfc1 | ||
|
|
737d8c4d53 | ||
|
|
3aa7e103f7 | ||
|
|
c1d2d44da4 | ||
|
|
0fed8113d1 | ||
|
|
53c35cb554 | ||
|
|
be82365542 | ||
|
|
eae8a65597 | ||
|
|
fe54a25a3a | ||
|
|
15a4219ef4 | ||
|
|
2ffbdac89e | ||
|
|
402eb8397d | ||
|
|
ff88049a08 | ||
|
|
cee21241d4 | ||
|
|
60ad7c8a29 | ||
|
|
4989c92780 |
@@ -74,7 +74,8 @@
|
||||
;; https://github.com/borkdude/clj-kondo/issues/867
|
||||
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
|
||||
number
|
||||
legacy.status-im.test-helpers/restore-app-db]}
|
||||
legacy.status-im.test-helpers/restore-app-db
|
||||
(cljs.test/is [match-strict?])]}
|
||||
:unresolved-var {:level :error}
|
||||
:unsorted-required-namespaces {:level :error}
|
||||
:unused-alias {:level :warning}
|
||||
|
||||
@@ -711,11 +711,11 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8",
|
||||
"path": "nubank/matcher-combinators/3.9.1/matcher-combinators-3.9.1",
|
||||
"host": "https://repo.clojars.org",
|
||||
"jar": {
|
||||
"sha1": "4c94bd510f0c18a20191e46dd6becedebc640bbd",
|
||||
"sha256": "0wpla2hx0s4mda58ndyd8938zmnz1gyhgfr6pzfphy27xfbvsssl"
|
||||
"sha1": "f0830a112cae8ee931a90d9f39214a0ed4d44150",
|
||||
"sha256": "1rjcgqhms84xmnhs7sqcd3b2dpa37mmzgz2yz33yz2rdb9skl96g"
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ net/cgrand/macrovich/0.2.1/macrovich-0.2.1.jar
|
||||
net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar
|
||||
nrepl/bencode/1.1.0/bencode-1.1.0.jar
|
||||
nrepl/nrepl/1.0.0/nrepl-1.0.0.jar
|
||||
nubank/matcher-combinators/3.8.8/matcher-combinators-3.8.8.jar
|
||||
nubank/matcher-combinators/3.9.1/matcher-combinators-3.9.1.jar
|
||||
org/apache/ant/ant/1.10.11/ant-1.10.11.jar
|
||||
org/apache/ant/ant-launcher/1.10.11/ant-launcher-1.10.11.jar
|
||||
org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
[cider/piggieback "0.4.1"]
|
||||
[org.slf4j/slf4j-nop "2.0.9"]
|
||||
[re-frisk-remote "1.6.0"]
|
||||
[nubank/matcher-combinators "3.8.8"]
|
||||
[nubank/matcher-combinators "3.9.1"]
|
||||
|
||||
;; Use the same version specified in the Nix dependency.
|
||||
[clj-kondo/clj-kondo "2024.03.13"]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(ns legacy.status-im.data-store.communities
|
||||
(:require
|
||||
[clojure.set :as set]
|
||||
[clojure.walk :as walk]
|
||||
[status-im.constants :as constants]))
|
||||
[status-im.constants :as constants]
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(defn <-revealed-accounts-rpc
|
||||
[accounts]
|
||||
@@ -22,19 +22,26 @@
|
||||
(reduce #(assoc %1 (key-fn %2) (<-request-to-join-community-rpc %2)) {} requests))
|
||||
|
||||
(defn <-chats-rpc
|
||||
[chats]
|
||||
(reduce-kv (fn [acc k v]
|
||||
(assoc acc
|
||||
(name k)
|
||||
(-> v
|
||||
(assoc :token-gated? (:tokenGated v)
|
||||
:can-post? (:canPost v)
|
||||
:can-view? (:canView v)
|
||||
:hide-if-permissions-not-met? (:hideIfPermissionsNotMet v))
|
||||
(dissoc :canPost :tokenGated :canView :hideIfPermissionsNotMet)
|
||||
(update :members walk/stringify-keys))))
|
||||
{}
|
||||
chats))
|
||||
"This transformation from RPC is optimized differently because there can be
|
||||
thousands of members in all chats and we don't want to transform them from JS
|
||||
to CLJS because they will only be used to list community members or community
|
||||
chat members."
|
||||
[chats-js]
|
||||
(let [chat-key-fn (fn [k]
|
||||
(case k
|
||||
"tokenGated" :token-gated?
|
||||
"canPost" :can-post?
|
||||
"can-view" :can-view?
|
||||
"hideIfPermissionsNotMet" :hide-if-permissions-not-met?
|
||||
(keyword k)))
|
||||
chat-val-fn (fn [k v]
|
||||
(if (= "members" k)
|
||||
v
|
||||
(transforms/js->clj v)))]
|
||||
(transforms/<-js-map
|
||||
chats-js
|
||||
{:val-fn (fn [_ v]
|
||||
(transforms/<-js-map v {:key-fn chat-key-fn :val-fn chat-val-fn}))})))
|
||||
|
||||
(defn <-categories-rpc
|
||||
[categ]
|
||||
@@ -48,49 +55,59 @@
|
||||
[token-permission]
|
||||
(= (:type token-permission) constants/community-token-permission-become-member))
|
||||
|
||||
(defn- rename-community-key
|
||||
[k]
|
||||
(case k
|
||||
"canRequestAccess" :can-request-access?
|
||||
"canManageUsers" :can-manage-users?
|
||||
"canDeleteMessageForEveryone" :can-delete-message-for-everyone?
|
||||
;; This flag is misleading based on its name alone
|
||||
;; because it should not be used to decide if the user
|
||||
;; is *allowed* to join. Allowance is based on token
|
||||
;; permissions. Still, the flag can be used to know
|
||||
;; whether or not the user will have to wait until an
|
||||
;; admin approves a join request.
|
||||
"canJoin" :can-join?
|
||||
"requestedToJoinAt" :requested-to-join-at
|
||||
"isMember" :is-member?
|
||||
"outroMessage" :outro-message
|
||||
"adminSettings" :admin-settings
|
||||
"tokenPermissions" :token-permissions
|
||||
"communityTokensMetadata" :tokens-metadata
|
||||
"introMessage" :intro-message
|
||||
"muteTill" :muted-till
|
||||
"lastOpenedAt" :last-opened-at
|
||||
"joinedAt" :joined-at
|
||||
(keyword k)))
|
||||
|
||||
(defn <-rpc
|
||||
[c]
|
||||
(-> c
|
||||
(set/rename-keys
|
||||
{:canRequestAccess :can-request-access?
|
||||
:canManageUsers :can-manage-users?
|
||||
:canDeleteMessageForEveryone :can-delete-message-for-everyone?
|
||||
;; This flag is misleading based on its name alone
|
||||
;; because it should not be used to decide if the user
|
||||
;; is *allowed* to join. Allowance is based on token
|
||||
;; permissions. Still, the flag can be used to know
|
||||
;; whether or not the user will have to wait until an
|
||||
;; admin approves a join request.
|
||||
:canJoin :can-join?
|
||||
:requestedToJoinAt :requested-to-join-at
|
||||
:isMember :is-member?
|
||||
:outroMessage :outro-message
|
||||
:adminSettings :admin-settings
|
||||
:tokenPermissions :token-permissions
|
||||
:communityTokensMetadata :tokens-metadata
|
||||
:introMessage :intro-message
|
||||
:muteTill :muted-till
|
||||
:lastOpenedAt :last-opened-at
|
||||
:joinedAt :joined-at})
|
||||
(update :admin-settings
|
||||
set/rename-keys
|
||||
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
|
||||
(update :members walk/stringify-keys)
|
||||
(update :chats <-chats-rpc)
|
||||
(update :token-permissions seq)
|
||||
(update :categories <-categories-rpc)
|
||||
(assoc :role-permissions?
|
||||
(->> c
|
||||
:tokenPermissions
|
||||
vals
|
||||
(some role-permission?)))
|
||||
(assoc :membership-permissions?
|
||||
(->> c
|
||||
:tokenPermissions
|
||||
vals
|
||||
(some membership-permission?)))
|
||||
(assoc :token-images
|
||||
(reduce (fn [acc {sym :symbol image :image}]
|
||||
(assoc acc sym image))
|
||||
{}
|
||||
(:communityTokensMetadata c)))))
|
||||
[c-js]
|
||||
(let [community (transforms/<-js-map
|
||||
c-js
|
||||
{:key-fn rename-community-key
|
||||
:val-fn (fn [k v]
|
||||
(case k
|
||||
"members" v
|
||||
"chats" (<-chats-rpc v)
|
||||
(transforms/js->clj v)))})]
|
||||
(-> community
|
||||
(update :admin-settings
|
||||
set/rename-keys
|
||||
{:pinMessageAllMembersEnabled :pin-message-all-members-enabled?})
|
||||
(update :token-permissions seq)
|
||||
(update :categories <-categories-rpc)
|
||||
(assoc :role-permissions?
|
||||
(->> community
|
||||
:tokenPermissions
|
||||
vals
|
||||
(some role-permission?)))
|
||||
(assoc :membership-permissions?
|
||||
(->> community
|
||||
:tokenPermissions
|
||||
vals
|
||||
(some membership-permission?)))
|
||||
(assoc :token-images
|
||||
(reduce (fn [acc {sym :symbol image :image}]
|
||||
(assoc acc sym image))
|
||||
{}
|
||||
(:communityTokensMetadata community))))))
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
legacy.status-im.multiaccounts.logout.core
|
||||
[legacy.status-im.multiaccounts.model :as multiaccounts.model]
|
||||
legacy.status-im.multiaccounts.update.core
|
||||
legacy.status-im.network.net-info
|
||||
legacy.status-im.pairing.core
|
||||
legacy.status-im.profile.core
|
||||
legacy.status-im.search.core
|
||||
|
||||
@@ -13,15 +13,18 @@
|
||||
(native-module/logout)))
|
||||
|
||||
(rf/defn initialize-app-db
|
||||
[{{:keys [keycard initials-avatar-font-file biometrics]
|
||||
:network/keys [type]}
|
||||
[{{:keys [keycard initials-avatar-font-file biometrics]
|
||||
:network/keys [type status]
|
||||
:wallet-connect/keys [web3-wallet]}
|
||||
:db}]
|
||||
{:db (assoc db/app-db
|
||||
:network/type type
|
||||
:initials-avatar-font-file initials-avatar-font-file
|
||||
:keycard (dissoc keycard :secrets :pin :application-info)
|
||||
:biometrics biometrics
|
||||
:syncing nil)})
|
||||
: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)})
|
||||
|
||||
(rf/defn logout-method
|
||||
{:events [::logout-method]}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
(ns legacy.status-im.network.net-info
|
||||
(:require
|
||||
["@react-native-community/netinfo" :default net-info]
|
||||
[native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/defn change-network-status
|
||||
[{:keys [db] :as cofx} is-connected?]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :network-status (if is-connected? :online :offline))}))
|
||||
|
||||
(rf/defn change-network-type
|
||||
[{:keys [db] :as cofx} network-type expensive?]
|
||||
(rf/merge cofx
|
||||
{:db (assoc db :network/type network-type)
|
||||
:network/notify-status-go [network-type expensive?]
|
||||
:dispatch [:mobile-network/on-network-status-change]}))
|
||||
|
||||
(rf/defn handle-network-info-change
|
||||
{:events [::network-info-changed]}
|
||||
[{:keys [db] :as cofx} {:keys [isConnected type details] :as state}]
|
||||
(let [old-network-status (:network-status db)
|
||||
old-network-type (:network/type db)
|
||||
connectivity-status (if isConnected :online :offline)
|
||||
status-changed? (= connectivity-status old-network-status)
|
||||
type-changed? (= type old-network-type)]
|
||||
(log/debug "[net-info]"
|
||||
"old-network-status" old-network-status
|
||||
"old-network-type" old-network-type
|
||||
"connectivity-status" connectivity-status
|
||||
"type" type
|
||||
"details" details)
|
||||
(rf/merge cofx
|
||||
(when-not status-changed?
|
||||
(change-network-status isConnected))
|
||||
(when-not type-changed?
|
||||
(change-network-type type (:is-connection-expensive details))))))
|
||||
|
||||
(defn add-net-info-listener
|
||||
[]
|
||||
(when net-info
|
||||
(.addEventListener ^js net-info
|
||||
#(re-frame/dispatch [::network-info-changed
|
||||
(js->clj % :keywordize-keys true)]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:network/listen-to-network-info
|
||||
(fn []
|
||||
(add-net-info-listener)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:network/notify-status-go
|
||||
(fn [[network-type expensive?]]
|
||||
(native-module/connection-change network-type expensive?)))
|
||||
@@ -15,8 +15,6 @@
|
||||
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
|
||||
(reg-root-key-sub :fleets/custom-fleets :custom-fleets)
|
||||
(reg-root-key-sub :ui/search :ui/search)
|
||||
(reg-root-key-sub :network/type :network/type)
|
||||
(reg-root-key-sub :network-status :network-status)
|
||||
(reg-root-key-sub :peer-stats/count :peer-stats/count)
|
||||
(reg-root-key-sub :peers-summary :peers-summary)
|
||||
(reg-root-key-sub :web3-node-version :web3-node-version)
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
light-client-enabled?
|
||||
store-confirmations-enabled?
|
||||
current-fleet
|
||||
test-networks-enabled?
|
||||
is-goerli-enabled?
|
||||
peer-syncing-enabled?]}]
|
||||
(keep
|
||||
identity
|
||||
@@ -87,22 +85,6 @@
|
||||
[:wakuv2.ui/toggle-store-confirmations (not store-confirmations-enabled?)])
|
||||
:accessory :switch
|
||||
:active store-confirmations-enabled?}
|
||||
{:size :small
|
||||
:title "Testnet mode"
|
||||
:accessibility-label :test-networks-enabled
|
||||
:container-margin-bottom 8
|
||||
:on-press
|
||||
#(re-frame/dispatch [:profile.settings/toggle-test-networks])
|
||||
:accessory :switch
|
||||
:active test-networks-enabled?}
|
||||
{:size :small
|
||||
:title "Enable Goerli as test network"
|
||||
:accessibility-label :enable-sepolia-as-test-network
|
||||
:container-margin-bottom 8
|
||||
:on-press
|
||||
#(re-frame/dispatch [:profile.settings/toggle-goerli-test-network])
|
||||
:accessory :switch
|
||||
:active is-goerli-enabled?}
|
||||
{:size :small
|
||||
:title "Peer syncing"
|
||||
:accessibility-label :peer-syncing
|
||||
@@ -124,9 +106,7 @@
|
||||
|
||||
(views/defview advanced-settings
|
||||
[]
|
||||
(views/letsubs [test-networks-enabled? [:profile/test-networks-enabled?]
|
||||
is-goerli-enabled? [:profile/is-goerli-enabled?]
|
||||
light-client-enabled? [:profile/light-client-enabled?]
|
||||
(views/letsubs [light-client-enabled? [:profile/light-client-enabled?]
|
||||
store-confirmations-enabled? [:profile/store-confirmations-enabled?]
|
||||
telemetry-enabled? [:profile/telemetry-enabled?]
|
||||
current-log-level [:log-level/current-log-level]
|
||||
@@ -147,8 +127,6 @@
|
||||
:store-confirmations-enabled? store-confirmations-enabled?
|
||||
:current-fleet current-fleet
|
||||
:dev-mode? false
|
||||
:test-networks-enabled? test-networks-enabled?
|
||||
:is-goerli-enabled? is-goerli-enabled?
|
||||
:peer-syncing-enabled? peer-syncing-enabled?})
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn render-item}]]))
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
(when (and can-manage-users? (= constants/community-on-request-access (:access permissions)))
|
||||
[requests-to-join community-id])
|
||||
[rn/flat-list
|
||||
{:data (keys sorted-members)
|
||||
{:data sorted-members
|
||||
:render-data {:community-id community-id
|
||||
:my-public-key my-public-key
|
||||
:can-kick-users? (and can-manage-users?
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
[:app-state
|
||||
:current-chat-id
|
||||
:network
|
||||
:network-status
|
||||
:network/status
|
||||
:peers-summary
|
||||
:sync-state
|
||||
:view-id
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
#js
|
||||
{:getEnforcing {}})
|
||||
|
||||
(def net-info #js {})
|
||||
(def net-info #js {:addEventListener identity})
|
||||
(def react-native-biometrics #js {:default {}})
|
||||
(def react-native-static-safe-area-insets #js {:default {}})
|
||||
|
||||
|
||||
@@ -332,7 +332,9 @@
|
||||
(defn set-blank-preview-flag
|
||||
[flag]
|
||||
(log/debug "[native-module] set-blank-preview-flag")
|
||||
(.setBlankPreviewFlag ^js (encryption) flag))
|
||||
;; Sometimes the app crashes during logout because `flag` is nil.
|
||||
(when flag
|
||||
(.setBlankPreviewFlag ^js (encryption) flag)))
|
||||
|
||||
(defn get-device-model-info
|
||||
[]
|
||||
|
||||
@@ -65,9 +65,8 @@
|
||||
:style (style/container loading? theme size)}
|
||||
[loading-view theme]]
|
||||
[linear-gradient/linear-gradient
|
||||
(assoc {:style (style/container loading? theme size)}
|
||||
:colors
|
||||
(linear-gradient-props theme customization-color))
|
||||
{:style (style/container loading? theme size)
|
||||
:colors (linear-gradient-props theme customization-color)}
|
||||
[rn/pressable
|
||||
{:accessibility-label :internal-link-card
|
||||
:on-press on-press}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
(defn main
|
||||
[{:keys [type customization-color]} theme]
|
||||
{:justify-content :center
|
||||
{:justify-content :flex-start
|
||||
:align-items :center
|
||||
:height 32
|
||||
:padding-left 4
|
||||
@@ -16,6 +16,7 @@
|
||||
(defn label
|
||||
[type theme]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white theme)
|
||||
:flex-shrink 1
|
||||
:margin-left (if (= type :address) 6 4)})
|
||||
|
||||
(def collectible-image
|
||||
|
||||
@@ -58,16 +58,19 @@
|
||||
- :emoji - string - emoji used for displaying account avatar
|
||||
- :image-source - resource - image to display on :network, :collectible and :user
|
||||
- :theme - :light / :dark"
|
||||
[{:keys [label customization-color type]
|
||||
[{:keys [label customization-color type container-style]
|
||||
:as props
|
||||
:or {customization-color colors/neutral-80-opa-5}}]
|
||||
(let [theme (quo.theme/use-theme)]
|
||||
[rn/view
|
||||
{:accessibility-label :container
|
||||
:style (style/main (assoc props :customization-color customization-color) theme)}
|
||||
:style (merge (style/main (assoc props :customization-color customization-color)
|
||||
theme)
|
||||
container-style)}
|
||||
[left-view props]
|
||||
[text/text
|
||||
{:style (style/label type theme)
|
||||
:weight :semi-bold
|
||||
:size :heading-1}
|
||||
{:style (style/label type theme)
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:size :heading-1}
|
||||
label]]))
|
||||
|
||||
@@ -21,3 +21,8 @@
|
||||
(if blur?
|
||||
(colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70 theme)
|
||||
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
|
||||
|
||||
(def text
|
||||
{:flex 1
|
||||
;; NOTE: assures the ellipses are not cut off when text is too long
|
||||
:padding-right 2})
|
||||
|
||||
@@ -59,7 +59,9 @@
|
||||
[rn/view {:style (merge style/container container-style)}
|
||||
[text/text
|
||||
{:size :heading-1
|
||||
:number-of-lines 1
|
||||
:weight :semi-bold
|
||||
:style style/text
|
||||
:accessibility-label accessibility-label}
|
||||
title]
|
||||
(case right
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(def account-colors
|
||||
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :flamingo :camel :copper])
|
||||
[:blue :yellow :purple :turquoise :magenta :sky :orange :army :pink :camel :copper])
|
||||
|
||||
(defn alpha
|
||||
[value opacity]
|
||||
@@ -44,6 +44,13 @@
|
||||
(alpha light-color light-opacity)
|
||||
(alpha dark-color dark-opacity))))))
|
||||
|
||||
(defn valid-color?
|
||||
[color]
|
||||
(or (keyword? color)
|
||||
(and (string? color)
|
||||
(or (string/starts-with? color "#")
|
||||
(string/starts-with? color "rgb")))))
|
||||
|
||||
|
||||
;;;;Neutral
|
||||
|
||||
@@ -239,7 +246,7 @@
|
||||
60 "#CC6438"}
|
||||
:army {50 "#216266"
|
||||
60 "#1A4E52"}
|
||||
:flamingo {50 "#F66F8F"
|
||||
:pink {50 "#F66F8F"
|
||||
60 "#C55972"}
|
||||
:purple {50 "#7140FD"
|
||||
60 "#5A33CA"}
|
||||
@@ -316,13 +323,14 @@
|
||||
[s]
|
||||
(and (string? s) (string/starts-with? s "#")))
|
||||
|
||||
(def fallback-color (customization :blue))
|
||||
|
||||
(defn- get-from-colors-map
|
||||
[color suffix]
|
||||
(let [color-without-suffix (get colors-map color)
|
||||
resolved-color? (hex-string? color-without-suffix)]
|
||||
(if resolved-color?
|
||||
(let [color-without-suffix (get colors-map color fallback-color)]
|
||||
(if (hex-string? color-without-suffix)
|
||||
color-without-suffix
|
||||
(get-in colors-map [color suffix]))))
|
||||
(get color-without-suffix suffix))))
|
||||
|
||||
(defn- resolve-color*
|
||||
([color theme]
|
||||
@@ -356,11 +364,15 @@
|
||||
([color suffix]
|
||||
(custom-color color suffix nil))
|
||||
([color suffix opacity]
|
||||
(let [hex? (not (keyword? color))
|
||||
resolved-color (cond hex? color
|
||||
(hex-string? (get colors-map color)) (get colors-map color)
|
||||
:else (get-in colors-map
|
||||
[color suffix]))]
|
||||
(let [resolved-color (cond
|
||||
(not (keyword? color))
|
||||
color
|
||||
|
||||
(hex-string? (get colors-map color))
|
||||
(get colors-map color fallback-color)
|
||||
|
||||
:else
|
||||
(get-in colors-map [color suffix] (get fallback-color suffix)))]
|
||||
(if opacity
|
||||
(alpha resolved-color (/ opacity 100))
|
||||
resolved-color))))))
|
||||
|
||||
@@ -1,6 +1,39 @@
|
||||
(ns react-native.linear-gradient
|
||||
(:require
|
||||
["react-native-linear-gradient" :default LinearGradient]
|
||||
[reagent.core :as reagent]))
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def linear-gradient (reagent/adapt-react-class LinearGradient))
|
||||
(def ^:private linear-gradient* (reagent/adapt-react-class LinearGradient))
|
||||
|
||||
(defn- split-valid-colors
|
||||
[acc idx color]
|
||||
(let [color? (colors/valid-color? color)]
|
||||
(cond-> acc
|
||||
:always (update :safe-colors conj (if color? color "transparent"))
|
||||
(not color?) (update :wrong-colors conj [idx color]))))
|
||||
|
||||
(defn- wrong-colors-str
|
||||
[colors]
|
||||
(reduce-kv (fn [s idx color]
|
||||
(str s "Index: " idx ", color: " (prn-str color)))
|
||||
"Invalid color values in vector passed to Linear Gradient:\n"
|
||||
colors))
|
||||
|
||||
(defn linear-gradient
|
||||
[props & children]
|
||||
(when ^boolean js/goog.DEBUG
|
||||
(assert (vector? (:colors props))))
|
||||
(let [{:keys [wrong-colors safe-colors]} (rn/use-memo
|
||||
(fn []
|
||||
(reduce-kv split-valid-colors
|
||||
{:safe-colors []
|
||||
:wrong-colors {}}
|
||||
(:colors props)))
|
||||
[(:colors props)])]
|
||||
(when (seq wrong-colors)
|
||||
(log/error (wrong-colors-str wrong-colors)))
|
||||
(into [linear-gradient* (assoc props :colors safe-colors)]
|
||||
children)))
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
(oops/ocall wc-utils
|
||||
"buildApprovedNamespaces"
|
||||
(bean/->js {:proposal proposal
|
||||
:supportedNamespaces supported-namespaces})))
|
||||
:supportedNamespaces (clj->js supported-namespaces)})))
|
||||
|
||||
;; Get an error from this list:
|
||||
;; https://github.com/WalletConnect/walletconnect-monorepo/blob/c6e9529418a0c81d4efcc6ac4e61f242a50b56c5/packages/utils/src/errors.ts
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
(ns status-im.common.raw-data-block.view
|
||||
(:require [quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.common.raw-data-block.style :as style]))
|
||||
|
||||
(defn view
|
||||
[data]
|
||||
[rn/scroll-view
|
||||
{:style style/container
|
||||
:content-container-style style/content}
|
||||
[gesture/scroll-view
|
||||
{:style style/container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style style/content
|
||||
:weight :code}
|
||||
data]])
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
(ns status-im.contexts.chat.messenger.messages.link-preview.events
|
||||
(:require [camel-snake-kebab.core :as csk]
|
||||
[status-im.common.json-rpc.events :as json-rpc]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.collection]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -35,17 +33,6 @@
|
||||
{:fx [[:dispatch
|
||||
[:profile.settings/profile-update :link-preview-request-enabled (boolean enabled?)]]]}))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/link-preview-whitelist-received
|
||||
(fn [{:keys [db]} [whitelist]]
|
||||
{:db (assoc db :link-previews-whitelist whitelist)}))
|
||||
|
||||
(rf/reg-fx :chat.ui/request-link-preview-whitelist
|
||||
(fn []
|
||||
(json-rpc/call {:method "wakuext_getLinkPreviewWhitelist"
|
||||
:params []
|
||||
:on-success [:chat.ui/link-preview-whitelist-received]
|
||||
:on-error #(log/error "Failed to get link preview whitelist")})))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/enable-link-previews
|
||||
(fn [{{:profile/keys [profile]} :db} [site enabled?]]
|
||||
(let [enabled-sites (if enabled?
|
||||
|
||||
@@ -103,11 +103,11 @@
|
||||
(models.contact/process-js-contacts cofx response-js)
|
||||
|
||||
(seq communities)
|
||||
(let [communities-clj (types/js->clj communities)]
|
||||
(do
|
||||
(js-delete response-js "communities")
|
||||
(rf/merge cofx
|
||||
(process-next response-js sync-handler)
|
||||
(communities/handle-communities communities-clj)))
|
||||
(communities/handle-communities communities)))
|
||||
|
||||
(seq bookmarks)
|
||||
(let [bookmarks-clj (types/js->clj bookmarks)]
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"0xD" {:address "0xD"
|
||||
:operable? false
|
||||
:position 3
|
||||
:color :flamingo
|
||||
:color :pink
|
||||
: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-without-watched-accounts]))
|
||||
wallet-accounts-count (count (rf/sub [:wallet/operable-accounts]))
|
||||
addresses-shared-text (if (= revealed-accounts-count wallet-accounts-count)
|
||||
(i18n/label :t/all-addresses)
|
||||
(i18n/label-pluralize
|
||||
|
||||
@@ -57,19 +57,24 @@
|
||||
:index index})
|
||||
|
||||
(defn- members
|
||||
[items theme]
|
||||
[rn/section-list
|
||||
{:key-fn :public-key
|
||||
:content-container-style {:padding-bottom 20}
|
||||
:get-item-layout get-item-layout
|
||||
:content-inset-adjustment-behavior :never
|
||||
:sections items
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn contact-list/contacts-section-header
|
||||
:render-section-footer-fn footer
|
||||
:render-data {:theme theme}
|
||||
:render-fn contact-item
|
||||
:scroll-event-throttle 32}])
|
||||
[community-id chat-id theme]
|
||||
(let [online-members (rf/sub [:communities/chat-members-sorted community-id chat-id :online])
|
||||
offline-members (rf/sub [:communities/chat-members-sorted community-id chat-id :offline])]
|
||||
[rn/section-list
|
||||
{:key-fn :public-key
|
||||
:content-container-style {:padding-bottom 20}
|
||||
:get-item-layout get-item-layout
|
||||
:content-inset-adjustment-behavior :never
|
||||
:sections [{:title (i18n/label :t/online)
|
||||
:data online-members}
|
||||
{:title (i18n/label :t/offline)
|
||||
:data offline-members}]
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn contact-list/contacts-section-header
|
||||
:render-section-footer-fn footer
|
||||
:render-data {:theme theme}
|
||||
:render-fn contact-item
|
||||
:scroll-event-throttle 32}]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
@@ -78,8 +83,6 @@
|
||||
{:keys [description chat-name emoji muted chat-type color]
|
||||
:as chat} (rf/sub [:chats/chat-by-id chat-id])
|
||||
pins-count (rf/sub [:chats/pin-messages-count chat-id])
|
||||
items (rf/sub [:communities/sorted-community-members-section-list
|
||||
community-id chat-id])
|
||||
theme (quo.theme/use-theme)]
|
||||
(rn/use-mount (fn []
|
||||
(rf/dispatch [:pin-message/load-pin-messages chat-id])))
|
||||
@@ -133,4 +136,4 @@
|
||||
(if muted
|
||||
(home.actions/unmute-chat-action chat-id)
|
||||
(home.actions/mute-chat-action chat-id chat-type muted)))}]}]]]
|
||||
[members items theme]]))
|
||||
[members community-id chat-id theme]]))
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
:as item}]
|
||||
(let [user-selected? (rf/sub [:is-contact-selected? public-key])
|
||||
{:keys [id]} (rf/sub [:get-screen-params])
|
||||
community-members-keys (set (keys (rf/sub [:communities/community-members id])))
|
||||
community-members-keys (set (rf/sub [:communities/community-members id]))
|
||||
community-member? (boolean (community-members-keys public-key))
|
||||
on-toggle (fn []
|
||||
(when-not community-member?
|
||||
|
||||
@@ -39,17 +39,6 @@
|
||||
|
||||
(rf/reg-event-fx :communities/handle-community handle-community)
|
||||
|
||||
(schema/=> handle-community
|
||||
[:=>
|
||||
[:catn
|
||||
[:cofx :schema.re-frame/cofx]
|
||||
[:args
|
||||
[:schema [:catn [:community-js map?]]]]]
|
||||
[:maybe
|
||||
[:map
|
||||
[:db [:map [:communities map?]]]
|
||||
[:fx vector?]]]])
|
||||
|
||||
(rf/defn handle-removed-chats
|
||||
[{:keys [db]} chat-ids]
|
||||
{:db (reduce (fn [db chat-id]
|
||||
@@ -84,10 +73,9 @@
|
||||
|
||||
(rf/defn handle-communities
|
||||
{:events [:community/fetch-success]}
|
||||
[{:keys [db]} communities]
|
||||
{:fx
|
||||
(->> communities
|
||||
(map #(vector :dispatch [:communities/handle-community %])))})
|
||||
[{:keys [db]} communities-js]
|
||||
{:fx (map (fn [c] [:dispatch [:communities/handle-community c]])
|
||||
communities-js)})
|
||||
|
||||
(rf/reg-event-fx :communities/request-to-join-result
|
||||
(fn [{:keys [db]} [community-id request-id response-js]]
|
||||
@@ -136,21 +124,30 @@
|
||||
{}
|
||||
categories))}))
|
||||
|
||||
(rf/reg-event-fx :community/fetch-low-priority
|
||||
(fn []
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_checkAndDeletePendingRequestToJoinCommunity"
|
||||
:params []
|
||||
:js-response true
|
||||
:on-success [:sanitize-messages-and-process-response]
|
||||
:on-error #(log/info "failed to fetch communities" %)}
|
||||
{:method "wakuext_collapsedCommunityCategories"
|
||||
:params []
|
||||
:on-success [:communities/fetched-collapsed-categories-success]
|
||||
:on-error #(log/error "failed to fetch collapsed community categories" %)}]]]}))
|
||||
|
||||
(rf/reg-event-fx :community/fetch
|
||||
(fn [_]
|
||||
{:json-rpc/call [{:method "wakuext_serializedCommunities"
|
||||
:params []
|
||||
:on-success #(rf/dispatch [:community/fetch-success %])
|
||||
:on-error #(log/error "failed to fetch communities" %)}
|
||||
{:method "wakuext_checkAndDeletePendingRequestToJoinCommunity"
|
||||
:params []
|
||||
:js-response true
|
||||
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])
|
||||
:on-error #(log/info "failed to fetch communities" %)}
|
||||
{:method "wakuext_collapsedCommunityCategories"
|
||||
:params []
|
||||
:on-success #(rf/dispatch [:communities/fetched-collapsed-categories-success %])
|
||||
:on-error #(log/error "failed to fetch collapsed community categories" %)}]}))
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_serializedCommunities"
|
||||
:params []
|
||||
:on-success [:community/fetch-success]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to fetch communities" %)}]]
|
||||
;; Dispatch a little after 1000ms because other higher-priority events
|
||||
;; after login are being processed at the 1000ms mark.
|
||||
[:dispatch-later [{:ms 1200 :dispatch [:community/fetch-low-priority]}]]]}))
|
||||
|
||||
(defn update-previous-permission-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
(-> effects :json-rpc/call first (select-keys [:method :params]))))))))
|
||||
|
||||
(deftest handle-community-test
|
||||
(let [community {:id community-id :clock 2}]
|
||||
(let [community #js {:id community-id :clock 2}]
|
||||
(testing "given a unjoined community"
|
||||
(let [effects (events/handle-community {} [community])]
|
||||
(is (match? community-id
|
||||
@@ -163,7 +163,7 @@
|
||||
(filter some? (:fx effects))))))
|
||||
|
||||
(testing "given a joined community"
|
||||
(let [community (assoc community :joined true)
|
||||
(let [community #js {:id community-id :clock 2 :joined true}
|
||||
effects (events/handle-community {} [community])]
|
||||
(is (match?
|
||||
[[:dispatch
|
||||
@@ -172,16 +172,19 @@
|
||||
(filter some? (:fx effects))))))
|
||||
|
||||
(testing "given a community with token-permissions-check"
|
||||
(let [community (assoc community :token-permissions-check :fake-token-permissions-check)
|
||||
(let [community #js
|
||||
{:id community-id :clock 2 :token-permissions-check :fake-token-permissions-check}
|
||||
effects (events/handle-community {} [community])]
|
||||
(is (match?
|
||||
[[:dispatch
|
||||
[:communities/check-permissions-to-join-community-with-all-addresses community-id]]]
|
||||
(filter some? (:fx effects))))))
|
||||
|
||||
(testing "given a community with lower clock"
|
||||
(let [effects (events/handle-community {:db {:communities {community-id {:clock 3}}}} [community])]
|
||||
(is (nil? effects))))
|
||||
|
||||
(testing "given a community without clock"
|
||||
(let [community (dissoc community :clock)
|
||||
(let [community #js {:id community-id}
|
||||
effects (events/handle-community {} [community])]
|
||||
(is (nil? effects))))))
|
||||
|
||||
@@ -75,46 +75,51 @@
|
||||
:banner (resources/get-image :discover)
|
||||
:accessibility-label :communities-home-discover-card}})
|
||||
|
||||
(defn on-tab-change
|
||||
[tab]
|
||||
(rf/dispatch [:communities/select-tab tab]))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [flat-list-ref (atom nil)
|
||||
set-flat-list-ref #(reset! flat-list-ref %)]
|
||||
(fn []
|
||||
(let [theme (quo.theme/use-theme)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
selected-tab (or (rf/sub [:communities/selected-tab]) :joined)
|
||||
{:keys [joined pending opened]} (rf/sub [:communities/grouped-by-status])
|
||||
selected-items (case selected-tab
|
||||
:joined joined
|
||||
:pending pending
|
||||
:opened opened)
|
||||
scroll-shared-value (reanimated/use-shared-value 0)]
|
||||
[:<>
|
||||
(if (empty? selected-items)
|
||||
[common.empty-state/view
|
||||
{:selected-tab selected-tab
|
||||
:tab->content (empty-state-content theme)}]
|
||||
[reanimated/flat-list
|
||||
{:ref set-flat-list-ref
|
||||
:key-fn :id
|
||||
:content-inset-adjustment-behavior :never
|
||||
:header [common.header-spacing/view]
|
||||
:render-fn item-render
|
||||
:style {:margin-top -1}
|
||||
:data selected-items
|
||||
:scroll-event-throttle 8
|
||||
:content-container-style {:padding-bottom
|
||||
jump-to.constants/floating-shell-button-height}
|
||||
:on-scroll #(common.banner/set-scroll-shared-value
|
||||
{:scroll-input (oops/oget
|
||||
%
|
||||
"nativeEvent.contentOffset.y")
|
||||
:shared-value scroll-shared-value})}])
|
||||
[:f> common.banner/animated-banner
|
||||
{:content banner-data
|
||||
:customization-color customization-color
|
||||
:scroll-ref flat-list-ref
|
||||
:tabs tabs-data
|
||||
:selected-tab selected-tab
|
||||
:on-tab-change (fn [tab] (rf/dispatch [:communities/select-tab tab]))
|
||||
:scroll-shared-value scroll-shared-value}]]))))
|
||||
(let [flat-list-ref (rn/use-ref-atom nil)
|
||||
set-flat-list-ref (rn/use-callback #(reset! flat-list-ref %))
|
||||
theme (quo.theme/use-theme)
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
selected-tab (or (rf/sub [:communities/selected-tab]) :joined)
|
||||
{:keys [joined pending opened]} (rf/sub [:communities/grouped-by-status])
|
||||
selected-items (case selected-tab
|
||||
:joined joined
|
||||
:pending pending
|
||||
:opened opened)
|
||||
scroll-shared-value (reanimated/use-shared-value 0)
|
||||
on-scroll (rn/use-callback
|
||||
(fn [event]
|
||||
(common.banner/set-scroll-shared-value
|
||||
{:scroll-input (oops/oget event
|
||||
"nativeEvent.contentOffset.y")
|
||||
:shared-value scroll-shared-value})))]
|
||||
[:<>
|
||||
(if (empty? selected-items)
|
||||
[common.empty-state/view
|
||||
{:selected-tab selected-tab
|
||||
:tab->content (empty-state-content theme)}]
|
||||
[reanimated/flat-list
|
||||
{:ref set-flat-list-ref
|
||||
:key-fn :id
|
||||
:content-inset-adjustment-behavior :never
|
||||
:header [common.header-spacing/view]
|
||||
:render-fn item-render
|
||||
:style {:margin-top -1}
|
||||
:data selected-items
|
||||
:scroll-event-throttle 8
|
||||
:content-container-style {:padding-bottom
|
||||
jump-to.constants/floating-shell-button-height}
|
||||
:on-scroll on-scroll}])
|
||||
[common.banner/animated-banner
|
||||
{:content banner-data
|
||||
:customization-color customization-color
|
||||
:scroll-ref flat-list-ref
|
||||
:tabs tabs-data
|
||||
:selected-tab selected-tab
|
||||
:on-tab-change on-tab-change
|
||||
:scroll-shared-value scroll-shared-value}]]))
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
(ns status-im.contexts.networks.events
|
||||
(:require
|
||||
["@react-native-community/netinfo" :default net-info]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.feature-flags :as ff]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.network/listen-to-network-info
|
||||
(fn []
|
||||
(when net-info
|
||||
(.addEventListener ^js net-info
|
||||
#(rf/dispatch [:network/on-state-change
|
||||
(js->clj % :keywordize-keys true)])))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:network/on-state-change
|
||||
(fn [{:keys [db]} [{:keys [isConnected type details]}]]
|
||||
(let [old-network-status (:network/status db)
|
||||
old-network-type (:network/type db)
|
||||
connectivity-status (if isConnected :online :offline)
|
||||
status-changed? (not= connectivity-status old-network-status)
|
||||
type-changed? (not= type old-network-type)
|
||||
is-connection-expensive? (:is-connection-expensive details)]
|
||||
(log/debug "[net-info]"
|
||||
"old-network-status" old-network-status
|
||||
"old-network-type" old-network-type
|
||||
"connectivity-status" connectivity-status
|
||||
"type" type
|
||||
"details" details)
|
||||
{:fx [(when status-changed?
|
||||
[:dispatch [:network/on-network-status-change isConnected]])
|
||||
(when type-changed?
|
||||
[:dispatch [:network/on-network-type-change type is-connection-expensive?]])]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:network/on-network-type-change
|
||||
(fn [{:keys [db]} [network-type expensive?]]
|
||||
{:db (assoc db :network/type network-type)
|
||||
:fx [[:effects.network/notify-status-go network-type expensive?]
|
||||
[:dispatch [:mobile-network/on-network-status-change]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:network/on-network-status-change
|
||||
(fn [{:keys [db]} [is-connected?]]
|
||||
(let [network-status (if is-connected? :online :offline)]
|
||||
{:db (assoc db :network/status network-status)
|
||||
:fx [(when (ff/enabled? ::ff/wallet.wallet-connect)
|
||||
[:dispatch [:wallet-connect/reload-on-network-change is-connected?]])]})))
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.network/notify-status-go
|
||||
(fn [network-type expensive?]
|
||||
(native-module/connection-change network-type expensive?)))
|
||||
@@ -38,7 +38,7 @@
|
||||
(rf/dispatch [:push-notifications/switch true])
|
||||
(rf/dispatch [:navigate-to-within-stack
|
||||
[:screen/onboarding.welcome
|
||||
:screen/onboarding.generating-keys]]))
|
||||
:screen/onboarding.enable-notifications]]))
|
||||
:type :primary
|
||||
:icon-left :i/notifications
|
||||
:accessibility-label :enable-notifications-button
|
||||
@@ -52,7 +52,7 @@
|
||||
nil)
|
||||
(rf/dispatch [:navigate-to-within-stack
|
||||
[:screen/onboarding.welcome
|
||||
:screen/onboarding.generating-keys]]))
|
||||
:screen/onboarding.enable-notifications]]))
|
||||
:accessibility-label :enable-notifications-later-button
|
||||
:type :grey
|
||||
:background :blur
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(def absolute-fill
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(defn page-container
|
||||
[in-onboarding?]
|
||||
{:flex 1
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
profile-color (:color (rf/sub [:onboarding/profile]))
|
||||
logged-in? (rf/sub [:multiaccount/logged-in?])]
|
||||
[rn/view {:style (style/page-container in-onboarding?)}
|
||||
(when-not in-onboarding? [background/view true])
|
||||
(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 pairing-status)]
|
||||
(if config/show-not-implemented-features?
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(def absolute-fill
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(defn page-container
|
||||
[top]
|
||||
{:flex 1
|
||||
|
||||
@@ -66,7 +66,8 @@
|
||||
translate-x (reanimated/use-shared-value 0)
|
||||
window-width (:width (rn/get-window))]
|
||||
[rn/view {:style (style/page-container top)}
|
||||
[background/view true]
|
||||
[rn/view {:style style/absolute-fill}
|
||||
[background/view true]]
|
||||
[reanimated/view
|
||||
{:style (style/content translate-x)}
|
||||
[page-title]
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
[]
|
||||
(let [state (reagent/atom {:type :default
|
||||
:customization-color :blue
|
||||
:account-color :flamingo
|
||||
:account-color :pink
|
||||
: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 :flamingo
|
||||
{:customization-color :pink
|
||||
:label "Peter Lambo"}
|
||||
:account
|
||||
{:label "Account"
|
||||
|
||||
@@ -57,14 +57,15 @@
|
||||
[{: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]]
|
||||
[:push-notifications/load-preferences]
|
||||
[:profile.config/get-node-config]
|
||||
|
||||
;; 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]}]]
|
||||
|
||||
[: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
|
||||
@@ -90,24 +91,45 @@
|
||||
;; 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
|
||||
preview-privacy?]} (:profile/profile db)]
|
||||
(let [{:keys [notifications-enabled? key-uid]} (:profile/profile db)]
|
||||
{:db db
|
||||
:fx [[:effects.profile/enable-local-notifications]
|
||||
[:contacts/initialize-contacts]
|
||||
[:browser/initialize-browser]
|
||||
;; 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]}]]
|
||||
[: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?)]
|
||||
@@ -119,11 +141,6 @@
|
||||
(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-not new-account?
|
||||
[:dispatch [:universal-links/process-stored-event]])]})))
|
||||
|
||||
@@ -139,11 +156,9 @@
|
||||
(if error
|
||||
{:db (update db :profile/login #(-> % (dissoc :processing) (assoc :error error)))}
|
||||
{:db (dissoc db :profile/login)
|
||||
: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]]
|
||||
: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]}]]
|
||||
[:dispatch [:profile.login/login-existing-profile settings account]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
|
||||
+32
-28
@@ -7,6 +7,7 @@
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.common.floating-button-page.view :as floating-button-page]
|
||||
[status-im.contexts.settings.wallet.saved-addresses.add-address-to-save.style :as style]
|
||||
[status-im.contexts.wallet.common.utils :as utils]
|
||||
[status-im.contexts.wallet.common.validation :as validation]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
@@ -18,20 +19,21 @@
|
||||
|
||||
(defn- validate-input
|
||||
[account-addresses saved-addresses user-input]
|
||||
(cond
|
||||
(string/blank? user-input)
|
||||
nil
|
||||
(let [[_ address-without-prefix] (utils/split-prefix-and-address user-input)]
|
||||
(cond
|
||||
(string/blank? user-input)
|
||||
nil
|
||||
|
||||
(contains? saved-addresses user-input)
|
||||
:existing-saved-address
|
||||
(contains? saved-addresses address-without-prefix)
|
||||
:existing-saved-address
|
||||
|
||||
(contains? account-addresses user-input)
|
||||
:own-account
|
||||
(contains? account-addresses address-without-prefix)
|
||||
:own-account
|
||||
|
||||
(not
|
||||
(or (validation/eth-address? user-input)
|
||||
(validation/ens-name? user-input)))
|
||||
:invalid-address-or-ens))
|
||||
(not
|
||||
(or (validation/eth-address? user-input)
|
||||
(validation/ens-name? user-input)))
|
||||
:invalid-address-or-ens)))
|
||||
|
||||
(defn- address-input
|
||||
[{:keys [input-value on-change-text paste-into-input clear-input]}]
|
||||
@@ -93,8 +95,9 @@
|
||||
|
||||
(defn- existing-saved-address
|
||||
[{:keys [address]}]
|
||||
(let [{:keys [name customization-color chain-short-names ens ens?]}
|
||||
(rf/sub [:wallet/saved-address-by-address address])]
|
||||
(let [[_ address-without-prefix] (utils/split-prefix-and-address address)
|
||||
{:keys [name customization-color chain-short-names ens ens?]}
|
||||
(rf/sub [:wallet/saved-address-by-address address-without-prefix])]
|
||||
[rn/view {:style style/existing-saved-address-container}
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
@@ -105,7 +108,7 @@
|
||||
{:blur? true
|
||||
:active-state? true
|
||||
:user-props {:name name
|
||||
:address (str chain-short-names address)
|
||||
:address (str chain-short-names address-without-prefix)
|
||||
:ens (when ens? ens)
|
||||
:customization-color customization-color
|
||||
:blur? true}
|
||||
@@ -168,20 +171,21 @@
|
||||
(rn/use-mount #(rf/dispatch [:wallet/clear-address-to-save]))
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/close
|
||||
:behind-overlay? true
|
||||
:on-press navigate-back
|
||||
:margin-top (safe-area/get-top)
|
||||
:accessibility-label :add-address-to-save-page-nav}]
|
||||
:footer (when (= view-id :screen/settings.add-address-to-save)
|
||||
[quo/button
|
||||
{:customization-color profile-color
|
||||
:disabled? button-disabled?
|
||||
:on-press on-press-continue}
|
||||
(i18n/label :t/continue)])}
|
||||
{:footer-container-padding 0
|
||||
:keyboard-should-persist-taps :handled
|
||||
:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:icon-name :i/close
|
||||
:behind-overlay? true
|
||||
:on-press navigate-back
|
||||
:margin-top (safe-area/get-top)
|
||||
:accessibility-label :add-address-to-save-page-nav}]
|
||||
:footer (when (= view-id :screen/settings.add-address-to-save)
|
||||
[quo/button
|
||||
{:customization-color profile-color
|
||||
:disabled? button-disabled?
|
||||
:on-press on-press-continue}
|
||||
(i18n/label :t/continue)])}
|
||||
[quo/page-top
|
||||
{:container-style style/header-container
|
||||
:blur? true
|
||||
|
||||
@@ -105,24 +105,25 @@
|
||||
[ens ens? open-network-preferences address-text])]
|
||||
[quo/overlay {:type :shell}
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding (if edit? (+ (safe-area/get-bottom) 12) 0)
|
||||
:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name (if edit? :i/close :i/arrow-left)
|
||||
:on-press navigate-back
|
||||
:margin-top (when-not edit? (safe-area/get-top))
|
||||
:accessibility-label :save-address-page-nav}]
|
||||
:footer [quo/button
|
||||
{:accessibility-label :save-address-button
|
||||
:type :primary
|
||||
:customization-color address-color
|
||||
:disabled? (string/blank? address-label)
|
||||
:on-press on-press-save}
|
||||
(i18n/label :t/save-address)]
|
||||
:customization-color address-color
|
||||
:gradient-cover? true
|
||||
:shell-overlay? true}
|
||||
{:footer-container-padding (if edit? (+ (safe-area/get-bottom) 12) 0)
|
||||
:keyboard-should-persist-taps :handled
|
||||
:header [quo/page-nav
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name (if edit? :i/close :i/arrow-left)
|
||||
:on-press navigate-back
|
||||
:margin-top (when-not edit? (safe-area/get-top))
|
||||
:accessibility-label :save-address-page-nav}]
|
||||
:footer [quo/button
|
||||
{:accessibility-label :save-address-button
|
||||
:type :primary
|
||||
:customization-color address-color
|
||||
:disabled? (string/blank? address-label)
|
||||
:on-press on-press-save}
|
||||
(i18n/label :t/save-address)]
|
||||
:customization-color address-color
|
||||
:gradient-cover? true
|
||||
:shell-overlay? true}
|
||||
[quo/wallet-user-avatar
|
||||
{:full-name (if (string/blank? address-label)
|
||||
placeholder
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
(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]
|
||||
@@ -80,6 +82,10 @@
|
||||
; :network-logo network-logo}
|
||||
; :blur? false}])
|
||||
|
||||
(defn- section-header
|
||||
[{:keys [title]}]
|
||||
[quo/divider-date title])
|
||||
|
||||
(defn activity-item
|
||||
[{:keys [transaction] :as activity}]
|
||||
(case transaction
|
||||
@@ -88,20 +94,63 @@
|
||||
;; :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)
|
||||
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])}])))
|
||||
(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}])]))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.wallet.data-store-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
[matcher-combinators.matchers :as matchers]
|
||||
matcher-combinators.test
|
||||
[status-im.contexts.wallet.data-store :as sut]))
|
||||
|
||||
@@ -162,82 +161,73 @@
|
||||
(deftest reconcile-keypairs-test
|
||||
(testing "reconcile-keypairs represents updated key pairs and accounts"
|
||||
(is
|
||||
(match?
|
||||
(matchers/match-with
|
||||
[set? matchers/set-equals
|
||||
map? matchers/equals]
|
||||
{:removed-keypair-ids #{}
|
||||
:removed-account-addresses #{}
|
||||
:updated-accounts-by-address {"1x123" (merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})
|
||||
"1x456" (merge account
|
||||
{:key-uid "0x456"
|
||||
:address "1x456"
|
||||
:operable? false
|
||||
:operable :no})}
|
||||
:updated-keypairs-by-id {"0x123" {:key-uid "0x123"
|
||||
:type :seed
|
||||
:lowest-operability :fully
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})]}
|
||||
"0x456" {:key-uid "0x456"
|
||||
:type :key
|
||||
:lowest-operability :no
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x456"
|
||||
:address "1x456"
|
||||
:operable? false
|
||||
:operable :no})]}}})
|
||||
(match-strict?
|
||||
{:removed-keypair-ids #{}
|
||||
:removed-account-addresses #{}
|
||||
:updated-accounts-by-address {"1x123" (merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})
|
||||
"1x456" (merge account
|
||||
{:key-uid "0x456"
|
||||
:address "1x456"
|
||||
:operable? false
|
||||
:operable :no})}
|
||||
:updated-keypairs-by-id {"0x123" {:key-uid "0x123"
|
||||
:type :seed
|
||||
:lowest-operability :fully
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})]}
|
||||
"0x456" {:key-uid "0x456"
|
||||
:type :key
|
||||
:lowest-operability :no
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x456"
|
||||
:address "1x456"
|
||||
:operable? false
|
||||
:operable :no})]}}}
|
||||
(sut/reconcile-keypairs [raw-keypair-seed-phrase
|
||||
raw-keypair-private-key]))))
|
||||
(testing "reconcile-keypairs represents removed key pairs and accounts"
|
||||
(is
|
||||
(match?
|
||||
(matchers/match-with
|
||||
[set? matchers/set-equals
|
||||
map? matchers/equals]
|
||||
{:removed-keypair-ids #{"0x456"}
|
||||
:removed-account-addresses #{"1x456"}
|
||||
:updated-accounts-by-address {"1x123" (merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})}
|
||||
:updated-keypairs-by-id {"0x123" {:key-uid "0x123"
|
||||
:type :seed
|
||||
:lowest-operability :fully
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})]}}})
|
||||
(match-strict?
|
||||
{:removed-keypair-ids #{"0x456"}
|
||||
:removed-account-addresses #{"1x456"}
|
||||
:updated-accounts-by-address {"1x123" (merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})}
|
||||
:updated-keypairs-by-id {"0x123" {:key-uid "0x123"
|
||||
:type :seed
|
||||
:lowest-operability :fully
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x123"
|
||||
:address "1x123"})]}}}
|
||||
(sut/reconcile-keypairs [raw-keypair-seed-phrase
|
||||
(assoc raw-keypair-private-key :removed true)]))))
|
||||
(testing "reconcile-keypairs ignores chat accounts inside updated accounts"
|
||||
(is
|
||||
(match?
|
||||
(matchers/match-with
|
||||
[set? matchers/set-equals
|
||||
map? matchers/equals]
|
||||
{:removed-keypair-ids #{}
|
||||
:removed-account-addresses #{}
|
||||
:updated-accounts-by-address {"2x000" (merge account
|
||||
{:key-uid "0x000"
|
||||
:address "2x000"
|
||||
:chat false
|
||||
:wallet true
|
||||
:default-account? true})}
|
||||
:updated-keypairs-by-id {"0x000" {:key-uid "0x000"
|
||||
:type :profile
|
||||
:lowest-operability :fully
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x000"
|
||||
:address "1x000"
|
||||
:chat true
|
||||
:wallet false
|
||||
:default-account? false})
|
||||
(merge account
|
||||
{:key-uid "0x000"
|
||||
:address "2x000"
|
||||
:chat false
|
||||
:wallet true
|
||||
:default-account? true})]}}})
|
||||
(match-strict?
|
||||
{:removed-keypair-ids #{}
|
||||
:removed-account-addresses #{}
|
||||
:updated-accounts-by-address {"2x000" (merge account
|
||||
{:key-uid "0x000"
|
||||
:address "2x000"
|
||||
:chat false
|
||||
:wallet true
|
||||
:default-account? true})}
|
||||
:updated-keypairs-by-id {"0x000" {:key-uid "0x000"
|
||||
:type :profile
|
||||
:lowest-operability :fully
|
||||
:accounts [(merge account
|
||||
{:key-uid "0x000"
|
||||
:address "1x000"
|
||||
:chat true
|
||||
:wallet false
|
||||
:default-account? false})
|
||||
(merge account
|
||||
{:key-uid "0x000"
|
||||
:address "2x000"
|
||||
:chat false
|
||||
:wallet true
|
||||
:default-account? true})]}}}
|
||||
(sut/reconcile-keypairs [raw-keypair-profile])))))
|
||||
|
||||
@@ -50,11 +50,15 @@
|
||||
|
||||
(rf/reg-fx
|
||||
:effects.wallet-connect/approve-session
|
||||
(fn [{:keys [web3-wallet proposal supported-namespaces on-success on-fail]}]
|
||||
(fn [{:keys [web3-wallet proposal networks accounts on-success on-fail]}]
|
||||
(let [{:keys [params id]} proposal
|
||||
approved-namespaces (wallet-connect/build-approved-namespaces
|
||||
params
|
||||
supported-namespaces)]
|
||||
approved-namespaces (->> {:eip155
|
||||
{:chains networks
|
||||
:accounts accounts
|
||||
:methods constants/wallet-connect-supported-methods
|
||||
:events constants/wallet-connect-supported-events}}
|
||||
(wallet-connect/build-approved-namespaces
|
||||
params))]
|
||||
(-> (wallet-connect/approve-session
|
||||
{:web3-wallet web3-wallet
|
||||
:id id
|
||||
|
||||
@@ -13,18 +13,33 @@
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/init
|
||||
(fn []
|
||||
{:fx [[:effects.wallet-connect/init
|
||||
{:on-success #(rf/dispatch [:wallet-connect/on-init-success %])
|
||||
:on-fail #(rf/dispatch [:wallet-connect/on-init-fail %])}]]}))
|
||||
(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 %])}]]})
|
||||
;; 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]]]}))
|
||||
|
||||
(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")
|
||||
{:fx [[:dispatch [:wallet-connect/init]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/register-event-listeners
|
||||
(fn [{:keys [db]}]
|
||||
@@ -64,6 +79,7 @@
|
||||
(if (and (not-empty session-networks) required-networks-supported?)
|
||||
{:db (update db
|
||||
:wallet-connect/current-proposal assoc
|
||||
:response-sent? false
|
||||
:request proposal
|
||||
:session-networks session-networks
|
||||
:address (or current-viewing-address
|
||||
@@ -77,12 +93,12 @@
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/session-networks-unsupported
|
||||
(fn [_ [proposal]]
|
||||
(fn [{:keys [db]} [proposal]]
|
||||
(let [{:keys [name]} (wallet-connect-core/get-session-dapp-metadata proposal)]
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:theme (:theme db)
|
||||
:text (i18n/label :t/wallet-connect-networks-not-supported {:dapp name})}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
@@ -116,17 +132,20 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/disconnect-dapp
|
||||
(fn [{:keys [db]} [{:keys [topic on-success on-fail]}]]
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||
{:fx [[:effects.wallet-connect/disconnect
|
||||
{:web3-wallet web3-wallet
|
||||
:topic topic
|
||||
:reason (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-disconnected-reason-key)
|
||||
:on-fail on-fail
|
||||
:on-success (fn []
|
||||
(rf/dispatch [:wallet-connect/disconnect-session topic])
|
||||
(when on-success
|
||||
(on-success)))}]]})))
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
network-status (:network/status db)]
|
||||
(if (= network-status :online)
|
||||
{:fx [[:effects.wallet-connect/disconnect
|
||||
{:web3-wallet web3-wallet
|
||||
:topic topic
|
||||
:reason (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-disconnected-reason-key)
|
||||
:on-fail on-fail
|
||||
:on-success (fn []
|
||||
(rf/dispatch [:wallet-connect/disconnect-session topic])
|
||||
(when on-success
|
||||
(on-success)))}]]}
|
||||
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/pair
|
||||
@@ -141,51 +160,66 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/approve-session
|
||||
(fn [{:keys [db]}]
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
current-proposal (get-in db [:wallet-connect/current-proposal :request])
|
||||
session-networks (->> (get-in db [:wallet-connect/current-proposal :session-networks])
|
||||
(map wallet-connect-core/chain-id->eip155)
|
||||
vec)
|
||||
current-address (get-in db [:wallet-connect/current-proposal :address])
|
||||
accounts (-> (partial wallet-connect-core/format-eip155-address current-address)
|
||||
(map session-networks))
|
||||
supported-namespaces (clj->js {:eip155
|
||||
{:chains session-networks
|
||||
:methods constants/wallet-connect-supported-methods
|
||||
:events constants/wallet-connect-supported-events
|
||||
:accounts accounts}})]
|
||||
{:fx [[:effects.wallet-connect/approve-session
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal current-proposal
|
||||
:supported-namespaces supported-namespaces
|
||||
: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]]]})))
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
current-proposal (get-in db [:wallet-connect/current-proposal :request])
|
||||
session-networks (->> (get-in db [:wallet-connect/current-proposal :session-networks])
|
||||
(map wallet-connect-core/chain-id->eip155)
|
||||
vec)
|
||||
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])]
|
||||
(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]))}])
|
||||
[:dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]]]}
|
||||
{:fx [[:dispatch [:wallet-connect/no-internet-toast]]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/on-scan-connection
|
||||
(fn [_ [scanned-text]]
|
||||
(let [parsed-uri (wallet-connect/parse-uri scanned-text)
|
||||
(fn [{:keys [db]} [scanned-text]]
|
||||
(let [network-status (:network/status db)
|
||||
parsed-uri (wallet-connect/parse-uri scanned-text)
|
||||
version (:version parsed-uri)
|
||||
valid-wc-uri? (wc-utils/valid-wc-uri? parsed-uri)
|
||||
expired? (-> parsed-uri
|
||||
:expiryTimestamp
|
||||
wc-utils/timestamp-expired?)
|
||||
version-supported? (wc-utils/version-supported? version)]
|
||||
(if (or (not valid-wc-uri?) expired? (not version-supported?))
|
||||
(if (or (not valid-wc-uri?)
|
||||
(not version-supported?)
|
||||
(= network-status :offline)
|
||||
expired?)
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme :dark
|
||||
:text (cond (not valid-wc-uri?)
|
||||
:text (cond (= network-status :offline)
|
||||
(i18n/label :t/wallet-connect-no-internet-warning)
|
||||
|
||||
(not valid-wc-uri?)
|
||||
(i18n/label :t/wallet-connect-wrong-qr)
|
||||
|
||||
expired?
|
||||
@@ -193,7 +227,10 @@
|
||||
|
||||
(not version-supported?)
|
||||
(i18n/label :t/wallet-connect-version-not-supported
|
||||
{:version version}))}]]]}
|
||||
{:version version})
|
||||
|
||||
:else
|
||||
(i18n/label :t/something-went-wrong))}]]]}
|
||||
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
|
||||
|
||||
;; We first load sessions from database, then we initiate a call to Wallet Connect SDK and
|
||||
@@ -236,16 +273,18 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/fetch-persisted-sessions-success
|
||||
(fn [{:keys [db]} [sessions]]
|
||||
(let [sessions' (mapv (fn [{:keys [sessionJson] :as session}]
|
||||
(assoc session
|
||||
:accounts
|
||||
(-> sessionJson
|
||||
types/json->clj
|
||||
:namespaces
|
||||
:eip155
|
||||
:accounts)))
|
||||
sessions)]
|
||||
{:fx [[:dispatch [:wallet-connect/fetch-active-sessions]]]
|
||||
(let [network-status (:network/status db)
|
||||
sessions' (mapv (fn [{:keys [sessionJson] :as session}]
|
||||
(assoc session
|
||||
:accounts
|
||||
(-> sessionJson
|
||||
types/json->clj
|
||||
:namespaces
|
||||
:eip155
|
||||
:accounts)))
|
||||
sessions)]
|
||||
{:fx [(when (= network-status :online)
|
||||
[:dispatch [:wallet-connect/fetch-active-sessions]])]
|
||||
:db (assoc db :wallet-connect/sessions sessions')})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
@@ -256,14 +295,14 @@
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/fetch-persisted-sessions
|
||||
(fn [_ _]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getWalletConnectActiveSessions"
|
||||
;; This is the activeSince timestamp to avoid expired sessions
|
||||
;; 0 means, return everything
|
||||
:params [0]
|
||||
:on-success [:wallet-connect/fetch-persisted-sessions-success]
|
||||
:on-error [:wallet-connect/fetch-persisted-sessions-fail]}]]]}))
|
||||
(fn [{:keys [now]} _]
|
||||
(let [current-timestamp (quot now 1000)]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wallet_getWalletConnectActiveSessions"
|
||||
;; NOTE: This is the activeSince timestamp to avoid expired sessions
|
||||
:params [current-timestamp]
|
||||
:on-success [:wallet-connect/fetch-persisted-sessions-success]
|
||||
:on-error [:wallet-connect/fetch-persisted-sessions-fail]}]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/persist-session
|
||||
@@ -290,3 +329,12 @@
|
||||
:params [topic]
|
||||
:on-success #(log/info "Wallet Connect session disconnected")
|
||||
:on-error #(log/info "Wallet Connect session persistence failed" %)}]]]}))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/no-internet-toast
|
||||
(fn [{:keys [db]}]
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:type :negative
|
||||
:theme (:theme db)
|
||||
:text (i18n/label :t/wallet-connect-no-internet-warning)}]]]}))
|
||||
|
||||
@@ -14,26 +14,34 @@
|
||||
(rf/dispatch [:wallet-connect/respond-current-session password]))
|
||||
|
||||
(defn view
|
||||
[{:keys [warning-label slide-button-text disabled?]} & children]
|
||||
[{:keys [warning-label slide-button-text error-text]} & children]
|
||||
(let [{:keys [customization-color]} (rf/sub [:wallet-connect/current-request-account-details])
|
||||
offline? (rf/sub [:network/offline?])
|
||||
theme (quo.theme/use-theme)]
|
||||
[rn/view {:style style/content-container}
|
||||
(into [rn/view
|
||||
{:style style/data-items-container}]
|
||||
children)
|
||||
[rn/view {:style style/auth-container}
|
||||
[standard-authentication/slide-button
|
||||
{:size :size-48
|
||||
:track-text slide-button-text
|
||||
:disabled? disabled?
|
||||
:customization-color customization-color
|
||||
:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/confirm)}]]
|
||||
[rn/view {:style style/warning-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (if (= theme :dark)
|
||||
colors/white-opa-70
|
||||
colors/neutral-80-opa-70)}
|
||||
:weight :medium}
|
||||
warning-label]]]))
|
||||
[:<>
|
||||
(when (or offline? error-text)
|
||||
[quo/alert-banner
|
||||
{:action? false
|
||||
:text (if offline?
|
||||
(i18n/label :t/wallet-connect-no-internet-warning)
|
||||
error-text)}])
|
||||
[rn/view {:style style/content-container}
|
||||
(into [rn/view
|
||||
{:style style/data-items-container}]
|
||||
children)
|
||||
[rn/view {:style style/auth-container}
|
||||
[standard-authentication/slide-button
|
||||
{:size :size-48
|
||||
:track-text slide-button-text
|
||||
:disabled? (or offline? (seq error-text))
|
||||
:customization-color customization-color
|
||||
:on-auth-success on-auth-success
|
||||
:auth-button-label (i18n/label :t/confirm)}]]
|
||||
[rn/view {:style style/warning-container}
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (if (= theme :dark)
|
||||
colors/white-opa-70
|
||||
colors/neutral-80-opa-70)}
|
||||
:weight :medium}
|
||||
warning-label]]]]))
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.style)
|
||||
(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))
|
||||
|
||||
(def header-container
|
||||
{:padding-vertical 12})
|
||||
{:padding-vertical 12
|
||||
:justify-content :flex-start
|
||||
:align-items :center
|
||||
:flex-direction :row
|
||||
:flex-wrap :wrap
|
||||
:row-gap 2})
|
||||
|
||||
(def header-dapp-name
|
||||
{:margin-top -4})
|
||||
(def word-container
|
||||
{:height line-height
|
||||
:justify-content :center})
|
||||
|
||||
(def header-account-name
|
||||
{:padding-top 4})
|
||||
(def dapp-container
|
||||
{:margin-top 0
|
||||
:height line-height})
|
||||
|
||||
(def account-container
|
||||
{:height line-height})
|
||||
|
||||
@@ -1,30 +1,31 @@
|
||||
(ns status-im.contexts.wallet.wallet-connect.modals.common.header.view
|
||||
(: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]))
|
||||
(: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]))
|
||||
|
||||
(defn view
|
||||
[{:keys [label dapp account]}]
|
||||
[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}]])]])
|
||||
[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}]])])
|
||||
|
||||
@@ -7,6 +7,5 @@
|
||||
[quo/page-nav
|
||||
{:icon-name :i/close
|
||||
:background :blur
|
||||
:on-press #(do (rf/dispatch [:wallet-connect/dismiss-request-modal])
|
||||
(rf/dispatch [:wallet-connect/reject-session-request]))
|
||||
:on-press #(rf/dispatch [:wallet-connect/dismiss-request-modal])
|
||||
:accessibility-label accessibility-label}])
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
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
|
||||
@@ -33,19 +34,16 @@
|
||||
:dapp dapp
|
||||
:account account}]
|
||||
[data-block/view]]
|
||||
(when error-state
|
||||
[quo/alert-banner
|
||||
{:action? false
|
||||
:text (i18n/label (condp = error-state
|
||||
:not-enough-assets-to-pay-gas-fees
|
||||
:t/not-enough-assets-to-pay-gas-fees
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets))}])
|
||||
[footer/view
|
||||
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
|
||||
:slide-button-text (i18n/label :t/slide-to-send)
|
||||
:disabled? error-state}
|
||||
:error-text (when error-state
|
||||
(i18n/label (condp = error-state
|
||||
:not-enough-assets-to-pay-gas-fees
|
||||
:t/not-enough-assets-to-pay-gas-fees
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets)))}
|
||||
[quo/data-item
|
||||
{:status :default
|
||||
:card? false
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
{: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,6 +21,7 @@
|
||||
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
|
||||
@@ -32,19 +33,16 @@
|
||||
:dapp dapp
|
||||
:account account}]
|
||||
[data-block/view]]
|
||||
(when error-state
|
||||
[quo/alert-banner
|
||||
{:action? false
|
||||
:text (i18n/label (condp = error-state
|
||||
:not-enough-assets-to-pay-gas-fees
|
||||
:t/not-enough-assets-to-pay-gas-fees
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets))}])
|
||||
[footer/view
|
||||
{:warning-label (i18n/label :t/wallet-connect-sign-warning)
|
||||
:slide-button-text (i18n/label :t/slide-to-sign)
|
||||
:disabled? error-state}
|
||||
:error-text (when error-state
|
||||
(i18n/label (condp = error-state
|
||||
:not-enough-assets-to-pay-gas-fees
|
||||
:t/not-enough-assets-to-pay-gas-fees
|
||||
|
||||
:not-enough-assets
|
||||
:t/not-enough-assets)))}
|
||||
[quo/data-item
|
||||
{:status :default
|
||||
:card? false
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
existing-event (get-in db [:wallet-connect/current-request :event])]
|
||||
;; NOTE: make sure we don't show two requests at the same time
|
||||
(when-not existing-event
|
||||
{:db (assoc-in db [:wallet-connect/current-request :event] event)
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet-connect/current-request :event] event)
|
||||
(assoc-in [:wallet-connect/current-request :response-sent?] false))
|
||||
:fx [(condp = method
|
||||
constants/wallet-connect-eth-send-transaction-method
|
||||
[:dispatch [:wallet-connect/process-eth-send-transaction]]
|
||||
@@ -191,4 +193,4 @@
|
||||
:method method
|
||||
:wallet-connect-event event
|
||||
:event :wallet-connect/on-processing-error})
|
||||
{:fx [[:dispatch [:wallet-connect/reject-session-request]]]})))
|
||||
{:fx [[:dispatch [:wallet-connect/dismiss-request-modal]]]})))
|
||||
|
||||
@@ -3,31 +3,42 @@
|
||||
[react-native.wallet-connect :as wallet-connect]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.wallet.wallet-connect.core :as wallet-connect-core]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im.contexts.wallet.wallet-connect.utils :as wc-utils]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-current-session
|
||||
(fn [{:keys [db]} [password]]
|
||||
(let [event (get-in db [:wallet-connect/current-request :event])
|
||||
method (wallet-connect-core/get-request-method event)]
|
||||
{:fx [(condp = method
|
||||
constants/wallet-connect-personal-sign-method
|
||||
[:dispatch [:wallet-connect/respond-sign-message password :personal-sign]]
|
||||
method (wallet-connect-core/get-request-method event)
|
||||
screen (wallet-connect-core/method-to-screen method)
|
||||
expiry (get-in event [:params :request :expiryTimestamp])]
|
||||
(if (wc-utils/timestamp-expired? expiry)
|
||||
{:fx [[:dispatch
|
||||
[:toasts/upsert
|
||||
{:id :new-wallet-account-created
|
||||
:type :negative
|
||||
:text (i18n/label :t/wallet-connect-request-expired)}]]
|
||||
[:dispatch [:dismiss-modal screen]]]}
|
||||
{:fx [(condp = method
|
||||
constants/wallet-connect-personal-sign-method
|
||||
[:dispatch [:wallet-connect/respond-sign-message password :personal-sign]]
|
||||
|
||||
constants/wallet-connect-eth-sign-method
|
||||
[:dispatch [:wallet-connect/respond-sign-message password :eth-sign]]
|
||||
constants/wallet-connect-eth-sign-method
|
||||
[:dispatch [:wallet-connect/respond-sign-message password :eth-sign]]
|
||||
|
||||
constants/wallet-connect-eth-send-transaction-method
|
||||
[:dispatch [:wallet-connect/respond-send-transaction-data password]]
|
||||
constants/wallet-connect-eth-send-transaction-method
|
||||
[:dispatch [:wallet-connect/respond-send-transaction-data password]]
|
||||
|
||||
constants/wallet-connect-eth-sign-transaction-method
|
||||
[:dispatch [:wallet-connect/respond-sign-transaction-data password]]
|
||||
constants/wallet-connect-eth-sign-transaction-method
|
||||
[:dispatch [:wallet-connect/respond-sign-transaction-data password]]
|
||||
|
||||
constants/wallet-connect-eth-sign-typed-method
|
||||
[:dispatch [:wallet-connect/respond-sign-typed-data password :v1]]
|
||||
constants/wallet-connect-eth-sign-typed-method
|
||||
[:dispatch [:wallet-connect/respond-sign-typed-data password :v1]]
|
||||
|
||||
constants/wallet-connect-eth-sign-typed-v4-method
|
||||
[:dispatch [:wallet-connect/respond-sign-typed-data password :v4]])]})))
|
||||
constants/wallet-connect-eth-sign-typed-v4-method
|
||||
[:dispatch [:wallet-connect/respond-sign-typed-data password :v4]])]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/respond-sign-message
|
||||
@@ -95,31 +106,29 @@
|
||||
:method method
|
||||
:wallet-connect-event event
|
||||
:event :wallet-connect/on-sign-error})
|
||||
{:fx [[:dispatch [:wallet-connect/reject-session-request]]
|
||||
[:dispatch [:wallet-connect/dismiss-request-modal]]]})))
|
||||
{:fx [[:dispatch [:wallet-connect/dismiss-request-modal]]]})))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/send-response
|
||||
(fn [{:keys [db]} [{:keys [result error]}]]
|
||||
(let [{:keys [id topic] :as event} (get-in db [:wallet-connect/current-request :event])
|
||||
method (wallet-connect-core/get-request-method event)
|
||||
web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||
{:fx [[:effects.wallet-connect/respond-session-request
|
||||
{:web3-wallet web3-wallet
|
||||
:topic topic
|
||||
:id id
|
||||
:result result
|
||||
:error error
|
||||
:on-error (fn [error]
|
||||
(log/error "Failed to send Wallet Connect response"
|
||||
{:error error
|
||||
:method method
|
||||
:event :wallet-connect/send-response
|
||||
:wallet-connect-event event})
|
||||
(rf/dispatch [:wallet-connect/reset-current-request]))
|
||||
:on-success (fn []
|
||||
(log/info "Successfully sent Wallet Connect response to dApp")
|
||||
(rf/dispatch [:wallet-connect/reset-current-request]))}]]})))
|
||||
(when-let [{:keys [id topic] :as event} (get-in db [:wallet-connect/current-request :event])]
|
||||
(let [method (wallet-connect-core/get-request-method event)
|
||||
web3-wallet (get db :wallet-connect/web3-wallet)]
|
||||
{:db (assoc-in db [:wallet-connect/current-request :response-sent?] true)
|
||||
:fx [[:effects.wallet-connect/respond-session-request
|
||||
{:web3-wallet web3-wallet
|
||||
:topic topic
|
||||
:id id
|
||||
:result result
|
||||
:error error
|
||||
:on-error (fn [error]
|
||||
(log/error "Failed to send Wallet Connect response"
|
||||
{:error error
|
||||
:method method
|
||||
:event :wallet-connect/send-response
|
||||
:wallet-connect-event event}))
|
||||
:on-success (fn []
|
||||
(log/info "Successfully sent Wallet Connect response to dApp"))}]]}))))
|
||||
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/dismiss-request-modal
|
||||
@@ -139,16 +148,18 @@
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/reject-session-proposal
|
||||
(fn [{:keys [db]} _]
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
current-proposal (get-in db [:wallet-connect/current-proposal :request])]
|
||||
{:fx [[:effects.wallet-connect/reject-session-proposal
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal current-proposal
|
||||
:on-success #(log/info "Wallet Connect session proposal rejected")
|
||||
:on-error #(log/error "Wallet Connect unable to reject session proposal")}]
|
||||
(let [web3-wallet (get db :wallet-connect/web3-wallet)
|
||||
{:keys [request response-sent?]} (:wallet-connect/current-proposal db)]
|
||||
{:fx [(when-not response-sent?
|
||||
[:effects.wallet-connect/reject-session-proposal
|
||||
{:web3-wallet web3-wallet
|
||||
:proposal request
|
||||
:on-success #(log/info "Wallet Connect session proposal rejected")
|
||||
:on-error #(log/error "Wallet Connect unable to reject session proposal")}])
|
||||
[:dispatch [:wallet-connect/reset-current-session-proposal]]]})))
|
||||
|
||||
;; NOTE: Currently we only reject a session if the user rejected it
|
||||
;; NOTE: Currently we only reject a session if the user dismissed a modal
|
||||
;; without accepting the session first.
|
||||
;; But this needs to be solidified to ensure other cases:
|
||||
;; - Unsupported WC version
|
||||
;; - Invalid params from dapps
|
||||
@@ -156,9 +167,11 @@
|
||||
;; - Failed processing of request
|
||||
;; - Failed "responding" (signing or sending message/transaction)
|
||||
(rf/reg-event-fx
|
||||
:wallet-connect/reject-session-request
|
||||
(fn [_ _]
|
||||
{:fx [[:dispatch
|
||||
[:wallet-connect/send-response
|
||||
{:error (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-rejected-error-key)}]]]}))
|
||||
:wallet-connect/on-request-modal-dismissed
|
||||
(fn [{:keys [db]}]
|
||||
{:fx [(when-not (get-in db [:wallet-connect/current-request :response-sent?])
|
||||
[:dispatch
|
||||
[:wallet-connect/send-response
|
||||
{:error (wallet-connect/get-sdk-error
|
||||
constants/wallet-connect-user-rejected-error-key)}]])
|
||||
[:dispatch [:wallet-connect/reset-current-request]]]}))
|
||||
|
||||
@@ -148,10 +148,9 @@
|
||||
:button-two-label (i18n/label :t/decline)
|
||||
:button-two-props {:type :grey
|
||||
:accessibility-label :wc-deny-connection
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:navigate-back])
|
||||
(rf/dispatch
|
||||
[:wallet-connect/reject-session-proposal]))}
|
||||
:on-press #(rf/dispatch
|
||||
[:dismiss-modal
|
||||
:screen/wallet.wallet-connect-session-proposal])}
|
||||
:button-one-label (i18n/label :t/connect)
|
||||
:button-one-props {:customization-color customization-color
|
||||
:type :primary
|
||||
@@ -165,11 +164,13 @@
|
||||
{:type :no-title
|
||||
:background :blur
|
||||
:icon-name :i/close
|
||||
:on-press (rn/use-callback #(rf/dispatch [:navigate-back]))
|
||||
:on-press (rn/use-callback
|
||||
#(rf/dispatch [:dismiss-modal :screen/wallet.wallet-connect-session-proposal]))
|
||||
:accessibility-label :wc-session-proposal-top-bar}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(rn/use-unmount #(rf/dispatch [:wallet-connect/reject-session-proposal]))
|
||||
[floating-button-page/view
|
||||
{:footer-container-padding 0
|
||||
:header [header]
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
status-im.contexts.contact.blocking.events
|
||||
status-im.contexts.keycard.effects
|
||||
status-im.contexts.keycard.events
|
||||
status-im.contexts.networks.events
|
||||
status-im.contexts.onboarding.common.overlay.events
|
||||
status-im.contexts.onboarding.events
|
||||
status-im.contexts.profile.events
|
||||
@@ -57,7 +58,7 @@
|
||||
cofx
|
||||
{:db db/app-db
|
||||
:theme/init-theme nil
|
||||
:network/listen-to-network-info nil
|
||||
:effects.network/listen-to-network-info nil
|
||||
:effects.biometric/get-supported-type nil
|
||||
:effects.keycard/register-card-events nil
|
||||
:effects.keycard/check-nfc-enabled nil
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require
|
||||
["react-native" :refer (DevSettings LogBox NativeModules)]
|
||||
[react-native.platform :as platform]
|
||||
[status-im.setup.oops :as setup.oops]
|
||||
[status-im.setup.schema :as schema]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -47,6 +48,7 @@
|
||||
:utils/dispatch-later
|
||||
:json-rpc/call})
|
||||
(when ^:boolean js/goog.DEBUG
|
||||
(setup.oops/setup!)
|
||||
(schema/setup!)
|
||||
(when platform/ios?
|
||||
;; on Android this method doesn't work
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns status-im.setup.oops
|
||||
(:require [oops.config]))
|
||||
|
||||
(defn setup!
|
||||
"Change oops defaults to warn and print instead of throwing exceptions during
|
||||
development."
|
||||
[]
|
||||
(oops.config/update-current-runtime-config!
|
||||
merge
|
||||
{:error-reporting :console
|
||||
:expected-function-value :warn
|
||||
:invalid-selector :warn
|
||||
:missing-object-key :warn
|
||||
:object-is-frozen :warn
|
||||
:object-is-sealed :warn
|
||||
:object-key-not-writable :warn
|
||||
:unexpected-empty-selector :warn
|
||||
:unexpected-object-value :warn
|
||||
:unexpected-punching-selector :warn
|
||||
:unexpected-soft-selector :warn}))
|
||||
@@ -2,7 +2,8 @@
|
||||
(:require
|
||||
["bignumber.js" :as BigNumber]
|
||||
[matcher-combinators.core :as matcher-combinators]
|
||||
[matcher-combinators.model :as matcher.model]))
|
||||
[matcher-combinators.model :as matcher.model]
|
||||
[status-im.setup.oops :as setup.oops]))
|
||||
|
||||
;; We must implement Matcher in order for tests to work with the `match?`
|
||||
;; directive.
|
||||
@@ -16,3 +17,5 @@
|
||||
:matcher-combinators.result/value actual}
|
||||
{:matcher-combinators.result/type :mismatch
|
||||
:matcher-combinators.result/value (matcher.model/->Mismatch this actual)})))
|
||||
|
||||
(setup.oops/setup!)
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.communities.utils :as utils]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[status-im.subs.chat.utils :as subs.utils]
|
||||
[status-im.subs.contact.utils :as contact.utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.money :as money]))
|
||||
|
||||
@@ -69,7 +71,7 @@
|
||||
(fn [[_ community-id]]
|
||||
[(re-frame/subscribe [:communities/community community-id])])
|
||||
(fn [[{:keys [members]}] _]
|
||||
members))
|
||||
(js-keys members)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/community-chat-members
|
||||
@@ -92,51 +94,80 @@
|
||||
{}
|
||||
public-keys))
|
||||
|
||||
(defn- sort-members-by-name
|
||||
(defn- sort-members-by-name-old
|
||||
[names descending? members]
|
||||
(if descending?
|
||||
(sort-by #(get names (first %)) #(compare %2 %1) members)
|
||||
(sort-by #(get names (first %)) members)))
|
||||
(sort-by #(get names %) #(compare %2 %1) members)
|
||||
(sort-by #(get names %) members)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/sorted-community-members
|
||||
(defn- sort-members-by-name
|
||||
[names members-keys]
|
||||
(let [forced-last-key "zzzzzz"
|
||||
sort-keyfn (fn [k]
|
||||
(if-let [[primary-name secondary-name] (get names k)]
|
||||
(or (some-> primary-name
|
||||
string/lower-case)
|
||||
(some-> secondary-name
|
||||
string/lower-case))
|
||||
;; Sort unknown keys at the end.
|
||||
forced-last-key))]
|
||||
(sort-by sort-keyfn members-keys)))
|
||||
|
||||
;; This implementation is wrong, but since it's only used in a legacy view, we
|
||||
;; can ignore it for now.
|
||||
(re-frame/reg-sub :communities/sorted-community-members
|
||||
(fn [[_ community-id]]
|
||||
(let [profile (re-frame/subscribe [:profile/profile])
|
||||
members (re-frame/subscribe [:communities/community-members community-id])]
|
||||
[profile members]))
|
||||
[(re-frame/subscribe [:profile/profile])
|
||||
(re-frame/subscribe [:communities/community-members community-id])])
|
||||
(fn [[profile members] _]
|
||||
(let [names (keys->names (keys members) profile)]
|
||||
(let [names (keys->names members profile)]
|
||||
(->> members
|
||||
(sort-members-by-name names false)
|
||||
(sort-members-by-name-old names false)
|
||||
(sort-by #(visibility-status-utils/visibility-status-order (get % 0)))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/sorted-community-members-section-list
|
||||
(re-frame/reg-sub :communities/chat-members
|
||||
(fn [[_ community-id chat-id]]
|
||||
(let [profile (re-frame/subscribe [:profile/profile])
|
||||
members (re-frame/subscribe [:communities/community-chat-members
|
||||
community-id chat-id])
|
||||
visibility-status-updates (re-frame/subscribe
|
||||
[:visibility-status-updates])
|
||||
my-status-update (re-frame/subscribe
|
||||
[:multiaccount/current-user-visibility-status])]
|
||||
[profile members visibility-status-updates my-status-update]))
|
||||
(fn [[profile members visibility-status-updates my-status-update] _]
|
||||
(let [online? (fn [public-key]
|
||||
(let [{visibility-status-type :status-type}
|
||||
(if (or (string/blank? (:public-key profile))
|
||||
(= (:public-key profile) public-key))
|
||||
my-status-update
|
||||
(get visibility-status-updates public-key))]
|
||||
(subs.utils/online? visibility-status-type)))
|
||||
names (keys->names (keys members) profile)]
|
||||
(->> members
|
||||
(sort-members-by-name names true)
|
||||
keys
|
||||
(group-by online?)
|
||||
(map (fn [[k v]]
|
||||
{:title (if k (i18n/label :t/online) (i18n/label :t/offline))
|
||||
:data v}))))))
|
||||
[(re-frame/subscribe [:profile/public-key])
|
||||
(re-frame/subscribe [:communities/community-chat-members community-id chat-id])
|
||||
(re-frame/subscribe [:visibility-status-updates])
|
||||
(re-frame/subscribe [:multiaccount/current-user-visibility-status])])
|
||||
(fn [[profile-pub-key members-js visibility-status-updates my-status-update] [_ _ _ visibility-status]]
|
||||
(let [members-keys (js-keys members-js)
|
||||
online? (fn [public-key]
|
||||
(let [{visibility-status-type :status-type}
|
||||
(if (or (string/blank? profile-pub-key)
|
||||
(= profile-pub-key public-key))
|
||||
my-status-update
|
||||
(get visibility-status-updates public-key))]
|
||||
(subs.utils/online? visibility-status-type)))]
|
||||
(filter (if (= :online visibility-status)
|
||||
online?
|
||||
(complement online?))
|
||||
members-keys))))
|
||||
|
||||
(defn- names-by-key
|
||||
[contacts profile public-keys]
|
||||
(let [names (reduce (fn [acc k]
|
||||
(if-let [contact (get contacts k)]
|
||||
(assoc acc k (contact.utils/contact-two-names contact profile))
|
||||
acc))
|
||||
{}
|
||||
public-keys)]
|
||||
(assoc names
|
||||
(:public-key profile)
|
||||
[(profile.utils/displayed-name profile) nil])))
|
||||
|
||||
;; This is a potentially expensive subscription because we don't control how
|
||||
;; many members and contacts exist in the app-db. Future improvements include
|
||||
;; removing members from the payload and paginating them from status-go.
|
||||
(re-frame/reg-sub :communities/chat-members-sorted
|
||||
(fn [[_ community-id chat-id visibility-status]]
|
||||
[(re-frame/subscribe [:profile/profile])
|
||||
(re-frame/subscribe [:contacts/contacts-raw])
|
||||
(re-frame/subscribe [:communities/chat-members community-id chat-id visibility-status])])
|
||||
(fn [[profile contacts ^js members-keys]]
|
||||
(sort-members-by-name (names-by-key contacts profile members-keys)
|
||||
members-keys)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:communities/featured-contract-communities
|
||||
@@ -177,6 +208,13 @@
|
||||
(if (or (empty? @memo-communities-stack-items) (= view-id :communities-stack))
|
||||
(let [grouped-communities (->> communities
|
||||
vals
|
||||
;; Remove data that can grow fast or is
|
||||
;; reliably not needed to list communities.
|
||||
;; We could use an allowlist of keys for
|
||||
;; optimal performance of this sub, but
|
||||
;; that's harder to maintain in case we miss
|
||||
;; any key.
|
||||
(map #(dissoc % :members :chats :token-permissions :tokens-metadata))
|
||||
(group-by #(group-communities-by-status requests %))
|
||||
merge-opened-communities
|
||||
(map (fn [[k v]]
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def community-id "0x02b5bdaf5a25fcfe2ee14c501fab1836b8de57f61621080c3d52073d16de0d98d6")
|
||||
(def channel-id "0x1-channel-id")
|
||||
(def chat-id (str community-id channel-id))
|
||||
|
||||
(h/deftest-sub :communities
|
||||
[sub-name]
|
||||
@@ -457,65 +459,117 @@
|
||||
(match? []
|
||||
(rf/sub [sub-name community-id]))))))
|
||||
|
||||
(h/deftest-sub :communities/sorted-community-members-section-list
|
||||
(h/deftest-sub :communities/chat-members-sorted
|
||||
[sub-name]
|
||||
(testing "returns sorted community members per online status"
|
||||
(let [token-image-eth "data:image/jpeg;base64,/9j/2w"
|
||||
channel-id-1 "89f98a1e-6776-4e5f-8626-8ab9f855253f"
|
||||
channel-id-2 "a076358e-4638-470e-a3fb-584d0a542ce6"
|
||||
chat-id-1 (str community-id channel-id-1)
|
||||
chat-id-2 (str community-id channel-id-2)
|
||||
community {:id community-id
|
||||
:permissions {:access 3}
|
||||
:token-images {"ETH" token-image-eth}
|
||||
:name "Community super name"
|
||||
:chats {channel-id-1
|
||||
{:description "x"
|
||||
:emoji "🎲"
|
||||
:permissions {:access 1}
|
||||
:color "#88B0FF"
|
||||
:name "random"
|
||||
:categoryID "0c3c64e7-d56e-439b-a3fb-a946d83cb056"
|
||||
:id channel-id-1
|
||||
:position 4
|
||||
:can-post? false
|
||||
:members nil}
|
||||
channel-id-2
|
||||
{:description "General channel for the community"
|
||||
:emoji "🥔"
|
||||
:permissions {:access 1}
|
||||
:color "#4360DF"
|
||||
:name "general"
|
||||
:categoryID "0c3c64e7-d56e-439b-a3fb-a946d83cb056"
|
||||
:id channel-id-2
|
||||
:position 0
|
||||
:token-gated? true
|
||||
:can-post? false
|
||||
:members {"0x01" {"roles" [1]}
|
||||
"0x02" {"roles" [1]}
|
||||
"0x05" {"roles" [1]}}}}
|
||||
:members {"0x01" {"roles" [1]}
|
||||
"0x02" {"roles" [1]}
|
||||
"0x03" {"roles" [1]}
|
||||
"0x04" {"roles" [1]}}
|
||||
:can-request-access? false
|
||||
:outroMessage "bla"
|
||||
:verified false}]
|
||||
(let [token-image-eth "data:image/jpeg;base64,/9j/2w"
|
||||
channel-id-1 "89f98a1e-6776-4e5f-8626-8ab9f855253f"
|
||||
channel-id-2 "a076358e-4638-470e-a3fb-584d0a542ce6"
|
||||
chat-id-2 (str community-id channel-id-2)
|
||||
|
||||
member-id-1 "0x01"
|
||||
member-id-2 "0x02"
|
||||
|
||||
visibility-status-updates
|
||||
{member-id-1 {:status-type constants/visibility-status-always-online}
|
||||
member-id-2 {:status-type constants/visibility-status-always-online}}
|
||||
|
||||
contacts
|
||||
{member-id-1 {:display-name "John Marston"}
|
||||
member-id-2 {:display-name "Arthur Morgan"}}
|
||||
|
||||
community {:id community-id
|
||||
:permissions {:access 3}
|
||||
:token-images {"ETH" token-image-eth}
|
||||
:name "Community super name"
|
||||
:chats {channel-id-1
|
||||
{:description "x"
|
||||
:emoji "🎲"
|
||||
:permissions {:access 1}
|
||||
:color "#88B0FF"
|
||||
:name "random"
|
||||
:categoryID "0c3c64e7-d56e-439b-a3fb-a946d83cb056"
|
||||
:id channel-id-1
|
||||
:position 4
|
||||
:can-post? false
|
||||
:members nil}
|
||||
channel-id-2
|
||||
{:description "General channel for the community"
|
||||
:emoji "🥔"
|
||||
:permissions {:access 1}
|
||||
:color "#4360DF"
|
||||
:name "general"
|
||||
:categoryID "0c3c64e7-d56e-439b-a3fb-a946d83cb056"
|
||||
:id channel-id-2
|
||||
:position 0
|
||||
:token-gated? true
|
||||
:can-post? false
|
||||
:members (clj->js {member-id-1 {"roles" [1]}
|
||||
member-id-2 {"roles" [1]}
|
||||
"0x05" {"roles" [1]}})}}
|
||||
:members (js->clj {member-id-1 {"roles" [1]}
|
||||
member-id-2 {"roles" [1]}
|
||||
"0x03" {"roles" [1]}
|
||||
"0x04" {"roles" [1]}})}]
|
||||
(testing "returns sorted community members who are online"
|
||||
(swap! rf-db/app-db assoc :contacts/contacts contacts)
|
||||
(swap! rf-db/app-db assoc-in [:communities community-id] community)
|
||||
(swap! rf-db/app-db assoc :profile/profile profile-test/sample-profile)
|
||||
(swap! rf-db/app-db assoc :visibility-status-updates visibility-status-updates)
|
||||
(is (= [member-id-2 member-id-1]
|
||||
(rf/sub [sub-name community-id chat-id-2 :online]))))
|
||||
|
||||
(testing "returns sorted community members per offline status"
|
||||
(swap! rf-db/app-db assoc-in [:communities community-id] community)
|
||||
(swap! rf-db/app-db assoc :profile/profile profile-test/sample-profile)
|
||||
(swap! rf-db/app-db assoc :visibility-status-updates visibility-status-updates)
|
||||
(is (= ["0x05"] (rf/sub [sub-name community-id chat-id-2 :offline]))))))
|
||||
|
||||
(h/deftest-sub :communities/chat-members
|
||||
[sub-name]
|
||||
(let [member-1-id "0x1-member"
|
||||
member-2-id "0x2-member"
|
||||
|
||||
visibility-status-updates
|
||||
{member-1-id {:status-type constants/visibility-status-always-online}
|
||||
member-2-id {:status-type constants/visibility-status-always-online}}
|
||||
|
||||
communities
|
||||
{community-id {:id community-id
|
||||
:chats {channel-id {:token-gated? false
|
||||
:members (clj->js {member-2-id {}})}}
|
||||
:members (clj->js {member-1-id {}
|
||||
member-2-id {}})}}]
|
||||
(testing "members from non token-gated channels and online"
|
||||
(swap! rf-db/app-db assoc :visibility-status-updates visibility-status-updates)
|
||||
(swap! rf-db/app-db assoc :profile/profile profile-test/sample-profile)
|
||||
(swap! rf-db/app-db assoc :communities communities)
|
||||
|
||||
;; When channel is not token-gated, all community members are considered.
|
||||
(is (= [member-1-id member-2-id]
|
||||
(rf/sub [sub-name community-id chat-id :online]))))
|
||||
|
||||
(testing "members from token-gated channels and online"
|
||||
(swap! rf-db/app-db assoc :visibility-status-updates visibility-status-updates)
|
||||
(swap! rf-db/app-db assoc :profile/profile profile-test/sample-profile)
|
||||
(swap! rf-db/app-db assoc
|
||||
:visibility-status-updates
|
||||
{"0x01" {:status-type constants/visibility-status-always-online}
|
||||
"0x02" {:status-type constants/visibility-status-always-online}})
|
||||
(testing "a non-token gated community should look at all members of a community"
|
||||
(is (= [{:title (i18n/label :t/online)
|
||||
:data ["0x01" "0x02"]}
|
||||
{:title (i18n/label :t/offline)
|
||||
:data ["0x03" "0x04"]}]
|
||||
(rf/sub [sub-name community-id chat-id-1]))))
|
||||
(testing "a token gated community should use the members option in the channel"
|
||||
(is (= [{:title (i18n/label :t/online)
|
||||
:data ["0x01" "0x02"]}
|
||||
{:title (i18n/label :t/offline)
|
||||
:data ["0x05"]}]
|
||||
(rf/sub [sub-name community-id chat-id-2])))))))
|
||||
:communities
|
||||
(assoc-in communities [community-id :chats channel-id :token-gated?] true))
|
||||
|
||||
;; When channel is token-gated, only its members are considered.
|
||||
(is (= [member-2-id]
|
||||
(rf/sub [sub-name community-id chat-id :online]))))
|
||||
|
||||
(testing "members from token-gated channels and offline"
|
||||
(swap! rf-db/app-db assoc :profile/profile profile-test/sample-profile)
|
||||
(swap! rf-db/app-db assoc
|
||||
:communities
|
||||
(assoc-in communities [community-id :chats channel-id :token-gated?] true))
|
||||
|
||||
(is (= [member-2-id] (rf/sub [sub-name community-id chat-id :offline]))))
|
||||
|
||||
(testing "members from non token-gated channels and offline"
|
||||
(swap! rf-db/app-db assoc :profile/profile profile-test/sample-profile)
|
||||
(swap! rf-db/app-db assoc :communities communities)
|
||||
|
||||
(is (= [member-1-id member-2-id]
|
||||
(rf/sub [sub-name community-id chat-id :offline]))))))
|
||||
|
||||
@@ -2,29 +2,15 @@
|
||||
(:require
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
|
||||
[quo.theme]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[status-im.subs.chat.utils :as chat.utils]
|
||||
[status-im.subs.contact.utils :as contact.utils]
|
||||
[utils.address :as address]
|
||||
[utils.collection]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn query-chat-contacts
|
||||
[{:keys [contacts]} all-contacts query-fn]
|
||||
(let [participant-set (into #{} (filter identity) contacts)]
|
||||
(query-fn (comp participant-set :public-key) (vals all-contacts))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
::query-current-chat-contacts
|
||||
:<- [:chats/current-chat]
|
||||
:<- [:contacts/contacts]
|
||||
(fn [[chat contacts] [_ query-fn]]
|
||||
(query-chat-contacts chat contacts query-fn)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:multiaccount/profile-pictures-show-to
|
||||
:<- [:profile/profile]
|
||||
@@ -124,15 +110,6 @@
|
||||
sort
|
||||
vals)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/sorted-contacts
|
||||
:<- [:contacts/active]
|
||||
(fn [active-contacts]
|
||||
(->> active-contacts
|
||||
(sort-by :primary-name)
|
||||
(sort-by
|
||||
#(visibility-status-utils/visibility-status-order (:public-key %))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/sorted-and-grouped-by-first-letter
|
||||
:<- [:contacts/active]
|
||||
@@ -150,12 +127,6 @@
|
||||
{:title title
|
||||
:data data})))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/active-count
|
||||
:<- [:contacts/active]
|
||||
(fn [active-contacts]
|
||||
(count active-contacts)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/blocked
|
||||
:<- [:contacts/contacts]
|
||||
@@ -171,12 +142,6 @@
|
||||
(fn [contacts]
|
||||
(into #{} (map :public-key contacts))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/blocked-count
|
||||
:<- [:contacts/blocked]
|
||||
(fn [blocked-contacts]
|
||||
(count blocked-contacts)))
|
||||
|
||||
(defn public-key-and-ens-name->new-contact
|
||||
[public-key ens-name]
|
||||
(let [contact {:public-key public-key}]
|
||||
@@ -226,24 +191,8 @@
|
||||
(fn [[_ contact-identity] _]
|
||||
[(re-frame/subscribe [:contacts/contact-by-identity contact-identity])
|
||||
(re-frame/subscribe [:profile/profile])])
|
||||
(fn [[{:keys [primary-name] :as contact}
|
||||
{:keys [public-key preferred-name display-name name]}]
|
||||
[_ contact-identity]]
|
||||
[(if (= public-key contact-identity)
|
||||
(cond
|
||||
(not (string/blank? preferred-name)) preferred-name
|
||||
(not (string/blank? display-name)) display-name
|
||||
(not (string/blank? primary-name)) primary-name
|
||||
(not (string/blank? name)) name
|
||||
:else public-key)
|
||||
(profile.utils/displayed-name contact))
|
||||
(:secondary-name contact)]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/all-contacts-not-in-current-chat
|
||||
:<- [::query-current-chat-contacts remove]
|
||||
(fn [contacts]
|
||||
(filter :added? contacts)))
|
||||
(fn [[contact profile] [_ _]]
|
||||
(contact.utils/contact-two-names contact profile)))
|
||||
|
||||
(defn get-all-contacts-in-group-chat
|
||||
[members admins contacts {:keys [public-key preferred-name name display-name] :as current-account}]
|
||||
@@ -300,8 +249,10 @@
|
||||
:<- [:multiaccount/contact]
|
||||
(fn [[contacts multiaccount] [_ address]]
|
||||
(if (address/address= address (:public-key multiaccount))
|
||||
multiaccount
|
||||
(find-contact-by-address contacts address))))
|
||||
(merge (contact.utils/build-contact-from-public-key address)
|
||||
multiaccount)
|
||||
(or (find-contact-by-address contacts address)
|
||||
(contact.utils/build-contact-from-public-key address)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:contacts/contact-customization-color-by-address
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
(ns status-im.subs.contact.utils
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[native-module.core :as native-module]
|
||||
[status-im.common.pixel-ratio :as pixel-ratio]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.profile.utils :as profile.utils]
|
||||
[utils.address :as address]))
|
||||
|
||||
(defn replace-contact-image-uri
|
||||
@@ -44,11 +46,29 @@
|
||||
|
||||
(assoc contact :images images)))
|
||||
|
||||
|
||||
(defn build-contact-from-public-key
|
||||
(defn- build-contact-from-public-key*
|
||||
[public-key]
|
||||
(when public-key
|
||||
(let [compressed-key (native-module/serialize-legacy-key public-key)]
|
||||
{:public-key public-key
|
||||
:compressed-key compressed-key
|
||||
:primary-name (address/get-shortened-compressed-key (or compressed-key public-key))})))
|
||||
|
||||
(def build-contact-from-public-key
|
||||
"The result of this function is stable because it relies exclusively on the
|
||||
public key, but it's not cheap to be performed hundreds of times in a row,
|
||||
such as when displaying a long list of channel members."
|
||||
(memoize build-contact-from-public-key*))
|
||||
|
||||
(defn contact-two-names
|
||||
[{:keys [primary-name] :as contact}
|
||||
{:keys [public-key preferred-name display-name name]}]
|
||||
[(if (= public-key (:public-key contact))
|
||||
(cond
|
||||
(not (string/blank? preferred-name)) preferred-name
|
||||
(not (string/blank? display-name)) display-name
|
||||
(not (string/blank? primary-name)) primary-name
|
||||
(not (string/blank? name)) name
|
||||
:else public-key)
|
||||
(profile.utils/displayed-name contact))
|
||||
(:secondary-name contact)])
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
:preferred-name "Preferred Name"}
|
||||
|
||||
:contacts/contacts
|
||||
{profile-key {:primary-name "Primary Name"}
|
||||
{profile-key {:primary-name "Primary Name" :public-key profile-key}
|
||||
"contact-key" {:secondary-name "Secondary Name"}})
|
||||
|
||||
(is (= ["Preferred Name" nil] (rf/sub [sub-name profile-key])))
|
||||
|
||||
@@ -151,3 +151,9 @@
|
||||
:<- [:toasts]
|
||||
(fn [toasts [_ toast-id & cursor]]
|
||||
(get-in toasts (into [:toasts toast-id] cursor))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:network/offline?
|
||||
:<- [:network/status]
|
||||
(fn [status]
|
||||
(= status :offline)))
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
;;push notifications
|
||||
(reg-root-key-sub :push-notifications/preferences :push-notifications/preferences)
|
||||
|
||||
;;device
|
||||
(reg-root-key-sub :network/status :network/status)
|
||||
(reg-root-key-sub :network/type :network/type)
|
||||
|
||||
;;general
|
||||
(reg-root-key-sub :messenger/started? :messenger/started?)
|
||||
(reg-root-key-sub :animations :animations)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
(ns test-helpers.matchers
|
||||
"Internal use. Don't require it directly."
|
||||
(:require
|
||||
[cljs.test :as test]
|
||||
[matcher-combinators.core :as core]
|
||||
[matcher-combinators.matchers :as matchers]
|
||||
[matcher-combinators.parser]
|
||||
[matcher-combinators.result :as result]))
|
||||
|
||||
;; This implementation is identical to `match?`, but wraps the expected value
|
||||
;; with `nested-equals`. This differs from the default `embeds` matcher on maps,
|
||||
;; where extra map keys are considered valid.
|
||||
(defmethod test/assert-expr 'match-strict?
|
||||
[_ msg form]
|
||||
`(let [args# (list ~@(rest form))
|
||||
[matcher# actual#] args#]
|
||||
(cond
|
||||
(not (= 2 (count args#)))
|
||||
(test/do-report
|
||||
{:type :fail
|
||||
:message ~msg
|
||||
:expected (symbol "`match-strict?` expects 2 arguments: a `matcher` and the `actual`")
|
||||
:actual (symbol (str (count args#) " were provided: " '~form))})
|
||||
|
||||
(core/matcher? matcher#)
|
||||
(let [result# (core/match (matchers/nested-equals matcher#) actual#)]
|
||||
(test/do-report
|
||||
(if (core/indicates-match? result#)
|
||||
{:type :pass
|
||||
:message ~msg
|
||||
:expected '~form
|
||||
:actual (list 'match? matcher# actual#)}
|
||||
(with-file+line-info
|
||||
{:type :fail
|
||||
:message ~msg
|
||||
:expected '~form
|
||||
:actual (tagged-for-pretty-printing (list '~'not (list 'match? matcher# actual#))
|
||||
result#)
|
||||
:markup (::result/value result#)}))))
|
||||
|
||||
:else
|
||||
(test/do-report
|
||||
{:type :fail
|
||||
:message ~msg
|
||||
:expected (str "The first argument of `match-strict?` "
|
||||
"needs to be a matcher (implement the match protocol)")
|
||||
:actual '~form}))))
|
||||
@@ -0,0 +1,24 @@
|
||||
(ns test-helpers.matchers
|
||||
"Some vars in this namespace solely exist to support the matchers.clj file."
|
||||
(:require-macros test-helpers.matchers)
|
||||
(:require
|
||||
[cljs.test :as t]
|
||||
[matcher-combinators.parser]
|
||||
[matcher-combinators.printer :as printer]
|
||||
[matcher-combinators.result :as result]))
|
||||
|
||||
(defrecord Mismatch [summary match-result])
|
||||
|
||||
(defn tagged-for-pretty-printing
|
||||
[actual-summary result]
|
||||
(->Mismatch actual-summary result))
|
||||
|
||||
(extend-protocol IPrintWithWriter
|
||||
Mismatch
|
||||
(-pr-writer [this writer _]
|
||||
(-write writer (printer/as-string (-> this :match-result ::result/value)))))
|
||||
|
||||
(defn with-file+line-info
|
||||
[report]
|
||||
(merge (t/file-and-line (js/Error.) 4)
|
||||
report))
|
||||
@@ -12,7 +12,10 @@
|
||||
[re-frame.events :as rf-events]
|
||||
[re-frame.registrar :as rf-registrar]
|
||||
[re-frame.subs :as rf-subs]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
|
||||
;; We must require this namespace to register the custom cljs.test directive `match-strict?`.
|
||||
test-helpers.matchers))
|
||||
|
||||
(defn db
|
||||
"A simple wrapper to get the latest value from the app db."
|
||||
|
||||
@@ -15,6 +15,34 @@
|
||||
|
||||
(defn clj->json [data] (clj->pretty-json data 0))
|
||||
|
||||
(defn <-js-map
|
||||
"Shallowly transforms JS Object keys/values with `key-fn`/`val-fn`.
|
||||
|
||||
Returns nil if `m` is not an instance of `js/Object`.
|
||||
|
||||
Implementation taken from `js->clj`, but with the ability to customize how
|
||||
keys and/or values are transformed in one loop.
|
||||
|
||||
This function is useful when you don't want to recursively apply the same
|
||||
transformation to keys/values. For example, many maps in the app-db are
|
||||
indexed by ID, like `community.members`. If we convert the entire community
|
||||
with (js->clj m :keywordize-keys true), then IDs will be converted to
|
||||
keywords, but we want them as strings. Instead of transforming to keywords and
|
||||
then transforming back to strings, it's better to not transform them at all.
|
||||
"
|
||||
([^js m]
|
||||
(<-js-map m nil))
|
||||
([^js m {:keys [key-fn val-fn]}]
|
||||
(when (identical? (type m) js/Object)
|
||||
(persistent!
|
||||
(reduce (fn [r k]
|
||||
(let [v (oops/oget+ m k)
|
||||
new-key (if key-fn (key-fn k v) k)
|
||||
new-val (if val-fn (val-fn k v) v)]
|
||||
(assoc! r new-key new-val)))
|
||||
(transient {})
|
||||
(js-keys m))))))
|
||||
|
||||
(defn js-stringify
|
||||
[js-object spaces]
|
||||
(.stringify js/JSON js-object nil spaces))
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
(ns utils.transforms-test
|
||||
(:require
|
||||
[cljs.test :refer [are deftest is testing]]
|
||||
[utils.transforms :as sut]))
|
||||
|
||||
(defn equals-as-json
|
||||
[m1 m2]
|
||||
(= (js/JSON.stringify (clj->js m1))
|
||||
(js/JSON.stringify (clj->js m2))))
|
||||
|
||||
(deftest <-js-map-test
|
||||
(testing "without transforming keys/values"
|
||||
(are [expected m]
|
||||
(is (equals-as-json expected (sut/<-js-map m)))
|
||||
nil nil
|
||||
nil #js []
|
||||
#js {} #js {}
|
||||
#js {"a" 1 "b" 2} #js {"a" 1 "b" 2}))
|
||||
|
||||
(testing "with key/value transformation"
|
||||
(is (equals-as-json {"aa" [1] "bb" [2]}
|
||||
(sut/<-js-map #js {"a" 1 "b" 2}
|
||||
{:key-fn (fn [k] (str k k))
|
||||
:val-fn (fn [_ v] (vector v))}))))
|
||||
|
||||
(testing "it is non-recursive"
|
||||
(is (equals-as-json {:a 1 :b #js {"c" 3}}
|
||||
(sut/<-js-map #js {"a" 1 "b" #js {"c" 3}}
|
||||
{:key-fn (fn [k] (keyword k))}))))
|
||||
|
||||
(testing "value transformation based on the key"
|
||||
(is (equals-as-json {"a" 1 "b" "banana"}
|
||||
(sut/<-js-map #js {"a" 1 "b" 2}
|
||||
{:val-fn (fn [k v]
|
||||
(if (= "b" k)
|
||||
"banana"
|
||||
v))})))))
|
||||
@@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.182.37",
|
||||
"commit-sha1": "4a43b2b2bebe45df2100d1a5c5034105d93e50b8",
|
||||
"src-sha256": "0f5mm7lx6s2qcy9xpa9v7piqb60yazi6p677fy105yz7hg731cw6"
|
||||
"version": "f32d15cb887496ce55ca3c958e987ff104c83a8a",
|
||||
"commit-sha1": "f32d15cb887496ce55ca3c958e987ff104c83a8a",
|
||||
"src-sha256": "1x7p0pia6402hfyd4pnihz76g7pydby4isvmzmsdyl0hl1wn9q0b"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ from os import environ
|
||||
from sys import argv
|
||||
|
||||
import emoji
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from support.base_test_report import BaseTestReport
|
||||
@@ -139,20 +140,12 @@ class TestrailReport(BaseTestReport):
|
||||
for category in test_cases['pr']:
|
||||
for case in self.get_cases([test_cases['pr'][category]]):
|
||||
case_ids.append(case['id'])
|
||||
case_ids.extend([703133, 702742, 702745])
|
||||
elif 'nightly' in argv:
|
||||
case_ids.extend([703133, 702742, 702745, 702843])
|
||||
# elif 'nightly' in argv:
|
||||
else:
|
||||
for category in test_cases['nightly']:
|
||||
for case in self.get_cases([test_cases['nightly'][category]]):
|
||||
case_ids.append(case['id'])
|
||||
elif 'upgrade' in argv and 'not upgrade' not in argv:
|
||||
for case in self.get_cases([test_cases['upgrade']['general']]):
|
||||
case_ids.append(case['id'])
|
||||
else:
|
||||
for phase in test_cases:
|
||||
if phase != 'upgrade':
|
||||
for category in test_cases[phase]:
|
||||
for case in self.get_cases([test_cases[phase][category]]):
|
||||
case_ids.append(case['id'])
|
||||
return case_ids
|
||||
|
||||
def add_results(self):
|
||||
|
||||
@@ -253,9 +253,7 @@ class TestCommunityOneDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
self.home.navigate_back_to_home_view()
|
||||
self.home.just_fyi("Turn off testnet in the profile settings")
|
||||
profile = self.home.profile_button.click()
|
||||
profile.advanced_button.scroll_and_click()
|
||||
profile.testnet_mode_toggle.click()
|
||||
profile.ok_button.click()
|
||||
profile.switch_network()
|
||||
self.sign_in.sign_in()
|
||||
|
||||
self.home.just_fyi("Check Discover Communities content")
|
||||
@@ -368,6 +366,7 @@ class TestCommunityMultipleDeviceMerged(MultipleSharedDeviceTestCase):
|
||||
self.errors.append("Default username '%s' is not shown next to the received message" % self.username_1)
|
||||
self.errors.verify_no_errors()
|
||||
|
||||
@marks.smoke
|
||||
@marks.testrail_id(702843)
|
||||
def test_community_message_edit(self):
|
||||
message_before_edit, message_after_edit = 'Message BEFORE edit', "Message AFTER edit 2"
|
||||
|
||||
@@ -304,7 +304,6 @@ class ProfileView(BaseView):
|
||||
self.advanced_button = AdvancedButton(self.driver)
|
||||
self.mutual_contact_request_switcher = Button(self.driver, accessibility_id="mutual-contact-requests-switch")
|
||||
## Network
|
||||
self.network_settings_button = Button(self.driver, accessibility_id="network-button")
|
||||
self.active_network_name = Text(self.driver,
|
||||
xpath="//android.widget.TextView[contains(@text,'with upstream RPC')]")
|
||||
self.plus_button = Button(self.driver, xpath="(//android.widget.ImageView[@content-desc='icon'])[2]")
|
||||
@@ -361,22 +360,18 @@ class ProfileView(BaseView):
|
||||
self.profile_password_button = Button(self.driver, accessibility_id="icon, Password, label-component, icon")
|
||||
self.profile_messages_button = Button(self.driver, accessibility_id="icon, Messages, label-component, icon")
|
||||
self.profile_blocked_users_button = Button(self.driver, accessibility_id="Blocked users, label-component, icon")
|
||||
self.profile_wallet_button = Button(self.driver, accessibility_id="icon, Wallet, label-component, icon")
|
||||
self.network_settings_button = Button(self.driver, accessibility_id="Network settings, label-component, icon")
|
||||
self.profile_legacy_button = Button(self.driver,
|
||||
accessibility_id="icon, Legacy settings, label-component, icon")
|
||||
self.testnet_mode_toggle = Button(self.driver,
|
||||
xpath="//*[@content-desc='test-networks-enabled']/android.widget.Switch")
|
||||
self.testnet_mode_toggle = Button(self.driver, accessibility_id="icon, Testnet mode, label-component")
|
||||
self.confirm_testnet_mode_change_button = Button(self.driver, accessibility_id="confirm-testnet-mode-change")
|
||||
|
||||
def switch_network(self, network='Mainnet with upstream RPC'):
|
||||
self.driver.info("## Switch network to '%s'" % network, device=False)
|
||||
self.advanced_button.click()
|
||||
def switch_network(self):
|
||||
self.profile_wallet_button.click()
|
||||
self.network_settings_button.click()
|
||||
network_button = Button(self.driver, xpath="//*[@text='%s']" % network)
|
||||
network_button.scroll_and_click()
|
||||
self.connect_button.click_until_presence_of_element(self.confirm_button)
|
||||
self.confirm_button.click_until_absense_of_element(self.confirm_button)
|
||||
from views.sign_in_view import SignInView
|
||||
SignInView(self.driver).sign_in()
|
||||
self.driver.info("## Network is switched successfully!", device=False)
|
||||
self.testnet_mode_toggle.click()
|
||||
self.confirm_testnet_mode_change_button.click()
|
||||
|
||||
def open_contact_from_profile(self, username):
|
||||
self.driver.info("Opening profile of '%s' via Contacts" % username)
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
"approved-amount-symbol": "Approved {{amount}} {{symbol}}",
|
||||
"approving-amount-symbol": "Approving {{amount}} {{symbol}}...",
|
||||
"apr": "Apr",
|
||||
"arbiscan": "Arbiscan",
|
||||
"arbitrum": "Arbitrum",
|
||||
"are-not-allowed": "{{check} are not allowed",
|
||||
"are-you-sure": "Are you sure?",
|
||||
@@ -975,6 +976,7 @@
|
||||
"ethereum-address": "Ethereum address",
|
||||
"ethereum-node-started-incorrectly-description": "Ethereum node was started with incorrect configuration, application will be stopped to recover from that condition. Configured network id = {{network-id}}, actual = {{fetched-network-id}}",
|
||||
"ethereum-node-started-incorrectly-title": "Ethereum node started incorrectly",
|
||||
"etherscan": "Etherscan",
|
||||
"etherscan-lookup": "Look up on Etherscan",
|
||||
"everyone": "Everyone",
|
||||
"everyone-mention": "everyone",
|
||||
@@ -1760,6 +1762,7 @@
|
||||
"oops-this-qr-does-not-contain-an-address": "Oops! This QR does not contain an address",
|
||||
"oops-wrong-password": "Oops, wrong password!",
|
||||
"oops-wrong-word": "Oops! Wrong word",
|
||||
"op-explorer": "OP Explorer",
|
||||
"open": "Open",
|
||||
"open-chat": "Open chat",
|
||||
"open-dapp": "Open ÐApp",
|
||||
@@ -2620,6 +2623,7 @@
|
||||
"wakuv2-node-format": "/ip4/{node-ip}/tcp/{port}/p2p/{id}",
|
||||
"wakuv2-settings": "Waku v2 settings",
|
||||
"wallet": "Wallet",
|
||||
"wallet-activity-beta-message": "Activity is in beta. If transactions are missing, check",
|
||||
"wallet-address": "Wallet address",
|
||||
"wallet-asset": "Asset",
|
||||
"wallet-assets": "Assets",
|
||||
@@ -2632,9 +2636,12 @@
|
||||
"wallet-connect-go-back": "Go back to your browser or dapp",
|
||||
"wallet-connect-label": "WalletConnect",
|
||||
"wallet-connect-networks-not-supported": "{{dapp}} requires an unsupported network.",
|
||||
"wallet-connect-no-internet-warning": "Oops, you have no internet. Try again later!",
|
||||
"wallet-connect-proposal-description": "By connecting you allow {{name}} to retrieve your account address and enable Web3",
|
||||
"wallet-connect-proposal-expired": "WalletConnect proposal has expired",
|
||||
"wallet-connect-proposal-title": "Would like to connect with your wallet",
|
||||
"wallet-connect-qr-expired": "WalletConnect QR has expired",
|
||||
"wallet-connect-request-expired": "WalletConnect request has expired",
|
||||
"wallet-connect-send-transaction-header": "wants you to send this transaction with",
|
||||
"wallet-connect-send-transaction-warning": "Send transactions only if you trust the dApp",
|
||||
"wallet-connect-sign-message-header": "wants you to sign the message with",
|
||||
|
||||
Reference in New Issue
Block a user