Skip to content

Commit

Permalink
feat(shell): add share qr wallet accounts feature(#18511)
Browse files Browse the repository at this point in the history
Co-authored-by: Paul Fitzgerald <paulfitz99@gmail.com>
  • Loading branch information
J-Son89 and Pau1fitz authored Jan 15, 2024
1 parent 92dcd11 commit 3e787ff
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 105 deletions.
5 changes: 0 additions & 5 deletions .clj-kondo/rewrite-clj/rewrite-clj/config.edn

This file was deleted.

1 change: 0 additions & 1 deletion .clj-kondo/taoensso/encore/config.edn

This file was deleted.

16 changes: 0 additions & 16 deletions .clj-kondo/taoensso/encore/taoensso/encore.clj

This file was deleted.

75 changes: 75 additions & 0 deletions src/status_im/contexts/shell/share/profile/view.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
(ns status-im.contexts.shell.share.profile.view
(:require
[clojure.string :as string]
[legacy.status-im.ui.components.list-selection :as list-selection]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.core :as rn]
[status-im.common.qr-codes.view :as qr-codes]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.share.style :as style]
[utils.address :as address]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))

(defn profile-tab
[]
(let [{:keys [emoji-hash
customization-color
universal-profile-url]
:as profile} (rf/sub [:profile/profile])
abbreviated-url (address/get-abbreviated-profile-url
universal-profile-url)
emoji-hash-string (string/join emoji-hash)]
[:<>
[rn/view {:style style/qr-code-container}
[qr-codes/share-qr-code
{:type :profile
:unblur-on-android? true
:qr-data universal-profile-url
:qr-data-label-shown abbreviated-url
:on-share-press #(list-selection/open-share {:message universal-profile-url})
:on-text-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:on-text-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:profile-picture (:uri (profile.utils/photo profile))
:full-name (profile.utils/displayed-name profile)
:customization-color customization-color}]]

[rn/view {:style style/emoji-hash-container}
[rn/view {:style style/emoji-address-container}
[rn/view {:style style/emoji-address-column}
[quo/text
{:size :paragraph-2
:weight :medium
:style style/emoji-hash-label}
(i18n/label :t/emoji-hash)]
[rn/touchable-highlight
{:active-opacity 1
:underlay-color colors/neutral-80-opa-1-blur
:background-color :transparent
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
[rn/text {:style style/emoji-hash-content} emoji-hash-string]]]]
[rn/view {:style style/emoji-share-button-container}
[quo/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :link-to-profile
:container-style {:margin-right 12}
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
:i/copy]]]]))
78 changes: 4 additions & 74 deletions src/status_im/contexts/shell/share/view.cljs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
(ns status-im.contexts.shell.share.view
(:require
[clojure.string :as string]
[legacy.status-im.ui.components.list-selection :as list-selection]
[quo.core :as quo]
[quo.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.common.qr-codes.view :as qr-codes]
[status-im.contexts.profile.utils :as profile.utils]
[status-im.contexts.shell.share.profile.view :as profile-view]
[status-im.contexts.shell.share.style :as style]
[utils.address :as address]
[status-im.contexts.shell.share.wallet.view :as wallet-view]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))

Expand Down Expand Up @@ -43,72 +39,6 @@
:style style/header-heading}
(i18n/label :t/share)]])

(defn profile-tab
[]
(let [{:keys [emoji-hash
customization-color
universal-profile-url]
:as profile} (rf/sub [:profile/profile])
abbreviated-url (address/get-abbreviated-profile-url
universal-profile-url)
emoji-hash-string (string/join emoji-hash)]
[:<>
[rn/view {:style style/qr-code-container}
[qr-codes/share-qr-code
{:type :profile
:unblur-on-android? true
:qr-data universal-profile-url
:qr-data-label-shown abbreviated-url
:on-share-press #(list-selection/open-share {:message universal-profile-url})
:on-text-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:on-text-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy universal-profile-url
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
:profile-picture (:uri (profile.utils/photo profile))
:full-name (profile.utils/displayed-name profile)
:customization-color customization-color}]]

[rn/view {:style style/emoji-hash-container}
[rn/view {:style style/emoji-address-container}
[rn/view {:style style/emoji-address-column}
[quo/text
{:size :paragraph-2
:weight :medium
:style style/emoji-hash-label}
(i18n/label :t/emoji-hash)]
[rn/touchable-highlight
{:active-opacity 1
:underlay-color colors/neutral-80-opa-1-blur
:background-color :transparent
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
[rn/text {:style style/emoji-hash-content} emoji-hash-string]]]]
[rn/view {:style style/emoji-share-button-container}
[quo/button
{:icon-only? true
:type :grey
:background :blur
:size 32
:accessibility-label :link-to-profile
:container-style {:margin-right 12}
:on-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])
:on-long-press #(rf/dispatch [:share/copy-text-and-show-toast
{:text-to-copy emoji-hash-string
:post-copy-message (i18n/label :t/emoji-hash-copied)}])}
:i/copy]]]]))

(defn wallet-tab
[]
[rn/text {:style style/wip-style} "not implemented"])

(defn tab-content
[]
(let [selected-tab (reagent/atom :profile)]
Expand All @@ -126,8 +56,8 @@
{:id :wallet
:label (i18n/label :t/wallet)}]}]]
(if (= @selected-tab :profile)
[profile-tab]
[wallet-tab])])))
[profile-view/profile-tab]
[wallet-view/wallet-tab])])))

(defn view
[]
Expand Down
44 changes: 44 additions & 0 deletions src/status_im/contexts/shell/share/wallet/component_spec.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
(ns status-im.contexts.shell.share.wallet.component-spec
(:require
[status-im.contexts.shell.share.wallet.view :as wallet-view]
status-im.contexts.wallet.events
[test-helpers.component :as h]))

(defn render-wallet-view
[]
(let [component-rendered (h/render [wallet-view/wallet-tab])
rerender-fn (h/get-rerender-fn component-rendered)
share-qr-code (h/get-by-label-text :share-qr-code)]
;; Fires on-layout since it's needed to render the content
(h/fire-event :layout share-qr-code #js {:nativeEvent #js {:layout #js {:width 500}}})
(rerender-fn [wallet-view/wallet-tab])))

(h/describe "share wallet addresses"
(h/setup-restorable-re-frame)
(h/before-each
(fn []
(h/setup-subs {:dimensions/window-width 500
:mediaserver/port 200
:wallet/accounts [{:address "0x707f635951193ddafbb40971a0fcaab8a6415160"
:name "Wallet One"
:emoji "😆"
:color :blue}]})))

(h/test "should display the the wallet tab"
(render-wallet-view)
(h/wait-for #(h/is-truthy (h/get-by-text "Wallet One"))))

(h/test "should display the the legacy account"
(render-wallet-view)
(-> (h/wait-for #(h/get-by-label-text :share-qr-code-legacy-tab))
(.then (fn []
(h/fire-event :press (h/get-by-label-text :share-qr-code-legacy-tab))
(-> (h/wait-for #(h/is-falsy (h/query-by-text "eth:"))))))))

(h/test "should display the the multichain account"
(render-wallet-view)
(-> (h/wait-for #(h/get-by-label-text :share-qr-code-multichain-tab))
(.then (fn []
(h/fire-event :press (h/get-by-label-text :share-qr-code-multichain-tab))
(-> (h/wait-for #(h/is-truthy (h/query-by-text "eth:")))))))))

91 changes: 91 additions & 0 deletions src/status_im/contexts/shell/share/wallet/view.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
(ns status-im.contexts.shell.share.wallet.view
(:require
[quo.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.share :as share]
[reagent.core :as reagent]
[status-im.contexts.shell.share.style :as style]
[status-im.contexts.wallet.common.sheets.network-preferences.view :as network-preferences]
[status-im.contexts.wallet.common.utils :as utils]
[utils.i18n :as i18n]
[utils.image-server :as image-server]
[utils.re-frame :as rf]))

(def qr-size 500)

(defn- share-action
[address share-title]
(share/open
(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:linkMetadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address
:isNewTask true})))

(defn- open-preferences
[selected-networks]
(rf/dispatch [:show-bottom-sheet
{:theme :dark
:shell? true
:content
(fn []
[network-preferences/view
{:blur? true
:selected-networks (set selected-networks)
:on-save (fn [chain-ids]
(rf/dispatch [:hide-bottom-sheet])
(reset! selected-networks (map #(get utils/id->network %)
chain-ids)))}])}]))
(defn wallet-qr-code-item
[account width index]
(let [selected-networks (reagent/atom [:ethereum :optimism :arbitrum])
wallet-type (reagent/atom :wallet-legacy)]
(fn []
(let [share-title (str (:name account) " " (i18n/label :t/address))
qr-url (utils/get-wallet-qr {:wallet-type @wallet-type
:selected-networks @selected-networks
:address (:address account)})
qr-media-server-uri (image-server/get-qr-image-uri-for-any-url
{:url qr-url
:port (rf/sub [:mediaserver/port])
:qr-size qr-size
:error-level :highest})]
[rn/view {:style {:width width :margin-left (if (zero? index) 0 -30)}}
[rn/view {:style style/qr-code-container}
[quo/share-qr-code
{:type @wallet-type
:qr-image-uri qr-media-server-uri
:qr-data qr-url
:networks @selected-networks
:on-share-press #(share-action qr-url share-title)
:profile-picture nil
:unblur-on-android? true
:full-name (:name account)
:customization-color (:color account)
:emoji (:emoji account)
:on-multichain-press #(reset! wallet-type :wallet-multichain)
:on-legacy-press #(reset! wallet-type :wallet-legacy)
:on-settings-press #(open-preferences @selected-networks)}]]]))))

(defn wallet-tab
[]
(let [accounts (rf/sub [:wallet/accounts])
width (rf/sub [:dimensions/window-width])]
[rn/flat-list
{:horizontal true
:deceleration-rate 0.9
:snap-to-alignment "start"
:snap-to-interval (- width 30)
:disable-interval-momentum true
:scroll-event-throttle 64
:data accounts
:directional-lock-enabled true
:render-fn (fn [account index]
(wallet-qr-code-item account width index))}]))
19 changes: 10 additions & 9 deletions src/status_im/contexts/wallet/receive/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
[address share-title]
(share/open
(if platform/ios?
{:activity-item-sources [{:placeholder-item {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:link-metadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address})))
{:activityItemSources [{:placeholderItem {:type "text"
:content address}
:item {:default {:type "text"
:content
address}}
:linkMetadata {:title share-title}}]}
{:title share-title
:subject share-title
:message address
:isNewTask true})))

(defn- open-preferences
[selected-networks]
Expand Down
1 change: 1 addition & 0 deletions src/status_im/core_spec.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[status-im.common.floating-button-page.component-spec]
[status-im.contexts.chat.messenger.messages.content.audio.component-spec]
[status-im.contexts.communities.actions.community-options.component-spec]
[status-im.contexts.shell.share.wallet.component-spec]
[status-im.contexts.wallet.add-address-to-watch.component-spec]
[status-im.contexts.wallet.add-address-to-watch.confirm-address.component-spec]
[status-im.contexts.wallet.create-account.edit-derivation-path.component-spec]
Expand Down
4 changes: 4 additions & 0 deletions test/jest/jestSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ jest.mock('react-native-fs', () => ({
default: {},
}));

jest.mock('react-native-share', () => ({
default: {},
}));

jest.mock('react-native-navigation', () => ({
getNavigationConstants: () => ({ constants: [] }),
Navigation: {
Expand Down

0 comments on commit 3e787ff

Please sign in to comment.