wallet redesign

This commit is contained in:
andrey 2022-03-14 12:52:25 +01:00
parent 784cb491ab
commit 12e3b74651
No known key found for this signature in database
GPG Key ID: 89B67245FD2F0272
16 changed files with 404 additions and 124 deletions

View File

@ -1,7 +1,11 @@
(ns quo.theme (ns quo.theme
(:require [quo.design-system.colors :as colors])) (:require [quo.design-system.colors :as colors]
[reagent.core :as reagent]))
(def theme (atom nil)) (def theme (reagent/atom nil))
(defn dark? []
(= :dark @theme))
(defn get-theme [] (defn get-theme []
@theme) @theme)

View File

@ -1,10 +1,10 @@
(ns quo2.components.button (ns quo2.components.button
(:require [quo.react-native :as rn] (:require [quo.react-native :as rn]
[status-im.ui.components.icons.icons :as icons]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[quo2.components.text :as text] [quo2.components.text :as text]
[quo.theme :as theme] [quo.theme :as theme]
[reagent.core :as reagent])) [reagent.core :as reagent]
[quo2.components.icon :as quo2.icons]))
(def themes {:light {:primary {:icon-color colors/white (def themes {:light {:primary {:icon-color colors/white
:label {:style {:color colors/white}} :label {:style {:color colors/white}}
@ -16,9 +16,9 @@
:background-color {:default colors/primary-50-opa-20 :background-color {:default colors/primary-50-opa-20
:pressed colors/primary-50-opa-40 :pressed colors/primary-50-opa-40
:disabled colors/primary-50-opa-20}} :disabled colors/primary-50-opa-20}}
:grey {:icon-color colors/neutral-50 :grey {:icon-color colors/black
:label {:style {:color colors/black}} :label {:style {:color colors/black}}
:background-color {:default colors/neutral-40 :background-color {:default colors/neutral-20
:pressed colors/neutral-30 :pressed colors/neutral-30
:disabled colors/neutral-20}} :disabled colors/neutral-20}}
:outline {:icon-color colors/neutral-50 :outline {:icon-color colors/neutral-50
@ -61,7 +61,7 @@
:pressed colors/danger-40 :pressed colors/danger-40
:disabled colors/danger-50}}}}) :disabled colors/danger-50}}}})
(defn style-container [type size disabled background-color border-color icon above] (defn style-container [type size disabled background-color border-color icon above width before after]
(merge {:height size (merge {:height size
:align-items :center :align-items :center
:justify-content :center :justify-content :center
@ -74,7 +74,14 @@
32 10 32 10
24 8)) 24 8))
:background-color background-color :background-color background-color
:padding-horizontal (if icon 0 (case size 56 16 40 16 32 12 24 8))} :padding-horizontal (when-not (or icon before after)
(case size 56 16 40 16 32 12 24 8))
:padding-left (when-not (or icon before)
(case size 56 16 40 16 32 12 24 8))
:padding-right (when-not (or icon after)
(case size 56 16 40 16 32 12 24 8))}
(when width
{:width width})
(when icon (when icon
{:width size}) {:width size})
(when border-color (when border-color
@ -97,14 +104,15 @@
[button {:icon true} :main-icons/close-circle]" [button {:icon true} :main-icons/close-circle]"
[_ _] [_ _]
(let [pressed (reagent/atom false)] (let [pressed (reagent/atom false)]
(fn [{:keys [on-press disabled type size before after above (fn [{:keys [on-press disabled type size before after above width
on-long-press accessibility-label icon] on-long-press accessibility-label icon]
:or {type :primary :or {type :primary
size 40}} size 40}}
children] children]
(let [{:keys [icon-color background-color label border-color]} (let [{:keys [icon-color background-color label border-color]}
(get-in themes [(theme/get-theme) type]) (get-in themes [(theme/get-theme) type])
state (cond disabled :disabled @pressed :pressed :else :default)] state (cond disabled :disabled @pressed :pressed :else :default)
icon-size (when (= 24 size) 12)]
[rn/touchable-without-feedback (merge {:disabled disabled [rn/touchable-without-feedback (merge {:disabled disabled
:accessibility-label accessibility-label} :accessibility-label accessibility-label}
(when on-press (when on-press
@ -118,17 +126,33 @@
{:on-press-out (fn [] {:on-press-out (fn []
(reset! pressed nil))}) (reset! pressed nil))})
[rn/view {:style (style-container type size disabled (get background-color state) (get border-color state) icon above)} [rn/view {:style (style-container
type
size
disabled
(get background-color state)
(get border-color state)
icon
above
width
before
after)}
(when above (when above
[rn/view [rn/view
[icons/icon above {:color icon-color}]]) [quo2.icons/icon above {:container-style {:margin-bottom 2}
:color icon-color
:size icon-size}]])
(when before (when before
[rn/view [rn/view
[icons/icon before {:color icon-color}]]) [quo2.icons/icon before {:container-style {:margin-left (if (= size 40) 12 8)
:margin-right 4}
:color icon-color
:size icon-size}]])
[rn/view [rn/view
(cond (cond
icon icon
[icons/icon children {:color icon-color}] [quo2.icons/icon children {:color icon-color
:size icon-size}]
(string? children) (string? children)
[text/text (merge {:size (when (#{56 24} size) :paragraph-2) [text/text (merge {:size (when (#{56 24} size) :paragraph-2)
@ -141,4 +165,7 @@
children)] children)]
(when after (when after
[rn/view [rn/view
[icons/icon after {:color icon-color}]])]])))) [quo2.icons/icon after {:container-style {:margin-left 4
:margin-right (if (= size 40) 12 8)}
:color icon-color
:size icon-size}]])]]))))

View File

@ -0,0 +1,10 @@
(ns quo2.components.icon
(:require [status-im.ui.components.icons.icons :as icons]))
(defn icon
([icon-name] (icon icon-name nil))
([icon-name {:keys [size] :as props}]
(let [size (or size 20)]
[icons/icon (str (name icon-name) size) (merge props
{:width size
:height size})])))

View File

@ -5,7 +5,7 @@
(defn tabs [{:keys [default-active on-change]}] (defn tabs [{:keys [default-active on-change]}]
(let [active-tab-id (reagent/atom default-active)] (let [active-tab-id (reagent/atom default-active)]
(fn [{:keys [data size]}] (fn [{:keys [data size] :or {size 32}}]
(let [active-id @active-tab-id] (let [active-id @active-tab-id]
[rn/view {:flex-direction :row} [rn/view {:flex-direction :row}
(for [{:keys [label id]} data] (for [{:keys [label id]} data]

View File

@ -1,5 +1,6 @@
(ns quo2.foundations.colors (ns quo2.foundations.colors
(:require [clojure.string :as string])) (:require [clojure.string :as string]
[quo.theme :as theme]))
(defn alpha [value opacity] (defn alpha [value opacity]
(if (string/starts-with? value "#") (if (string/starts-with? value "#")
@ -173,4 +174,7 @@
(def info-50-opa-10 (alpha info-50 0.1)) (def info-50-opa-10 (alpha info-50 0.1))
(def info-50-opa-20 (alpha info-50 0.2)) (def info-50-opa-20 (alpha info-50 0.2))
(def info-50-opa-30 (alpha info-50 0.3)) (def info-50-opa-30 (alpha info-50 0.3))
(def info-50-opa-40 (alpha info-50 0.4)) (def info-50-opa-40 (alpha info-50 0.4))
(defn theme-colors [light dark]
(if (theme/dark?) dark light))

View File

@ -2,23 +2,24 @@
(def heading-1 {:font-size 27 (def heading-1 {:font-size 27
:line-height 32.4 :line-height 32.4
:letter-spacing -2.1}) :letter-spacing -0.5})
(def heading-2 {:font-size 19 (def heading-2 {:font-size 19
:line-height 25.65 :line-height 25.65
:letter-spacing -1.6}) :letter-spacing -0.4})
(def paragraph-1 {:font-size 15 (def paragraph-1 {:font-size 15
:line-height 21.75 :line-height 21.75
:letter-spacing -0.9}) :letter-spacing -0.1})
(def paragraph-2 {:font-size 13 (def paragraph-2 {:font-size 13
:line-height 18.2 :line-height 18.2
:letter-spacing -0.3}) :letter-spacing 0})
(def label {:font-size 11 (def label {:font-size 11
:line-height 15.62 :line-height 15.62
:letter-spacing -0.055}) :letter-spacing -0.055
:text-transform :uppercase})
(def font-regular {:font-family "Inter-Regular"}) ; 400 (def font-regular {:font-family "Inter-Regular"}) ; 400

View File

@ -70,12 +70,12 @@
:theme :before :after) :theme :before :after)
{:on-press #(println "Hello world!")} {:on-press #(println "Hello world!")}
(when @above (when @above
{:above :main-icons/close-circle}) {:above :main-icons2/placeholder})
(when @before (when @before
{:before :main-icons/back}) {:before :main-icons2/placeholder})
(when @after (when @after
{:after :main-icons/next})) {:after :main-icons2/placeholder}))
(if @icon :main-icons/close-circle @label)]]]))) (if @icon :main-icons2/placeholder @label)]]])))
(defn preview-button [] (defn preview-button []
[rn/view {:background-color (:ui-background @colors/theme) [rn/view {:background-color (:ui-background @colors/theme)

View File

@ -8,12 +8,8 @@
(def descriptor [{:label "Size:" (def descriptor [{:label "Size:"
:key :size :key :size
:type :select :type :select
:options [{:key 32 :options [{:key 28
:value "32"}
{:key 28
:value "28"} :value "28"}
{:key 24
:value "24"}
{:key 20 {:key 20
:value "20"}]}]) :value "20"}]}])

View File

@ -10,12 +10,8 @@
:type :select :type :select
:options [{:key 32 :options [{:key 32
:value "32"} :value "32"}
{:key 28
:value "28"}
{:key 24 {:key 24
:value "24"} :value "24"}]}])
{:key 20
:value "20"}]}])
(defn cool-preview [] (defn cool-preview []
(let [state (reagent/atom {:size 32})] (let [state (reagent/atom {:size 32})]

View File

@ -27,8 +27,6 @@
:value "Medium"} :value "Medium"}
{:key :semi-bold {:key :semi-bold
:value "Semi-bold"} :value "Semi-bold"}
{:key :bold
:value "Bold"}
{:key :monospace {:key :monospace
:value "Monospace"}]}]) :value "Monospace"}]}])

View File

@ -121,7 +121,8 @@
[status-im.ui.screens.wallet.recipient.views :as recipient] [status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.wallet.send.views :as wallet.send] [status-im.ui.screens.wallet.send.views :as wallet.send]
[quo2.screens.main :as quo2.preview] [quo2.screens.main :as quo2.preview]
[status-im.utils.config :as config])) [status-im.utils.config :as config]
[quo2.foundations.colors :as quo2.colors]))
(def components (def components
[{:name :chat-toolbar [{:name :chat-toolbar
@ -357,6 +358,7 @@
{:name :wallet {:name :wallet
:insets {:top false} :insets {:top false}
:on-focus [:wallet/tab-opened] :on-focus [:wallet/tab-opened]
:options {:statusBar {:backgroundColor quo2.colors/neutral-5}}
:component wallet.accounts/accounts-overview} :component wallet.accounts/accounts-overview}
{:name :wallet-account {:name :wallet-account
;;TODO dynamic title ;;TODO dynamic title

View File

@ -13,14 +13,20 @@
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.ui.screens.wallet.account.styles :as styles] [status-im.ui.screens.wallet.account.styles :as styles]
[status-im.ui.screens.wallet.accounts.sheets :as sheets] [status-im.ui.screens.wallet.accounts.sheets :as sheets]
[status-im.ui.screens.wallet.accounts.views :as accounts] [status-im.ui.screens.wallet.accounts.common :as common]
[status-im.ui.screens.wallet.transactions.views :as history] [status-im.ui.screens.wallet.transactions.views :as history]
[status-im.ui.components.tabs :as tabs] [status-im.ui.components.tabs :as tabs]
[status-im.ui.screens.wallet.collectibles.views :as collectibles.views] [status-im.ui.screens.wallet.collectibles.views :as collectibles.views]
[status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]) [status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]
[quo2.foundations.colors :as quo2.colors]
[status-im.utils.handlers :refer [<sub]]
[quo2.components.text :as quo2.text]
[quo2.components.button :as quo2.button]
[quo2.components.tabs :as quo2.tabs])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(def state (reagent/atom {:tab :assets})) (def state (reagent/atom {:tab :assets}))
(def selected-tab (reagent/atom :tokens))
(defn button [label icon color handler] (defn button [label icon color handler]
[react/touchable-highlight {:on-press handler :style {:flex 1}} [react/touchable-highlight {:on-press handler :style {:flex 1}}
@ -98,26 +104,27 @@
{:style {:color colors/blue}} {:style {:color colors/blue}}
(i18n/label :t/check-on-opensea)]]]) (i18n/label :t/check-on-opensea)]]])
(views/defview assets-and-collections [address] (views/defview assets-and-collections-new [address]
(views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address] (views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address]
currency [:wallet/currency] currency [:wallet/currency]
opensea-enabled? [:opensea-enabled?] opensea-enabled? [:opensea-enabled?]
collectible-collection [:wallet/collectible-collection address] collectible-collection [:wallet/collectible-collection address]]
ethereum-network? [:ethereum-network?]] ;ethereum-network? [:ethereum-network?]]
(let [{:keys [tab]} @state] (let [tab @selected-tab]
[react/view {:flex 1} [react/view {:flex 1}
[react/view {:flex-direction :row :margin-bottom 8 :padding-horizontal 4} [react/view {:padding-horizontal 20 :padding-bottom 20}
[tabs/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)] [quo2.tabs/tabs {:size 24
(when ethereum-network? :on-change #(reset! selected-tab %)
[tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)]) :default-active :tokens
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]] :data [{:id :tokens :label "Tokens"}
[quo/separator {:style {:margin-top -8}}] {:id :nft :label "NFTs"}
{:id :activity :label "Activity"}]}]]
(cond (cond
(= tab :assets) (= tab :tokens)
[:<> [react/scroll-view
(for [item tokens] (for [item tokens]
^{:key (:name item)} ^{:key (:name item)}
[accounts/render-asset item nil nil (:code currency)])] [common/render-asset-new item nil nil (:code currency)])]
(= tab :nft) (= tab :nft)
[:<> [:<>
[opensea-link address] [opensea-link address]
@ -134,7 +141,7 @@
[react/view {:align-items :center :margin-top 32} [react/view {:align-items :center :margin-top 32}
[react/text {:style {:color colors/gray}} [react/text {:style {:color colors/gray}}
(i18n/label :t/no-collectibles)]]))] (i18n/label :t/no-collectibles)]]))]
(= tab :history) (= tab :activity)
[transactions address])]))) [transactions address])])))
(views/defview bottom-send-recv-buttons [{:keys [address type] :as account} anim-y] (views/defview bottom-send-recv-buttons [{:keys [address type] :as account} anim-y]
@ -201,6 +208,76 @@
:title (i18n/label :t/swap) :title (i18n/label :t/swap)
:on-press #(re-frame/dispatch [:open-modal :token-swap])}]]) :on-press #(re-frame/dispatch [:open-modal :token-swap])}]])
(views/defview assets-and-collections [address]
(views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address]
currency [:wallet/currency]
opensea-enabled? [:opensea-enabled?]
collectible-collection [:wallet/collectible-collection address]
ethereum-network? [:ethereum-network?]]
(let [{:keys [tab]} @state]
[react/view {:flex 1}
[react/view {:flex-direction :row :margin-bottom 8 :padding-horizontal 4}
[tabs/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)]
(when ethereum-network?
[tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)])
[tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]]
[quo/separator {:style {:margin-top -8}}]
(cond
(= tab :assets)
[:<>
(for [item tokens]
^{:key (:name item)}
[common/render-asset item nil nil (:code currency)])]
(= tab :nft)
[:<>
[opensea-link address]
;; Hide collectibles behind a feature flag
(when config/collectibles-enabled?
(cond
(not opensea-enabled?)
[collectibles.views/enable-opensea-view]
(and opensea-enabled? (seq collectible-collection))
[collectibles.views/nft-collections address]
:else
[react/view {:align-items :center :margin-top 32}
[react/text {:style {:color colors/gray}}
(i18n/label :t/no-collectibles)]]))]
(= tab :history)
[transactions address])])))
(defn account-new [selected-account]
(let [;{:keys [name address] :as account} (<sub [:account-by-address selected-account])
currency (<sub [:wallet/currency])
portfolio-value (<sub [:account-portfolio-value selected-account])
width (<sub [:dimensions/window-width])
button-width (/ (- width 40 (* 2 12)) 3)]
;fetching-error (<sub [:wallet/fetching-error])]
[react/view {:flex 1
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)
:border-top-left-radius 20
:border-top-right-radius 20
:elevation 4
:shadow-opacity 1
:shadow-radius 20
:shadow-color (:shadow-01 @colors/theme)
:shadow-offset {:width 0 :height 4}}
[react/view {:padding 20}
[quo2.text/text {:size :heading-2 :weight :semi-bold} (str portfolio-value " " (:code currency))]]
[react/view
[react/scroll-view {:horizontal true :margin-bottom 32 :showsHorizontalScrollIndicator false}
[react/view {:width 20}]
[quo2.button/button {:size 56 :width button-width :above :main-icons2/placeholder} "Buy"]
[react/view {:width 12}]
[quo2.button/button {:size 56 :width button-width :type :secondary :above :main-icons2/placeholder} "Send"]
[react/view {:width 12}]
[quo2.button/button {:size 56 :width button-width :type :secondary :above :main-icons2/placeholder} "Receive"]
[react/view {:width 12}]
[quo2.button/button {:size 56 :width button-width :type :secondary :above :main-icons2/placeholder} "Swap"]
[react/view {:width 20}]]]
[assets-and-collections-new selected-account]]))
(views/defview account [] (views/defview account []
(views/letsubs [{:keys [name address] :as account} [:multiaccount/current-account] (views/letsubs [{:keys [name address] :as account} [:multiaccount/current-account]
fetching-error [:wallet/fetching-error]] fetching-error [:wallet/fetching-error]]
@ -221,9 +298,9 @@
[{:nativeEvent {:contentOffset {:y scroll-y}}}] [{:nativeEvent {:contentOffset {:y scroll-y}}}]
{:useNativeDriver true}) {:useNativeDriver true})
:scrollEventThrottle 1 :scrollEventThrottle 1
:refreshControl (accounts/refresh-control :refreshControl (common/refresh-control
(and (and
@accounts/updates-counter @common/updates-counter
@(re-frame/subscribe [:wallet/refreshing-history?])))} @(re-frame/subscribe [:wallet/refreshing-history?])))}
(when fetching-error (when fetching-error
[react/view {:style {:flex 1 [react/view {:style {:flex 1

View File

@ -0,0 +1,87 @@
(ns status-im.ui.screens.wallet.accounts.common
(:require [quo.core :as quo]
[status-im.wallet.utils :as wallet.utils]
[status-im.ui.screens.wallet.components.views :as wallet.components]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[reagent.core :as reagent]
[quo.react-native :as rn]
[status-im.utils.utils :as utils.utils]
[re-frame.core :as re-frame]
[quo2.foundations.colors :as quo2.colors]
[quo2.components.text :as quo2.text]))
;; Note(rasom): sometimes `refreshing` might get stuck on iOS if action happened
;; too fast. By updating this atom in 1s we ensure that `refreshing?` property
;; is updated properly in this case.
(def updates-counter (reagent/atom 0))
(defn schedule-counter-reset []
(utils.utils/set-timeout
(fn []
(swap! updates-counter inc)
(when @(re-frame/subscribe [:wallet/refreshing-history?])
(schedule-counter-reset)))
1000))
(defn refresh-action []
(schedule-counter-reset)
(re-frame/dispatch [:wallet.ui/pull-to-refresh-history]))
(defn refresh-control [refreshing?]
(reagent/as-element
[rn/refresh-control
{:refreshing (boolean refreshing?)
:onRefresh refresh-action}]))
(defn render-asset [{:keys [icon decimals amount color value] :as token} _ _ currency]
[quo/list-item
{:title [quo/text {:weight :medium}
[quo/text {:weight :inherit}
(str (if amount
(wallet.utils/format-amount amount decimals)
"...")
" ")]
[quo/text {:color :secondary
:weight :inherit}
(wallet.utils/display-symbol token)]]
:subtitle (str (if value value "...") " " currency)
:accessibility-label (str (:symbol token) "-asset-value")
:icon (if icon
[wallet.components/token-icon icon]
[chat-icon/custom-icon-view-list (:name token) color])}])
(defn render-asset-new [{:keys [icon decimals amount color value name] :as token} _ _ currency]
[rn/view {:height 56 :margin-horizontal 8 :margin-top 4}
[rn/view {:position :absolute :left 12 :top 12}
(if icon
[wallet.components/token-icon (merge icon {:width 32 :height 32})]
[chat-icon/custom-icon-view-list (:name token) color])]
[rn/view {:position :absolute :left 52 :top 8 :right 12}
[rn/view {:flex-direction :row :justify-content :space-between :align-items :center}
[quo2.text/text {:weight :semi-bold :style {:height 22}}
name]
[quo2.text/text {:size :paragraph-2 :weight :medium}
(str (if value value "...") " " currency)]]
[quo2.text/text {:size :paragraph-2
:weight :medium
:style {:color (quo2.colors/theme-colors quo2.colors/neutral-50 quo2.colors/neutral-40)}}
(str (if amount
(wallet.utils/format-amount amount decimals)
"...")
" "
(wallet.utils/display-symbol token))]]]
#_[quo/list-item
{:title [quo/text {:weight :medium}
[quo/text {:weight :inherit}
(str (if amount
(wallet.utils/format-amount amount decimals)
"...")
" ")]
[quo/text {:color :secondary
:weight :inherit}
(wallet.utils/display-symbol token)]]
:subtitle (str (if value value "...") " " currency)
:accessibility-label (str (:symbol token) "-asset-value")
:icon (if icon
[wallet.components/token-icon icon]
[chat-icon/custom-icon-view-list (:name token) color])}])

View File

@ -5,22 +5,24 @@
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.i18n.i18n :as i18n] [status-im.i18n.i18n :as i18n]
[status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto] [status-im.ui.screens.wallet.buy-crypto.views :as buy-crypto]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[status-im.ui.components.icons.icons :as icons] [status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.wallet.accounts.sheets :as sheets] [status-im.ui.screens.wallet.accounts.sheets :as sheets]
[status-im.ui.screens.wallet.accounts.styles :as styles] [status-im.ui.screens.wallet.accounts.styles :as styles]
[status-im.qr-scanner.core :as qr-scanner] [status-im.qr-scanner.core :as qr-scanner]
[status-im.wallet.utils :as wallet.utils]
[status-im.keycard.login :as keycard.login] [status-im.keycard.login :as keycard.login]
[quo.react-native :as rn] [quo2.foundations.colors :as quo2.colors]
[status-im.utils.utils :as utils.utils] [quo2.components.button :as quo2.button]
[status-im.ui.screens.wallet.components.views :as wallet.components]) [quo2.components.text :as quo2.text]
[quo2.components.tabs :as quo2.tabs]
[status-im.ui.screens.wallet.accounts.common :as common]
[status-im.ui.screens.wallet.account.views :as account.views]
[quo.components.safe-area :as safe-area])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(views/defview account-card [{:keys [name color address type wallet] :as account} keycard? card-width] (views/defview account-card [{:keys [name color address type wallet] :as account} keycard? card-width]
(views/letsubs [currency [:wallet/currency] (views/letsubs [currency [:wallet/currency]
portfolio-value [:account-portfolio-value address] portfolio-value [:account-portfolio-value address]
prices-loading? [:prices-loading?]] prices-loading? [:prices-loading?]]
[react/touchable-highlight [react/touchable-highlight
@ -35,7 +37,7 @@
[react/view {:style {:flex-direction :row}} [react/view {:style {:flex-direction :row}}
(if prices-loading? (if prices-loading?
[react/small-loading-indicator :colors/white-persist] [react/small-loading-indicator :colors/white-persist]
[react/text {:style styles/card-value [react/text {:style styles/card-value
:accessibility-label "account-total-value"} portfolio-value]) :accessibility-label "account-total-value"} portfolio-value])
[react/text {:style styles/card-value-currency} (str " " (:code currency))]] [react/text {:style styles/card-value-currency} (str " " (:code currency))]]
(let [icon (cond (let [icon (cond
@ -46,9 +48,9 @@
:main-icons/keycard-account)] :main-icons/keycard-account)]
(when icon (when icon
[icons/icon icon {:container-style styles/card-icon-type [icons/icon icon {:container-style styles/card-icon-type
:color color}])) :color color}]))
[react/touchable-highlight [react/touchable-highlight
{:style styles/card-icon-more {:style styles/card-icon-more
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet :on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [sheets/account-card-actions account type wallet]) {:content (fn [] [sheets/account-card-actions account type wallet])
:content-height 130}])} :content-height 130}])}
@ -63,30 +65,13 @@
[icons/icon :main-icons/add-circle {:color colors/blue}] [icons/icon :main-icons/add-circle {:color colors/blue}]
[react/text {:style styles/add-text} (i18n/label :t/add-account)]]]) [react/text {:style styles/add-text} (i18n/label :t/add-account)]]])
(defn render-asset [{:keys [icon decimals amount color value] :as token} _ _ currency]
[quo/list-item
{:title [quo/text {:weight :medium}
[quo/text {:weight :inherit}
(str (if amount
(wallet.utils/format-amount amount decimals)
"...")
" ")]
[quo/text {:color :secondary
:weight :inherit}
(wallet.utils/display-symbol token)]]
:subtitle (str (if value value "...") " " currency)
:accessibility-label (str (:symbol token) "-asset-value")
:icon (if icon
[wallet.components/token-icon icon]
[chat-icon/custom-icon-view-list (:name token) color])}])
(views/defview assets [] (views/defview assets []
(views/letsubs [{:keys [tokens]} [:wallet/all-visible-assets-with-values] (views/letsubs [{:keys [tokens]} [:wallet/all-visible-assets-with-values]
currency [:wallet/currency]] currency [:wallet/currency]]
[:<> [:<>
(for [item tokens] (for [item tokens]
^{:key (:name item)} ^{:key (:name item)}
[render-asset item nil nil (:code currency)])])) [common/render-asset item nil nil (:code currency)])]))
(views/defview send-button [] (views/defview send-button []
(views/letsubs [account [:multiaccount/default-account]] (views/letsubs [account [:multiaccount/default-account]]
@ -108,7 +93,8 @@
^{:key i} ^{:key i}
[dot {:selected (= selected i)}])]) [dot {:selected (= selected i)}])])
(views/defview accounts [] ;;ACCOUNTS OLD
(views/defview accounts-old []
(views/letsubs [accounts [:multiaccount/visible-accounts] (views/letsubs [accounts [:multiaccount/visible-accounts]
keycard? [:keycard-multiaccount?] keycard? [:keycard-multiaccount?]
window-width [:dimensions/window-width] window-width [:dimensions/window-width]
@ -133,17 +119,18 @@
[account-card account keycard? card-width])) [account-card account keycard? card-width]))
[add-card card-width]]] [add-card card-width]]]
(let [columns (Math/ceil (/ (inc (count accounts)) 2)) (let [columns (Math/ceil (/ (inc (count accounts)) 2))
totalwidth (* (styles/page-width card-width) columns) totalwidth (* (styles/page-width card-width) columns)
n (Math/ceil (/ totalwidth window-width))] n (Math/ceil (/ totalwidth window-width))]
(when (> n 1) (when (> n 1)
[dots-selector {:selected @index [dots-selector {:selected @index
:n n}]))]))) :n n}]))])))
(views/defview total-value [{:keys [animation minimized]}] ;;TOTAL VALUE OLD
(views/letsubs [currency [:wallet/currency] (views/defview total-value-old [{:keys [animation minimized]}]
portfolio-value [:portfolio-value] (views/letsubs [currency [:wallet/currency]
empty-balances? [:empty-balances?] portfolio-value [:portfolio-value]
frozen-card? [:keycard/frozen-card?] empty-balances? [:empty-balances?]
frozen-card? [:keycard/frozen-card?]
{:keys [mnemonic]} [:multiaccount]] {:keys [mnemonic]} [:multiaccount]]
[reanimated/view {:style (styles/container {:minimized minimized})} [reanimated/view {:style (styles/container {:minimized minimized})}
(when (or (when (or
@ -174,8 +161,8 @@
(i18n/label :t/your-card-is-frozen) (i18n/label :t/your-card-is-frozen)
(i18n/label :t/back-up-your-seed-phrase))]]]]) (i18n/label :t/back-up-your-seed-phrase))]]]])
[reanimated/view {:style (styles/value-container {:minimized minimized [reanimated/view {:style (styles/value-container {:minimized minimized
:animation animation}) :animation animation})
:pointer-events :none} :pointer-events :none}
[reanimated/view {:style {:justify-content :center}} [reanimated/view {:style {:justify-content :center}}
[quo/text {:animated? true [quo/text {:animated? true
@ -192,39 +179,130 @@
[quo/text {:color :secondary} [quo/text {:color :secondary}
(i18n/label :t/wallet-total-value)]])])) (i18n/label :t/wallet-total-value)]])]))
;; Note(rasom): sometimes `refreshing` might get stuck on iOS if action happened (views/defview total-value []
;; too fast. By updating this atom in 1s we ensure that `refreshing?` property (views/letsubs [currency [:wallet/currency]
;; is updated properly in this case. portfolio-value [:portfolio-value]]
(def updates-counter (reagent/atom 0)) ;empty-balances? [:empty-balances?]
;frozen-card? [:keycard/frozen-card?]
;{:keys [mnemonic]} [:multiaccount]]
[react/view {:padding-vertical 12}
[quo2.text/text (i18n/label :t/wallet-total-value)]
[quo2.text/text {:size :heading-1 :weight :semi-bold}
(str portfolio-value " " (:code currency))]
[react/scroll-view {:horizontal true}]]
#_[reanimated/view {:style (styles/container {:minimized minimized})}
(when (or
(and frozen-card? minimized)
(and mnemonic minimized (not empty-balances?)))
[reanimated/view {:style (styles/accounts-mnemonic {:animation animation})}
[react/touchable-highlight
{:on-press #(re-frame/dispatch
(if frozen-card?
[::keycard.login/reset-pin]
[:navigate-to :backup-seed]))}
[react/view {:flex-direction :row
:align-items :center}
[react/view {:width 14
:height 14
:background-color colors/gray
:border-radius 7
:align-items :center
:justify-content :center
:margin-right 9}
[react/text {:style {:color colors/white
:font-size 13
:font-weight "700"}}
"!"]]
[react/text {:style {:color colors/gray}
:accessibility-label :back-up-your-seed-phrase-warning}
(if frozen-card?
(i18n/label :t/your-card-is-frozen)
(i18n/label :t/back-up-your-seed-phrase))]]]])
(defn schedule-counter-reset [] [reanimated/view {:style (styles/value-container {:minimized minimized
(utils.utils/set-timeout :animation animation})
(fn [] :pointer-events :none}
(swap! updates-counter inc) [reanimated/view {:style {:justify-content :center}}
(when @(re-frame/subscribe [:wallet/refreshing-history?]) [quo/text {:animated? true
(schedule-counter-reset))) :weight :semi-bold
1000)) :style (styles/value-text {:minimized minimized})}
portfolio-value
[quo/text {:animated? true
:size :inherit
:weight :inherit
:color :secondary}
(str " " (:code currency))]]]]
(when-not minimized
[reanimated/view
[quo/text {:color :secondary}
(i18n/label :t/wallet-total-value)]])]))
(defn refresh-action [] (views/defview accounts [selected-account-atom]
(schedule-counter-reset) (views/letsubs [accounts [:multiaccount/visible-accounts]]
(re-frame/dispatch [:wallet.ui/pull-to-refresh-history])) ;keycard? [:keycard-multiaccount?]]
(do
(defn refresh-control [refreshing?] (reset! selected-account-atom (:address (first accounts)))
(reagent/as-element (let [accounts-data (for [account accounts]
[rn/refresh-control {:label (:name account)
{:refreshing (boolean refreshing?) :id (:address account)})]
:onRefresh refresh-action}])) [react/scroll-view {:horizontal true
:shows-horizontal-scroll-indicator false
:scroll-event-throttle 64
:margin-top 12
:margin-bottom 20}
[react/view {:flex-direction :row}
[quo2.tabs/tabs {:default-active (:address (first accounts))
:on-change #(reset! selected-account-atom %)
:data accounts-data}]
[quo2.button/button {:type :grey
:size 32
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content sheets/add-account
:content-height 260}])}
"Add account"]]]))))
(defn accounts-overview [] (defn accounts-overview []
(let [mnemonic @(re-frame/subscribe [:mnemonic])
;mainnet? @(re-frame/subscribe [:mainnet?])
selected-account-atom (reagent/atom nil)]
(fn []
[safe-area/consumer
(fn [insets]
[react/view {:style {:flex 1
:padding-top (:top insets)
:background-color (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/neutral-95)}}
[react/view {:padding-horizontal 20}
[react/view {:flex-direction :row :height 56 :align-items :center :justify-content :flex-end}
[quo2.button/button {:icon true
:size 32
:type :grey
:accessibility-label :accounts-qr-code
:on-press #(re-frame/dispatch
[::qr-scanner/scan-code
{:handler :wallet.send/qr-scanner-result}])}
:main-icons2/placeholder]
[react/view {:width 12}]
[quo2.button/button {:icon true
:size 32
:type :grey
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (sheets/accounts-options mnemonic)}])
:accessibility-label :accounts-more-options}
:main-icons2/placeholder]]
[total-value]
[accounts selected-account-atom]]
[account.views/account-new @selected-account-atom]])])))
(defn accounts-overview-old []
(let [mnemonic @(re-frame/subscribe [:mnemonic]) (let [mnemonic @(re-frame/subscribe [:mnemonic])
mainnet? @(re-frame/subscribe [:mainnet?])] mainnet? @(re-frame/subscribe [:mainnet?])]
[react/view [react/view
{:style {:flex 1}} {:style {:flex 1}}
[quo/animated-header [quo/animated-header
{:extended-header total-value {:extended-header total-value-old
:refresh-control refresh-control :refresh-control common/refresh-control
:refreshing-sub (re-frame/subscribe [:wallet/refreshing-history?]) :refreshing-sub (re-frame/subscribe [:wallet/refreshing-history?])
:refreshing-counter updates-counter :refreshing-counter common/updates-counter
:use-insets true :use-insets true
:right-accessories [{:on-press #(re-frame/dispatch :right-accessories [{:on-press #(re-frame/dispatch
[::qr-scanner/scan-code [::qr-scanner/scan-code
@ -235,9 +313,9 @@
{:content (sheets/accounts-options mnemonic)}]) {:content (sheets/accounts-options mnemonic)}])
:icon :main-icons/more :icon :main-icons/more
:accessibility-label :accounts-more-options}]} :accessibility-label :accounts-more-options}]}
[accounts] [accounts-old]
(when mainnet? (when mainnet?
[buy-crypto/banner]) [buy-crypto/banner])
[assets] [assets]
[react/view {:height 68}]] [react/view {:height 68}]]
[send-button]])) [send-button]]))

View File

@ -8,10 +8,10 @@
(defn separator-dark [] (defn separator-dark []
[react/view (styles/separator-dark)]) [react/view (styles/separator-dark)])
(defn token-icon [{:keys [style source image-style]}] (defn token-icon [{:keys [style source image-style width height]}]
[react/view {:style style} [react/view {:style style}
[react/image {:source (if (fn? source) (source) source) [react/image {:source (if (fn? source) (source) source)
:style (merge :style (merge
{:width 40 {:width (or width 40)
:height 40} :height (or height 40)}
image-style)}]]) image-style)}]])

View File

@ -6,7 +6,7 @@
[quo.core :as quo] [quo.core :as quo]
[status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts])) [status-im.ui.screens.wallet.accounts.common :as common]))
(views/defview assets [address] (views/defview assets [address]
(views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address] (views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address]
@ -15,7 +15,7 @@
(for [token tokens] (for [token tokens]
^{:key (str (:symbol token))} ^{:key (str (:symbol token))}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet.send/set-symbol (:symbol token)])} [react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet.send/set-symbol (:symbol token)])}
[wallet.accounts/render-asset token nil nil (:code currency)]])])) [common/render-asset token nil nil (:code currency)]])]))
(defn render-account [account _ _ {:keys [field event]}] (defn render-account [account _ _ {:keys [field event]}]
[quo/list-item [quo/list-item