Add QR scanner to connect Dapps through Connected Dapps screen (#20647)

* Add QR scanner to connect Dapps through Connected Dapps screen

* Style fix

* use-mount
This commit is contained in:
Alexander 2024-07-08 13:55:32 +02:00 committed by GitHub
parent de6d9a6c3b
commit 4c4a8b65d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 179 additions and 109 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -6,7 +6,7 @@
[:type {:optional true}
[:maybe
[:enum :default :multiuser :group :channel :community :token :network :multinetwork :account
:collectible :address :icon :audio :wallet-user]]]
:collectible :address :icon :audio :wallet-user :dapp]]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:container-style {:optional true} [:maybe :map]]
[:blur? {:optional true} [:maybe :boolean]]

View File

@ -17,16 +17,18 @@
[schema.core :as schema]))
(defn- tag-skeleton
[{:keys [size text] :or {size 24}} logo-component]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
text]]]))
[{:keys [size text theme]
:or {size 24
theme (quo.theme/use-theme)}}
logo-component]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
text]]])
(defn- communities-tag
[{:keys [size community-logo community-name blur? channel? channel-name]}]
@ -81,95 +83,100 @@
context]]]))
(defn- view-internal
[{:keys [type size state blur? customization-color profile-picture full-name users
[{:keys [type theme size state blur? customization-color profile-picture full-name users
group-name amount token network-logo network-name networks
account-name emoji collectible collectible-name collectible-number duration container-style]
account-name emoji collectible collectible-name collectible-number
dapp-name dapp-logo duration container-style]
:or {customization-color :blue
type :default
state :default}
state :default
theme (quo.theme/use-theme)}
:as props}]
(let [theme (quo.theme/use-theme)]
[rn/view {:style (merge {:align-items :flex-start} container-style)}
[rn/view
{:style (style/container {:theme theme
:type type
:size size
:state state
:blur? blur?
:customization-color customization-color})
:accessibility-label :context-tag}
(case type
:default
[tag-skeleton {:theme theme :size size :text full-name}
[user-avatar/user-avatar
{:full-name full-name
:profile-picture profile-picture
:size (if (= size 24) :xxs 28)
:status-indicator? false
:ring? false
:customization-color customization-color}]]
[rn/view {:style (merge {:align-items :flex-start} container-style)}
[rn/view
{:style (style/container {:theme theme
:type type
:size size
:state state
:blur? blur?
:customization-color customization-color})
:accessibility-label :context-tag}
(case type
:default
[tag-skeleton {:theme theme :size size :text full-name}
[user-avatar/user-avatar
{:full-name full-name
:profile-picture profile-picture
:size (if (= size 24) :xxs 28)
:status-indicator? false
:ring? false
:customization-color customization-color}]]
:multiuser
[preview-list/view {:type :user :size :size-20}
users]
:multiuser
[preview-list/view {:type :user :size :size-20}
users]
:multinetwork
[preview-list/view {:type :network :size :size-20}
networks]
:multinetwork
[preview-list/view {:type :network :size :size-20}
networks]
:audio
[tag-skeleton {:theme theme :text (str duration)}
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
:audio
[tag-skeleton {:theme theme :text (str duration)}
[rn/view {:style (style/audio-tag-icon-container customization-color theme)}
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
:group
[tag-skeleton {:theme theme :size size :text group-name}
[group-avatar/view
{:icon-name :i/members
:size (if (= size 24) :size-20 :size-28)
:customization-color (colors/custom-color customization-color 50)}]]
:group
[tag-skeleton {:theme theme :size size :text group-name}
[group-avatar/view
{:icon-name :i/members
:size (if (= size 24) :size-20 :size-28)
:customization-color (colors/custom-color customization-color 50)}]]
(:channel :community)
[communities-tag (assoc props :channel? (= type :channel))]
(:channel :community)
[communities-tag (assoc props :channel? (= type :channel))]
:token
[tag-skeleton {:theme theme :size size :text (str amount " " token)}
[token/view
{:style (style/token-logo size)
:token token
:size (if (= size 24) :size-20 :size-28)}]]
:token
[tag-skeleton {:theme theme :size size :text (str amount " " token)}
[token/view
{:style (style/token-logo size)
:token token
:size (if (= size 24) :size-20 :size-28)}]]
:network
[tag-skeleton {:theme theme :size size :text network-name}
[rn/image {:style (style/circle-logo size) :source network-logo}]]
:network
[tag-skeleton {:theme theme :size size :text network-name}
[rn/image {:style (style/circle-logo size) :source network-logo}]]
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:account
[tag-skeleton {:theme theme :size size :text account-name}
[account-avatar/view
{:customization-color customization-color
:emoji emoji
:size (if (= size 24) 20 28)}]]
:account
[tag-skeleton {:theme theme :size size :text account-name}
[account-avatar/view
{:customization-color customization-color
:emoji emoji
:size (if (= size 24) 20 28)}]]
:address
[address-tag props]
:address
[address-tag props]
:icon
[icon-tag props]
:icon
[icon-tag props]
:wallet-user
[tag-skeleton {:theme theme :size size :text full-name}
[wallet-user-avatar/wallet-user-avatar
{:full-name full-name
:size (if (= size 24) :size-20 :size-24)
:customization-color customization-color}]]
:wallet-user
[tag-skeleton {:theme theme :size size :text full-name}
[wallet-user-avatar/wallet-user-avatar
{:full-name full-name
:size (if (= size 24) :size-20 :size-24)
:customization-color customization-color}]]
nil)]]))
:dapp
[tag-skeleton {:theme theme :size size :text dapp-name}
[rn/image {:style (style/circle-logo size) :source dapp-logo}]]
nil)]])
(def view (schema/instrument #'view-internal component-schema/?schema))

View File

@ -24,12 +24,13 @@
(get ui k))
(def dapps
{:coingecko (js/require "../resources/images/dapps/CoinGecko.png")
:1inch (js/require "../resources/images/dapps/1inch.png")
:aave (js/require "../resources/images/dapps/Aave.png")
:uniswap (js/require "../resources/images/dapps/Uniswap.png")
:zapper (js/require "../resources/images/dapps/Zapper.png")
:zerion (js/require "../resources/images/dapps/Zerion.png")})
{:coingecko (js/require "../resources/images/dapps/CoinGecko.png")
:1inch (js/require "../resources/images/dapps/1inch.png")
:aave (js/require "../resources/images/dapps/Aave.png")
:uniswap (js/require "../resources/images/dapps/Uniswap.png")
:zapper (js/require "../resources/images/dapps/Zapper.png")
:zerion (js/require "../resources/images/dapps/Zerion.png")
:wallet-connect (js/require "../resources/images/dapps/WalletConnect.png")})
(defn get-dapp
[k]

View File

@ -37,7 +37,7 @@
:networks networks
:align-center? true
:networks-on-press #(rf/dispatch [:show-bottom-sheet {:content network-filter/view}])
:right-side [(when (and (ff/enabled? ::wallet.wallet-connect)
:right-side [(when (and (ff/enabled? ::ff/wallet.wallet-connect)
(not watch-only?))
{:icon-name :i/dapps
:on-press #(rf/dispatch [:navigate-to :screen/wallet.connected-dapps])})

View File

@ -0,0 +1,11 @@
(ns status-im.contexts.wallet.connected-dapps.scan-dapp.style
(:require [quo.foundations.colors :as colors]))
(def subtitle-container
{:flex-direction :row
:align-items :center
:padding-horizontal 20
:gap 4})
(def subtitle-text
{:color colors/white})

View File

@ -0,0 +1,44 @@
(ns status-im.contexts.wallet.connected-dapps.scan-dapp.view
(:require [quo.core :as quo]
[quo.foundations.resources :as quo.resources]
[quo.theme]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[status-im.common.scan-qr-code.view :as scan-qr-code]
[status-im.contexts.wallet.connected-dapps.scan-dapp.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [keyboard-shown]} (hooks/use-keyboard)
{:keys [name emoji color]} (rf/sub [:wallet/current-viewing-account])]
(rn/use-mount
(fn []
(when keyboard-shown
(rn/dismiss-keyboard!))))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:subtitle [rn/view style/subtitle-container
[quo/context-tag
{:theme :dark
:type :account
:size 24
:account-name name
:emoji emoji
:customization-color color}]
[quo/text
{:style style/subtitle-text
:size :paragraph-1}
(i18n/label :t/wallet-connect-via)]
[quo/context-tag
{:theme :dark
:type :dapp
:size 24
:dapp-name (i18n/label :t/wallet-connect-label)
:dapp-logo (quo.resources/get-dapp :wallet-connect)}]]
:on-success-scan (fn [scanned-text]
(debounce/debounce-and-dispatch
[:wallet-connect/on-scan-connection scanned-text]
300))}]))

View File

@ -90,7 +90,7 @@
{:title (i18n/label :t/connected-dapps)
:wallet-account wallet-account
:on-close #(rf/dispatch [:navigate-back])
:on-add #(js/alert "Feature not implemented")}]
:on-add #(rf/dispatch [:navigate-to :screen/wallet.scan-dapp])}]
(if (empty? pairings)
[quo/empty-state
{:title (i18n/label :t/no-dapps)

View File

@ -67,8 +67,7 @@
:session-networks session-networks
:address (-> without-watched
first
:address)
)
:address))
:fx [[:dispatch
[:open-modal :screen/wallet.wallet-connect-session-proposal]]]}
{:fx [[:dispatch
@ -190,27 +189,25 @@
(fn [_ [scanned-text]]
(let [parsed-uri (wallet-connect/parse-uri scanned-text)
version (:version parsed-uri)
valid-wc-uri? (wc-utils/valid-uri? parsed-uri)
expired? (-> parsed-uri
:expiryTimestamp
wc-utils/timestamp-expired?)
version-supported? (wc-utils/version-supported? version)]
(cond
expired?
(if (or (not valid-wc-uri?) expired? (not version-supported?))
{:fx [[:dispatch
[:toasts/upsert
{:type :negative
:theme :dark
:text (i18n/label :t/wallet-connect-qr-expired)}]]]}
:text (cond (not valid-wc-uri?)
(i18n/label :t/wallet-connect-wrong-qr)
(not version-supported?)
{:fx [[:dispatch
[:toasts/upsert
{:type :negative
:theme :dark
:text (i18n/label :t/wallet-connect-version-not-supported
{:version version})}]]]}
expired?
(i18n/label :t/wallet-connect-qr-expired)
:else
(not version-supported?)
(i18n/label :t/wallet-connect-version-not-supported
{:version version}))}]]]}
{:fx [[:dispatch [:wallet-connect/pair scanned-text]]]}))))
(rf/reg-event-fx

View File

@ -108,6 +108,7 @@
[status-im.contexts.wallet.bridge.select-asset.view :as wallet-bridge-select-asset]
[status-im.contexts.wallet.collectible.view :as wallet-collectible]
[status-im.contexts.wallet.common.scan-account.view :as wallet-scan-address]
[status-im.contexts.wallet.connected-dapps.scan-dapp.view :as wallet-scan-dapp]
[status-im.contexts.wallet.connected-dapps.view :as wallet-connected-dapps]
[status-im.contexts.wallet.send.from.view :as wallet-select-from]
[status-im.contexts.wallet.send.select-address.view :as wallet-select-address]
@ -411,10 +412,6 @@
:options {:insets {:top? true}}
:component wallet-accounts/view}
{:name :screen/wallet.connected-dapps
:options {:insets {:top? true}}
:component wallet-connected-dapps/view}
{:name :screen/wallet.wallet-connect-session-proposal
:options {:sheet? true}
:component wallet-connect-session-proposal/view}
@ -549,6 +546,16 @@
:options {:sheet? true}
:component wallet-connect-send-transaction/view}
{:name :screen/wallet.connected-dapps
:options {:insets {:top? true}}
:component wallet-connected-dapps/view}
{:name :screen/wallet.scan-dapp
:options (merge
options/dark-screen
{:modalPresentationStyle :overCurrentContext})
:component wallet-scan-dapp/view}
;; Settings
{:name :screen/settings-password

View File

@ -2733,8 +2733,11 @@
"dapp-will-be-able-to": "{{dapp-name}} will be able to:",
"check-your-account-balance-and-activity": "Check your account balance and activity",
"request-txns-and-message-signing": "Request transactions and message signing",
"wallet-connect-label": "WalletConnect",
"wallet-connect-via": "via",
"wallet-connect-qr-expired": "WalletConnect QR has expired",
"wallet-connect-version-not-supported": "WalletConnect version {{version}} is not supported",
"wallet-connect-wrong-qr": "Its not a WalletConnect QR",
"add-network-preferences": "Add network preferences",
"saved-address-network-preference-selection-description": "Only change if you know which networks the address owner is happy to to receive funds on",
"add-preferences": "Add preferences",