From 748b0fcf092d4ddd4799308045a86077881cb1d9 Mon Sep 17 00:00:00 2001 From: Julien Eluard Date: Fri, 26 Jan 2018 10:29:36 +0100 Subject: [PATCH] [ISSUE #2883] Migrate wallet/request to latest mockups Signed-off-by: Goran Jovic --- src/status_im/chat/screen.cljs | 4 +- src/status_im/translations/en.cljs | 6 +- src/status_im/ui/components/colors.cljs | 1 + .../ui/components/common/common.cljs | 18 +-- .../ui/components/common/styles.cljs | 27 ++-- .../ui/components/qr_code_viewer/styles.cljs | 21 +-- .../ui/components/qr_code_viewer/views.cljs | 68 +++------ .../ui/components/status_bar/styles.cljs | 12 +- .../ui/components/status_bar/view.cljs | 2 +- src/status_im/ui/components/toolbar/view.cljs | 25 +++- src/status_im/ui/screens/main_tabs/views.cljs | 22 +-- .../ui/screens/profile/navigation.cljs | 11 +- src/status_im/ui/screens/profile/views.cljs | 39 +++-- src/status_im/ui/screens/views.cljs | 7 +- .../wallet/choose_recipient/events.cljs | 8 +- .../ui/screens/wallet/components.cljs | 39 +++-- .../ui/screens/wallet/components/views.cljs | 54 +++---- src/status_im/ui/screens/wallet/db.cljs | 9 +- src/status_im/ui/screens/wallet/events.cljs | 21 ++- .../ui/screens/wallet/main/styles.cljs | 118 --------------- .../ui/screens/wallet/main/views.cljs | 110 -------------- .../ui/screens/wallet/navigation.cljs | 4 +- .../ui/screens/wallet/request/events.cljs | 15 +- .../ui/screens/wallet/request/styles.cljs | 33 +++-- .../ui/screens/wallet/request/subs.cljs | 21 +-- .../ui/screens/wallet/request/views.cljs | 119 ++++++++------- src/status_im/ui/screens/wallet/send/db.cljs | 3 +- .../ui/screens/wallet/send/events.cljs | 4 +- .../ui/screens/wallet/send/views.cljs | 12 +- src/status_im/ui/screens/wallet/styles.cljs | 136 ++++++++++-------- src/status_im/ui/screens/wallet/subs.cljs | 6 - .../screens/wallet/transactions/events.cljs | 4 +- .../screens/wallet/transactions/styles.cljs | 22 --- .../ui/screens/wallet/transactions/subs.cljs | 10 +- .../ui/screens/wallet/transactions/views.cljs | 4 - src/status_im/ui/screens/wallet/views.cljs | 108 ++++++++++++-- src/status_im/utils/ethereum/tokens.cljs | 2 +- test/cljs/status_im/test/runner.cljs | 2 - test/cljs/status_im/test/wallet/events.cljs | 33 ----- 39 files changed, 466 insertions(+), 694 deletions(-) delete mode 100644 src/status_im/ui/screens/wallet/main/styles.cljs delete mode 100644 src/status_im/ui/screens/wallet/main/views.cljs delete mode 100644 test/cljs/status_im/test/wallet/events.cljs diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index f88d0e4b23..b17f5edc69 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -53,8 +53,8 @@ [toolbar/toolbar {} (when-not (or show-actions? creating?) (if (empty? accounts) - [toolbar/nav-clear-text (i18n/label :t/recover) - #(re-frame/dispatch [:navigate-to-modal :recover-modal])] + [toolbar/nav-clear-text {:handler #(re-frame/dispatch [:navigate-to-modal :recover-modal])} + (i18n/label :t/recover)] toolbar/default-nav-back)) [toolbar-content/toolbar-content-view] [toolbar-action show-actions?]] diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 6e43642f87..e0a57eadb4 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -318,8 +318,10 @@ :wallet-manage-assets "Manage Assets" :signing-phrase-description "Sign the transaction by entering your password. Make sure that the words above match your secret signing phrase" :wallet-insufficient-funds "Insufficient funds" - :request-transaction "Request transaction" + :receive "Receive" + :request-qr-legend "Share this code to receive assets" :send-request "Send request" + :send-transaction-request "Send a transaction request" :share "Share" :eth "ETH" :gwei "Gwei" @@ -352,6 +354,8 @@ :sign-later-text "Check the transaction history to sign this transaction" :not-applicable "Not applicable for unsigned transactions" :send-transaction "Send transaction" + :new-request "New request" + :request-transaction "Request transaction" :receive-transaction "Receive transaction" :new-transaction "New Transaction" :transaction-history "Transaction History" diff --git a/src/status_im/ui/components/colors.cljs b/src/status_im/ui/components/colors.cljs index be5e8cd0db..79c21735bb 100644 --- a/src/status_im/ui/components/colors.cljs +++ b/src/status_im/ui/components/colors.cljs @@ -5,6 +5,7 @@ (def white-transparent "rgba(255, 255, 255, 0.2)") ;; Used as icon color on dark background (def white-lighter-transparent "rgba(255, 255, 255, 0.6)") ;; Used for input placeholder color (def black "#000000") ;; Used as the default text color +(def black-transparent "#00000020") ;; Used as background color for rounded button on dark background (def gray "#939ba1") ;; Used as a background for a light foreground and as section header and secondary text color (def gray-light "#d9dae1") ;; Used as divider color (def gray-lighter "#eef2f5") ;; Used as a background or shadow diff --git a/src/status_im/ui/components/common/common.cljs b/src/status_im/ui/components/common/common.cljs index d9f687a5d2..219d7b6f81 100644 --- a/src/status_im/ui/components/common/common.cljs +++ b/src/status_im/ui/components/common/common.cljs @@ -1,12 +1,12 @@ (ns status-im.ui.components.common.common (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [status-im.ui.components.react :as react] + (:require [status-im.i18n :as i18n] + [status-im.ui.components.react :as react] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.context-menu :as context-menu] [status-im.ui.components.common.styles :as styles] [status-im.utils.ethereum.core :as ethereum] - [status-im.utils.platform :as platform] - [status-im.i18n :as i18n])) + [status-im.utils.platform :as platform])) (defn top-shadow [] (when platform/android? @@ -72,15 +72,3 @@ (if (ethereum/testnet? network-id) (i18n/label :t/testnet-text {:testnet (get-in ethereum/chains [(ethereum/chain-id->chain-keyword network-id) :name] "Unknown")}) (i18n/label :t/mainnet-text))]]])) - -(defn icon-or-label - "Renders a touchable icon on Android or a label or iOS." - [action-opts label-kw label-style icon-id icon-opts] - [react/touchable-highlight action-opts - (if platform/ios? - [react/view - [react/text {:style (merge styles/label-action-text label-style)} - (i18n/label label-kw)]] - [react/view styles/icon-action - [vector-icons/icon icon-id icon-opts]])]) - diff --git a/src/status_im/ui/components/common/styles.cljs b/src/status_im/ui/components/common/styles.cljs index e7d18b8a8f..5ec3d30e0e 100644 --- a/src/status_im/ui/components/common/styles.cljs +++ b/src/status_im/ui/components/common/styles.cljs @@ -6,7 +6,7 @@ (def gradient-top {:flexDirection :row :height 3 - :backgroundColor styles/color-light-gray}) + :backgroundColor colors/gray-lighter}) (def gradient-top-colors ["rgba(25, 53, 76, 0.01)" @@ -15,19 +15,19 @@ (def gradient-bottom {:flexDirection :row :height 2 - :backgroundColor styles/color-light-gray}) + :backgroundColor colors/gray-lighter}) (def gradient-bottom-colors ["rgba(25, 53, 76, 0.1)" "rgba(25, 53, 76, 0.01)"]) (def separator-wrapper - {:background-color styles/color-white}) + {:background-color colors/white}) (defstyle separator {:android {:height 0} :ios {:height 1 - :background-color styles/color-gray5 + :background-color colors/gray-light :opacity 0.5}}) (def list-separator @@ -41,20 +41,20 @@ :padding-right 16 :flex 1 :flex-direction :row - :ios {:background-color styles/color-white + :ios {:background-color colors/white :padding-top 19 :padding-bottom 15 :margin-top 16} - :android {:background-color styles/color-light-gray + :android {:background-color colors/gray-lighter :padding-top 20 :padding-bottom 17 :margin-top 8}}) (defstyle form-title-extend-container {:ios {:margin-top 16 - :background-color styles/color-white} + :background-color colors/white} :android {:margin-top 8 - :background-color styles/color-light-gray}}) + :background-color colors/gray-lighter}}) (def form-title-extend-button {:padding 16}) @@ -80,7 +80,7 @@ :android {:height 11}}) (defstyle list-header-footer-spacing - {:android {:background-color styles/color-white + {:android {:background-color colors/white :height 8}}) (def network-container @@ -91,7 +91,7 @@ (defn network-text [text-color] {:flex 1 - :color (or text-color styles/color-black) + :color (or text-color colors/black) :letter-spacing -0.2 :font-size 14 :margin-left 16}) @@ -109,10 +109,3 @@ :color colors/blue :ios {:font-size 15} :android {:font-size 14}}) - -(def icon-action - {:width 40 - :height 40 - :margin-right 4 - :align-items :center - :justify-content :center}) \ No newline at end of file diff --git a/src/status_im/ui/components/qr_code_viewer/styles.cljs b/src/status_im/ui/components/qr_code_viewer/styles.cljs index abd8026cde..f533d2c082 100644 --- a/src/status_im/ui/components/qr_code_viewer/styles.cljs +++ b/src/status_im/ui/components/qr_code_viewer/styles.cljs @@ -4,25 +4,21 @@ (def qr-code-hint {:color colors/gray - :padding-bottom 24 + :padding-top 24 + :padding-bottom 22 :text-align :center}) (def qr-code-padding 15) -(defn qr-code-container [dimensions] +(defn qr-code-container [width] {:background-color colors/white - :width (:width dimensions) + :width width :align-items :center :justify-content :center :padding qr-code-padding :border-radius 8}) -(def toolbar-done-text-ios - {:color colors/blue - :letter-spacing -0.2 - :font-size 17}) - (defstyle name-container {:flex 0.6 :flex-direction :column @@ -47,7 +43,6 @@ (def toolbar-action-icon-container {:width 40 :height 40 - :margin-right 16 :align-items :center :justify-content :center}) @@ -66,16 +61,14 @@ :justify-content :center}) (def qr-code - {:background-color colors/gray-lighter - :flex-grow 1 + {:flex-grow 1 :align-items :center :justify-content :center}) (def footer - {:background-color colors/gray-lighter - :flex-direction :row + {:flex-direction :row :justify-content :center - :padding-bottom 50}) + :padding-top 22}) (def wallet-info {:align-items :center diff --git a/src/status_im/ui/components/qr_code_viewer/views.cljs b/src/status_im/ui/components/qr_code_viewer/views.cljs index 0cf2e152d5..b05feb06b2 100644 --- a/src/status_im/ui/components/qr_code_viewer/views.cljs +++ b/src/status_im/ui/components/qr_code_viewer/views.cljs @@ -1,59 +1,29 @@ (ns status-im.ui.components.qr-code-viewer.views - (:require [re-frame.core :as re-frame] - [status-im.ui.components.react :as react] - [status-im.ui.components.icons.vector-icons :as vector-icons] - [status-im.ui.components.status-bar.view :as status-bar] - [status-im.ui.components.list-selection :as list-selection] - [status-im.ui.components.qr-code-viewer.styles :as styles] - [status-im.ui.components.common.common :as common] - [status-im.ui.components.common.styles :as common.styles] - [status-im.utils.platform :as platform] - [status-im.i18n :as i18n] + (:require [reagent.core :as reagent] [status-im.react-native.js-dependencies :as rn-dependencies] - [reagent.core :as r]) - (:require-macros [status-im.utils.views :refer [defview letsubs]])) + [status-im.ui.components.qr-code-viewer.styles :as styles] + [status-im.ui.components.react :as react])) (defn qr-code [props] - (r/create-element + (reagent/create-element rn-dependencies/qr-code (clj->js (merge {:inverted true} props)))) -(defn qr-viewer-toolbar [name qr-value] - [react/view styles/account-toolbar - [react/view styles/toolbar-contents - [react/view styles/toolbar-action-container - [common/icon-or-label {:on-press #(re-frame/dispatch [:navigate-back])} - :t/done styles/toolbar-done-text-ios :icons/close {:color :black}]] - [react/view styles/name-container - [react/text {:style styles/name-text - :number-of-lines 1} name]] - [react/view styles/toolbar-action-container - [react/touchable-highlight {:on-press #(list-selection/open-share {:message qr-value})} - [react/view styles/toolbar-action-icon-container - [vector-icons/icon :icons/share {:color :black}]]]]]]) - -(defn qr-viewer-body [qr-value dimensions] - [react/view {:style styles/qr-code - :on-layout #(let [layout (.. % -nativeEvent -layout)] - (re-frame/dispatch [:set-in [:qr-modal :dimensions] {:width (* 0.7 (.-width layout)) - :height (.-height layout)}]))} - [react/text {:style styles/qr-code-hint} (i18n/label :t/qr-code-public-key-hint)] - (when (:width dimensions) - [react/view {:style (styles/qr-code-container dimensions)} - [qr-code {:value qr-value - :size (- (min (:width dimensions) - (:height dimensions)) - (* 2 styles/qr-code-padding))}]])]) - -(defn qr-viewer-footer [qr-value] +(defn- footer [style value] [react/view styles/footer [react/view styles/wallet-info - [react/text {:style styles/hash-value-text} qr-value]]]) + [react/text {:style (merge styles/hash-value-text style)} + value]]]) -(defview qr-viewer [] - (letsubs [{:keys [qr-value dimensions contact]} [:get :qr-modal]] - [react/view styles/wallet-qr-code - [status-bar/status-bar {:type :modal}] - [qr-viewer-toolbar (:name contact) qr-value] - [qr-viewer-body qr-value dimensions] - [qr-viewer-footer qr-value]])) +(defn qr-code-viewer [{:keys [hint-style footer-style]} value hint legend] + {:pre [(not (nil? value))]} + (let [{:keys [width height]} (react/get-dimensions "window")] + [react/view {:style styles/qr-code} + [react/text {:style (merge styles/qr-code-hint hint-style)} + hint] + (when width + (let [size (int (* 0.7 (min width height)))] + [react/view {:style (styles/qr-code-container size)} + [qr-code {:value value + :size (- size (* 2 styles/qr-code-padding))}]])) + [footer footer-style legend]])) diff --git a/src/status_im/ui/components/status_bar/styles.cljs b/src/status_im/ui/components/status_bar/styles.cljs index e287c5a5d8..4be05fb0b9 100644 --- a/src/status_im/ui/components/status_bar/styles.cljs +++ b/src/status_im/ui/components/status_bar/styles.cljs @@ -39,23 +39,23 @@ ;; :modal (defstyle status-bar-modal {:ios (create-status-bar-style {:background-color "#2f3031"}) - :android (create-status-bar-style {:background-color styles/color-black})}) + :android (create-status-bar-style {:background-color colors/black})}) (defstyle view-modal {:ios (create-view-style {:background-color "#2f3031"}) - :android (create-view-style {:background-color styles/color-black + :android (create-view-style {:background-color colors/black :height 0})}) ;; :modal-white (defstyle status-bar-modal-white {:ios (create-status-bar-style {:background-color colors/white :bar-style "default"}) - :android (create-status-bar-style {:background-color styles/color-black + :android (create-status-bar-style {:background-color colors/black :bar-style "light-content"})}) (defstyle view-modal-white {:ios (create-view-style {:background-color colors/white}) - :android (create-view-style {:background-color styles/color-black + :android (create-view-style {:background-color colors/black :height 0})}) ;; :modal-wallet @@ -90,8 +90,8 @@ ;; :wallet (defstyle status-bar-wallet - {:ios (create-status-bar-style {:background-color colors/blue}) - :android (create-status-bar-style {:translucent? true})}) + {:ios (create-status-bar-style {:background-color colors/blue}) + :android (create-status-bar-style {:translucent? true})}) (def view-wallet (create-view-style {:background-color styles/color-blue4 diff --git a/src/status_im/ui/components/status_bar/view.cljs b/src/status_im/ui/components/status_bar/view.cljs index 03b2521677..8471f9bed1 100644 --- a/src/status_im/ui/components/status_bar/view.cljs +++ b/src/status_im/ui/components/status_bar/view.cljs @@ -12,7 +12,7 @@ :modal-wallet [styles/status-bar-modal-wallet styles/view-modal-wallet] :transaction [styles/status-bar-transaction styles/view-transaction] :wallet [styles/status-bar-wallet styles/view-wallet] - :wallet-tab [styles/status-bar-wallet-tab styles/view-wallet-tab] + :wallet-tab [styles/status-bar-wallet-tab styles/view-wallet-tab] [styles/status-bar-default styles/view-default])] [react/view [react/status-bar status-bar-style] diff --git a/src/status_im/ui/components/toolbar/view.cljs b/src/status_im/ui/components/toolbar/view.cljs index 9724a5f139..c2cd27289b 100644 --- a/src/status_im/ui/components/toolbar/view.cljs +++ b/src/status_im/ui/components/toolbar/view.cljs @@ -1,6 +1,7 @@ (ns status-im.ui.components.toolbar.view (:require [reagent.core :as reagent] [re-frame.core :as re-frame] + [status-im.i18n :as i18n] [status-im.ui.components.colors :as colors] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.list-selection :as list-selection] @@ -28,20 +29,30 @@ [vector-icons/icon icon icon-opts]]) (defn nav-text - ([text] (nav-text text nil)) - ([props text] (nav-text props text nil)) - ([props text handler] - [react/text (utils/deep-merge {:style (merge styles/item styles/item-text) :on-press (or handler #(re-frame/dispatch [:navigate-back]))} + ([text] (nav-text nil text)) + ([{:keys [handler] :as props} text] + [react/text (utils/deep-merge {:style (merge styles/item styles/item-text) + :on-press (or handler #(re-frame/dispatch [:navigate-back]))} props) text])) (defn nav-clear-text - ([text] (nav-clear-text text nil)) - ([text handler] - (nav-text styles/item-text-white-background text handler))) + ([text] (nav-clear-text nil text)) + ([props text] + (nav-text (merge props styles/item-text-white-background) text))) (def default-nav-back [nav-button actions/default-back]) +(defn default-done + "Renders a touchable icon on Android or a label or iOS." + [{:keys [icon] :as props}] + (if platform/ios? + [react/view + [nav-text props + (i18n/label :t/done)]] + [react/view + [nav-button (merge props {:icon (or icon :icons/close)})]])) + ;; Content (defn content-wrapper [content] diff --git a/src/status_im/ui/screens/main_tabs/views.cljs b/src/status_im/ui/screens/main_tabs/views.cljs index fc848534bc..33aac210d7 100644 --- a/src/status_im/ui/screens/main_tabs/views.cljs +++ b/src/status_im/ui/screens/main_tabs/views.cljs @@ -1,15 +1,15 @@ (ns status-im.ui.screens.main-tabs.views (:require-macros [status-im.utils.views :as views]) - (:require [status-im.ui.components.icons.vector-icons :as vector-icons] + (:require [status-im.i18n :as i18n] + [re-frame.core :as re-frame] + [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.react :as react] [status-im.ui.components.status-bar.view :as status-bar.view] [status-im.ui.components.styles :as common.styles] - [status-im.i18n :as i18n] - [status-im.ui.screens.home.views :as home.views] - [status-im.ui.screens.profile.views :as profile.views] - [status-im.ui.screens.wallet.main.views :as wallet.views] - [status-im.ui.screens.main-tabs.styles :as styles] - [re-frame.core :as re-frame])) + [status-im.ui.screens.home.views :as home] + [status-im.ui.screens.profile.views :as profile] + [status-im.ui.screens.wallet.views :as wallet] + [status-im.ui.screens.main-tabs.styles :as styles])) (def tabs-list-data [{:view-id :home @@ -37,7 +37,7 @@ (def tabs-list (map #(update % :content tab-content) tabs-list-data)) -(defn tab [view-id content active?] +(defn- tab [view-id content active?] [react/touchable-highlight {:style common.styles/flex :disabled active? :on-press #(re-frame/dispatch [:navigate-to-tab view-id])} @@ -59,7 +59,7 @@ {:enabled? (= :home view-id) :preview [react/view {}]} [react/navigation-wrapper - {:component home.views/home + {:component home/home :views :home :current-view view-id}]] @@ -67,7 +67,7 @@ {:enabled? (= :wallet view-id) :preview [react/view {}]} [react/navigation-wrapper - {:component wallet.views/wallet + {:component wallet/wallet :views :wallet :current-view view-id}]] @@ -75,7 +75,7 @@ {:enabled? (= :my-profile view-id) :preview [react/view {}]} [react/navigation-wrapper - {:component profile.views/my-profile + {:component profile/my-profile :views :my-profile :current-view view-id}]] [tabs view-id]]])) diff --git a/src/status_im/ui/screens/profile/navigation.cljs b/src/status_im/ui/screens/profile/navigation.cljs index dc14adaa20..ecbf3bed01 100644 --- a/src/status_im/ui/screens/profile/navigation.cljs +++ b/src/status_im/ui/screens/profile/navigation.cljs @@ -3,10 +3,9 @@ ;;TODO(goranjovic) - replace this with an atomic navigation event that calls functions, not dispatch ;; possibly use the generic event, see https://github.com/status-im/status-react/issues/2987 -(defmethod navigation/preload-data! :qr-viewer - [{:accounts/keys [current-account-id] :as db} [_ _ {:keys [contact qr-source qr-value]}]] - (update db :qr-modal #(merge % {:contact (or contact - (get-in db [:accounts/accounts current-account-id])) - :qr-source qr-source - :qr-value qr-value}))) +(defmethod navigation/preload-data! :profile-qr-viewer + [{:accounts/keys [current-account-id] :as db} [_ _ {:keys [contact source value]}]] + (update db :qr-modal #(merge % {:contact (or contact (get-in db [:accounts/accounts current-account-id])) + :source source + :value value}))) diff --git a/src/status_im/ui/screens/profile/views.cljs b/src/status_im/ui/screens/profile/views.cljs index f2ffdd9ba9..a2f87696c2 100644 --- a/src/status_im/ui/screens/profile/views.cljs +++ b/src/status_im/ui/screens/profile/views.cljs @@ -1,6 +1,8 @@ (ns status-im.ui.screens.profile.views + (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [clojure.string :as string] [re-frame.core :as re-frame] + [status-im.i18n :as i18n] [status-im.ui.components.action-button.action-button :as action-button] [status-im.ui.components.action-button.styles :as action-button.styles] [status-im.ui.components.chat-icon.screen :as chat-icon.screen] @@ -8,6 +10,7 @@ [status-im.ui.components.common.styles :as common.styles] [status-im.ui.components.context-menu :as context-menu] [status-im.ui.components.list-selection :as list-selection] + [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] [status-im.ui.components.react :as react] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.status-bar.view :as status-bar] @@ -15,7 +18,6 @@ [status-im.ui.components.colors :as colors] [status-im.ui.components.toolbar.actions :as actions] [status-im.ui.components.toolbar.view :as toolbar] - [status-im.i18n :as i18n] [status-im.ui.screens.profile.styles :as styles] [status-im.ui.components.colors :as colors] [status-im.utils.utils :as utils] @@ -23,10 +25,7 @@ [status-im.utils.datetime :as time] [status-im.utils.config :as config] [status-im.utils.platform :as platform] - [status-im.protocol.core :as protocol] - [re-frame.core :as re-frame] - [status-im.ui.components.camera :as camera]) - (:require-macros [status-im.utils.views :refer [defview letsubs]])) + [status-im.protocol.core :as protocol])) (defn my-profile-toolbar [] [toolbar/toolbar {} @@ -42,8 +41,9 @@ [toolbar/toolbar {} nil [toolbar/content-title ""] - [common/icon-or-label {:on-press #(re-frame/dispatch [:my-profile/save-profile])} - :t/done {} :icons/ok {:color colors/blue}]]) + [toolbar/default-done {:handler #(re-frame/dispatch [:my-profile/save-profile]) + :icon :icons/ok + :icon-opts {:color colors/blue}}]]) (defn profile-toolbar [contact] [toolbar/toolbar {} @@ -154,10 +154,27 @@ nil styles/profile-info-item-button])]) -(defn show-qr [contact qr-source qr-value] - #(re-frame/dispatch [:navigate-to :qr-viewer {:contact contact - :qr-source qr-source - :qr-value qr-value}])) +(defn- toolbar [label value] + [toolbar/toolbar {} + [toolbar/default-done {:icon-opts {:color colors/black}}] + [toolbar/content-title label] + [toolbar/actions [{:icon :icons/share + :icon-opts {:color :black} + :handler #(list-selection/open-share {:message value})}]]]) + +(defview qr-viewer [] + (letsubs [{:keys [value contact]} [:get :qr-modal]] + [react/view {:flex-grow 1 + :flex-direction :column} + [status-bar/status-bar {:type :modal}] + [toolbar (:name contact) value] + [qr-code-viewer/qr-code-viewer {} + value (i18n/label :t/qr-code-public-key-hint) (str value)]])) + +(defn- show-qr [contact source value] + #(re-frame/dispatch [:navigate-to :profile-qr-viewer {:contact contact + :source source + :value value}])) (defn profile-options [contact k text] (into [] diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 23b1eebcfd..7cdaebfbda 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -31,11 +31,9 @@ [status-im.ui.screens.profile.views :as profile] [status-im.ui.screens.profile.photo-capture.views :refer [profile-photo-capture]] - [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] - [status-im.ui.screens.wallet.send.views :refer [send-transaction send-transaction-modal]] [status-im.ui.screens.wallet.choose-recipient.views :refer [choose-recipient]] - [status-im.ui.screens.wallet.request.views :refer [request-transaction]] + [status-im.ui.screens.wallet.request.views :refer [request-transaction send-transaction-request]] [status-im.ui.screens.wallet.components.views :as wallet.components] [status-im.ui.screens.wallet.send.views :as wallet.send] [status-im.ui.screens.wallet.settings.views :as wallet-settings] @@ -141,6 +139,7 @@ :wallet-send-transaction send-transaction :wallet-transaction-sent transaction-sent :wallet-request-transaction request-transaction + :wallet-send-transaction-request send-transaction-request (:transactions-history :unsigned-transactions) wallet-transactions/transactions :wallet-transaction-details wallet-transactions/transaction-details :wallet-send-assets wallet.components/send-assets @@ -177,7 +176,7 @@ :recent-recipients recent-recipients :recipient-qr-code recipient-qr-code :contact-code contact-code - :qr-viewer qr-code-viewer/qr-viewer + :profile-qr-viewer profile/qr-viewer (throw (str "Unknown view: " current-view)))] [(if android? menu-context view) common-styles/flex [view common-styles/flex diff --git a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs index 3b29668dda..a80ba0f9a9 100644 --- a/src/status_im/ui/screens/wallet/choose_recipient/events.cljs +++ b/src/status_im/ui/screens/wallet/choose_recipient/events.cljs @@ -13,11 +13,11 @@ toggled-state (if (= :on flashlight-state) :off :on)] (assoc-in db [:wallet :send-transaction :camera-flashlight] toggled-state)))) -(defn- fill-request-details [db {:keys [address name value symbol gas gasPrice]}] +(defn- fill-request-details [db {:keys [address name value symbol gas gasPrice whisper-identity]}] {:pre [(not (nil? address))]} (update-in db [:wallet :send-transaction] - #(cond-> (assoc % :to address :to-name name) + #(cond-> (assoc % :to address :to-name name :whisper-identity whisper-identity) value (assoc :amount value) symbol (assoc :symbol symbol) gas (assoc :gas (money/bignumber gas)) @@ -50,6 +50,6 @@ (handlers/register-handler-fx :wallet/fill-request-from-contact - (fn [{db :db} [_ {:keys [address name]}]] - {:db (fill-request-details db {:address address :name name}) + (fn [{db :db} [_ {:keys [address name whisper-identity]}]] + {:db (fill-request-details db {:address address :name name :whisper-identity whisper-identity}) :dispatch [:navigate-back]})) diff --git a/src/status_im/ui/screens/wallet/components.cljs b/src/status_im/ui/screens/wallet/components.cljs index 6be9b04d52..eff8502a3e 100644 --- a/src/status_im/ui/screens/wallet/components.cljs +++ b/src/status_im/ui/screens/wallet/components.cljs @@ -24,18 +24,30 @@ props) text]) -(defn- toolbar [action title] - [toolbar/toolbar {:style styles/toolbar} - [toolbar/nav-button action] - [toolbar/content-title {:color :white} - title]]) +(def default-action (actions/back-white actions/default-handler)) -(defn simple-screen [title content] - [react/view {:flex 1 :background-color colors/blue} - [status-bar/status-bar {:type :wallet}] - [toolbar (actions/back-white actions/default-handler) - title] - content]) +(defn- toolbar + ([title] (toolbar default-action title)) + ([action title] (toolbar action title nil)) + ([action title options] + [toolbar/toolbar {:style styles/toolbar} + [toolbar/nav-button action] + [toolbar/content-title {:color :white} + title] + options])) + +(defn- top-view [avoid-keyboard?] + (if avoid-keyboard? + react/keyboard-avoiding-view + react/view)) + +(defn simple-screen + ([toolbar content] (simple-screen nil toolbar content)) + ([{:keys [avoid-keyboard? status-bar-type]} toolbar content] + [(top-view avoid-keyboard?) {:flex 1 :background-color colors/blue} + [status-bar/status-bar {:type (or status-bar-type :wallet)}] + toolbar + content])) (defn- cartouche-content [{:keys [disabled?]} content] [react/view {:style (styles/cartouche-content-wrapper disabled?)} @@ -67,9 +79,6 @@ s]) (defn cartouche-text-content [primary secondary] - [react/view {:flex-direction :row - :justify-content :space-between - :padding-horizontal 15 - :padding-vertical 15} + [react/view styles/cartouche-text-wrapper [cartouche-primary-text primary] [cartouche-secondary-text secondary]]) diff --git a/src/status_im/ui/screens/wallet/components/views.cljs b/src/status_im/ui/screens/wallet/components/views.cljs index e33cae0648..ee56c3ef74 100644 --- a/src/status_im/ui/screens/wallet/components/views.cljs +++ b/src/status_im/ui/screens/wallet/components/views.cljs @@ -18,7 +18,7 @@ [status-im.ui.screens.wallet.components.animations :as animations] [status-im.ui.screens.wallet.components.styles :as styles] [status-im.ui.screens.wallet.choose-recipient.views :as choose-recipient] - [status-im.ui.screens.wallet.main.views :as main] + [status-im.ui.screens.wallet.views :as wallet] [status-im.ui.screens.wallet.utils :as wallet.utils] [status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.tokens :as tokens] @@ -66,10 +66,11 @@ (views/letsubs [network [:network] visible-tokens [:wallet.settings/visible-tokens] balance [:balance]] - [components/simple-screen (i18n/label :t/wallet-assets) + [components/simple-screen + [components/toolbar (i18n/label :t/wallet-assets)] [react/view {:style (assoc components.styles/flex :background-color :white)} [list/flat-list {:default-separator? true - :data (concat [tokens/ethereum] (main/current-tokens visible-tokens network)) + :data (concat [tokens/ethereum] (wallet/current-tokens visible-tokens network)) :render-fn #(render-token % balance type)}]]])) (defn send-assets [] @@ -130,7 +131,7 @@ (views/defview recent-recipients [] (views/letsubs [contacts [:contacts-filtered :all-added-people-contacts]] [components/simple-screen - (i18n/label :t/recipient) + [components/toolbar (i18n/label :t/recipient)] [react/view styles/recent-recipients [list/flat-list {:data contacts :render-fn render-contact}]]])) @@ -138,19 +139,18 @@ (defn contact-code [] (let [content (reagent/atom nil)] (fn [] - [react/view components.styles/flex - [components/simple-screen - (i18n/label :t/recipient) - [react/view components.styles/flex - [components/cartouche {} - (i18n/label :t/recipient) - [components/text-input {:multiline true - :placeholder (i18n/label :t/recipient-code) - :on-change-text #(reset! content %)}]] - [bottom-buttons/bottom-button - [button/button {:disabled? (string/blank? @content) - :on-press #(re-frame/dispatch [:wallet/fill-request-from-url @content])} - (i18n/label :t/done)]]]]]))) + [components/simple-screen {:avoid-keyboard? true} + [components/toolbar (i18n/label :t/recipient)] + [react/view components.styles/flex + [components/cartouche {} + (i18n/label :t/recipient) + [components/text-input {:multiline true + :placeholder (i18n/label :t/recipient-code) + :on-change-text #(reset! content %)}]] + [bottom-buttons/bottom-button + [button/button {:disabled? (string/blank? @content) + :on-press #(re-frame/dispatch [:wallet/fill-request-from-url @content])} + (i18n/label :t/done)]]]]))) (defn recipient-qr-code [] [choose-recipient/choose-recipient]) @@ -159,17 +159,19 @@ (re-frame/dispatch [:request-permissions [:camera] #(re-frame/dispatch [:navigate-to :recipient-qr-code])])) -(defn- on-choose-recipient [] +(defn- on-choose-recipient [contact-only?] (list-selection/show {:title (i18n/label :t/wallet-choose-recipient) - :options [{:label (i18n/label :t/recent-recipients) - :action #(re-frame/dispatch [:navigate-to :recent-recipients])} - {:label (i18n/label :t/scan-qr) - :action request-camera-permissions} - {:label (i18n/label :t/enter-contact-code) - :action #(re-frame/dispatch [:navigate-to :contact-code])}]})) + :options (concat + [{:label (i18n/label :t/recent-recipients) + :action #(re-frame/dispatch [:navigate-to :recent-recipients])}] + (when-not contact-only? + [{:label (i18n/label :t/scan-qr) + :action request-camera-permissions} + {:label (i18n/label :t/enter-contact-code) + :action #(re-frame/dispatch [:navigate-to :contact-code])}]))})) -(defn recipient-selector [{:keys [name address disabled?]}] - [components/cartouche {:on-press on-choose-recipient :disabled? disabled? :icon :icons/dots-horizontal} +(defn recipient-selector [{:keys [name address disabled? contact-only?]}] + [components/cartouche {:on-press #(on-choose-recipient contact-only?) :disabled? disabled? :icon :icons/dots-horizontal} (i18n/label :t/wallet-choose-recipient) (if name [recipient-contact address name] diff --git a/src/status_im/ui/screens/wallet/db.cljs b/src/status_im/ui/screens/wallet/db.cljs index ed364ae63e..6484f47c04 100644 --- a/src/status_im/ui/screens/wallet/db.cljs +++ b/src/status_im/ui/screens/wallet/db.cljs @@ -6,22 +6,15 @@ status-im.ui.screens.wallet.send.db [status-im.utils.money :as money])) -;; (angusiguess) If we add more error types we can treat them as 'one-of' the following -(spec/def :wallet/error #{:error}) - (spec/def :wallet.send/recipient string?) (spec/def :wallet/send (spec/keys :req-un [:wallet.send/recipient])) -(spec/def :wallet/wallet (spec/keys :opt [:wallet/error] - :opt-un [:wallet/send-transaction :wallet/request-transaction])) +(spec/def :wallet/wallet (spec/keys :opt-un [:wallet/send-transaction :wallet/request-transaction])) ;; Placeholder namespace for wallet specs, which are a WIP depending on data ;; model we decide on for balances, prices, etc. -;; TODO(oskarth): spec for balance as BigNumber -;; TODO(oskarth): Spec for prices as as: {:from ETH, :to USD, :price 290.11, :last-day 304.17} - (defn- too-precise-amount? [amount] (let [amount-splited (string/split amount #"[.]")] (and (= (count amount-splited) 2) (> (count (last amount-splited)) 18)))) diff --git a/src/status_im/ui/screens/wallet/events.cljs b/src/status_im/ui/screens/wallet/events.cljs index 6b013061c2..35b90fe69d 100644 --- a/src/status_im/ui/screens/wallet/events.cljs +++ b/src/status_im/ui/screens/wallet/events.cljs @@ -1,8 +1,6 @@ (ns status-im.ui.screens.wallet.events (:require [re-frame.core :as re-frame :refer [dispatch reg-fx]] [status-im.i18n :as i18n] - [status-im.native-module.core :as status] - [status-im.ui.screens.wallet.db :as wallet.db] [status-im.ui.screens.wallet.navigation] [status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.erc20 :as erc20] @@ -10,7 +8,6 @@ [status-im.utils.handlers :as handlers] [status-im.utils.prices :as prices] [status-im.utils.transactions :as transactions] - [status-im.utils.utils :as utils] [taoensso.timbre :as log] status-im.ui.screens.wallet.request.events)) @@ -51,8 +48,8 @@ (fn [{:keys [web3 account-id success-event error-event]}] (get-balance {:web3 web3 :account-id account-id - :on-success #(dispatch [success-event %]) - :on-error #(dispatch [error-event %])}))) + :on-success #(re-frame/dispatch [success-event %]) + :on-error #(re-frame/dispatch [error-event %])}))) (reg-fx :get-tokens-balance @@ -62,16 +59,16 @@ (get-token-balance {:web3 web3 :contract contract :account-id account-id - :on-success #(dispatch [success-event symbol %]) - :on-error #(dispatch [error-event %])}))))) + :on-success #(re-frame/dispatch [success-event symbol %]) + :on-error #(re-frame/dispatch [error-event %])}))))) (reg-fx :get-transactions (fn [{:keys [network account-id success-event error-event]}] (transactions/get-transactions network account-id - #(dispatch [success-event %]) - #(dispatch [error-event %])))) + #(re-frame/dispatch [success-event %]) + #(re-frame/dispatch [error-event %])))) ;; TODO(oskarth): At some point we want to get list of relevant assets to get prices for (reg-fx @@ -79,8 +76,8 @@ (fn [{:keys [from to success-event error-event]}] (prices/get-prices from to - #(dispatch [success-event %]) - #(dispatch [error-event %])))) + #(re-frame/dispatch [success-event %]) + #(re-frame/dispatch [error-event %])))) ;; Handlers @@ -200,7 +197,7 @@ (handlers/register-handler-fx :wallet/discard-unsigned-transaction-with-confirmation - (fn [cofx [_ transaction-id]] + (fn [_ [_ transaction-id]] {:show-confirmation {:title (i18n/label :t/transactions-delete) :content (i18n/label :t/transactions-delete-content) :confirm-button-text (i18n/label :t/confirm) diff --git a/src/status_im/ui/screens/wallet/main/styles.cljs b/src/status_im/ui/screens/wallet/main/styles.cljs deleted file mode 100644 index e560502d0a..0000000000 --- a/src/status_im/ui/screens/wallet/main/styles.cljs +++ /dev/null @@ -1,118 +0,0 @@ -(ns status-im.ui.screens.wallet.main.styles - (:require-macros [status-im.utils.styles :refer [defstyle]]) - (:require [status-im.ui.components.styles :as styles] - [status-im.ui.components.colors :as colors])) - -;; Toolbar - -(def toolbar-title-container - {:flex-direction :row}) - -(def toolbar-title-text - {:flex -1 - :color colors/white - :font-size 17}) - -(def toolbar-icon - {:width 24 - :height 24}) - -(def toolbar-title-icon - (merge toolbar-icon {:opacity 0.4})) - -;; Main section - -(def main-section - {:background-color colors/blue}) - -(def total-balance-container - {:align-items :center - :justify-content :center}) - -(def total-balance - {:flex-direction :row}) - -(def total-balance-value - {:font-size 37 - :color colors/white}) - -(def total-value - {:font-size 14 - :color styles/color-white-transparent}) - -(defstyle total-balance-currency - {:font-size 37 - :margin-left 9 - :color styles/color-white-transparent-5 - :android {:letter-spacing 1.5} - :ios {:letter-spacing 1.16}}) - -(defstyle buttons - {:margin-top 34 - :android {:margin-horizontal 21} - :ios {:margin-horizontal 30}}) - -(defstyle main-button-text - {:padding-vertical 13 - :padding-horizontal nil - :android {:font-size 13 - :letter-spacing 0.46} - :ios {:font-size 15 - :letter-spacing -0.2}}) - -;; Actions section - -(def action-section - {:background-color colors/blue}) - -(def action - {:background-color colors/white-transparent - :border-radius 50}) - -(def action-label - {:color :white}) - -(def action-separator - {:height 1 - :background-color colors/white-light-transparent - :margin-left 70}) - -;; Assets section - -(def asset-section - {:flex 1 - :padding-vertical 16}) - -(def asset-section-title - {:font-size 14 - :margin-left 16 - :color styles/color-gray4}) - -(def asset-item-value-container - {:flex 1 - :flex-direction :row - :align-items :center}) - -(def asset-item-value - {:flex -1 - :font-size 16 - :color styles/color-black}) - -(defstyle add-asset-icon - {:flex 1 - :justify-content :center - :align-items :center - :width 40 - :height 40 - :border-radius 32 - :ios {:background-color styles/color-blue4-transparent}}) - -(defstyle add-asset-text - {:font-size 16 - :ios {:color colors/blue} - :android {:color styles/color-black}}) - -(def asset-item-currency - {:font-size 16 - :color styles/color-gray4 - :margin-left 6}) diff --git a/src/status_im/ui/screens/wallet/main/views.cljs b/src/status_im/ui/screens/wallet/main/views.cljs deleted file mode 100644 index 2e572a2670..0000000000 --- a/src/status_im/ui/screens/wallet/main/views.cljs +++ /dev/null @@ -1,110 +0,0 @@ -(ns status-im.ui.screens.wallet.main.views - (:require-macros [status-im.utils.views :refer [defview letsubs]]) - (:require [re-frame.core :as re-frame] - [status-im.i18n :as i18n] - [status-im.ui.components.styles :as components.styles] - [status-im.ui.components.list.views :as list] - [status-im.ui.components.react :as react] - [status-im.ui.components.toolbar.actions :as act] - [status-im.ui.components.toolbar.view :as toolbar] - [status-im.ui.screens.wallet.main.styles :as styles] - [status-im.ui.screens.wallet.styles :as wallet.styles] - [status-im.ui.screens.wallet.utils :as wallet.utils] - [status-im.ui.screens.wallet.views :as wallet.views] - [status-im.utils.config :as config] - [status-im.utils.ethereum.core :as ethereum] - [status-im.utils.ethereum.tokens :as tokens] - [status-im.utils.platform :as platform])) - -(defn toolbar-view [] - [toolbar/toolbar {:style wallet.styles/toolbar :flat? true} - nil - [toolbar/content-wrapper] - [toolbar/actions - [(assoc (act/opts [{:label (i18n/label :t/wallet-manage-assets) - :action #(re-frame/dispatch [:navigate-to-modal :wallet-settings-assets])}]) - :icon-opts {:color :white})]]]) - -(defn- total-section [usd-value syncing? error-message] - [react/view {:style styles/main-section} - (if syncing? - wallet.views/wallet-syncing - (when error-message - wallet.views/error-message-view)) - [react/view {:style styles/total-balance-container} - [react/view {:style styles/total-balance} - [react/text {:style styles/total-balance-value} usd-value] - [react/text {:style styles/total-balance-currency} (i18n/label :t/usd-currency)]] - [react/text {:style styles/total-value} (i18n/label :t/wallet-total-value)]]]) - -(defn- render-action [{:keys [label icon action]}] - [react/touchable-highlight {:on-press action} - [react/view - [list/item - [list/item-icon {:icon icon :style styles/action :icon-opts {:color :white}}] - [list/item-primary-only {:style styles/action-label} - label] - list/item-icon-forward]]]) - -(def actions - [{:label (i18n/label :t/send-transaction) - :icon :icons/arrow-right - :action #(re-frame/dispatch [:navigate-to :wallet-send-transaction])} - {:label (i18n/label :t/receive-transaction) - :icon :icons/arrow-left - :action #(re-frame/dispatch [:navigate-to :wallet-request-transaction])} - {:label (i18n/label :t/transaction-history) - :icon :icons/transaction-history - :action #(re-frame/dispatch [:navigate-to :transactions-history])}]) - -(defn- action-section [] - [react/view styles/action-section - [list/flat-list - {:separator (when platform/ios? [react/view styles/action-separator]) - :data actions - :render-fn render-action}]]) - -(defn- render-asset [{:keys [symbol icon decimals amount]}] - [react/view - [list/item - [list/item-image icon] - [react/view {:style styles/asset-item-value-container} - [react/text {:style styles/asset-item-value - :number-of-lines 1 - :ellipsize-mode :tail} - (wallet.utils/format-amount amount decimals)] - [react/text {:style styles/asset-item-currency - :uppercase? true - :number-of-lines 1} - (clojure.core/name symbol)]]]]) - -(defn- current-tokens [visible-tokens network] - (filter #(contains? visible-tokens (:symbol %)) (tokens/tokens-for (ethereum/network->chain-keyword network)))) - -(defn- asset-section [network balance visible-tokens prices-loading? balance-loading?] - (let [tokens (current-tokens visible-tokens network) - assets (map #(assoc % :amount (get balance (:symbol %))) (concat [tokens/ethereum] tokens))] - [react/view styles/asset-section - [react/text {:style styles/asset-section-title} (i18n/label :t/wallet-assets)] - [list/flat-list - {:default-separator? true - :data assets - :render-fn render-asset - :on-refresh #(re-frame/dispatch [:update-wallet (map :symbol tokens)]) - :refreshing (boolean (or prices-loading? balance-loading?))}]])) - -(defview wallet [] - (letsubs [network [:network] - balance [:balance] - visible-tokens [:wallet.settings/visible-tokens] - portfolio-value [:portfolio-value] - prices-loading? [:prices-loading?] - syncing? [:syncing?] - balance-loading? [:wallet/balance-loading?] - error-message [:wallet/error-message?]] - [react/view {:style wallet.styles/wallet-container} - [toolbar-view] - [react/view components.styles/flex - [total-section portfolio-value syncing? error-message] - [action-section] - [asset-section network balance visible-tokens prices-loading? balance-loading?]]])) diff --git a/src/status_im/ui/screens/wallet/navigation.cljs b/src/status_im/ui/screens/wallet/navigation.cljs index 432b0aa9ef..47ec962627 100644 --- a/src/status_im/ui/screens/wallet/navigation.cljs +++ b/src/status_im/ui/screens/wallet/navigation.cljs @@ -19,7 +19,9 @@ [db [event]] (if (= event :navigate-back) db - (update db :wallet dissoc :request-transaction))) + (-> db + (update :wallet dissoc :request-transaction) + (assoc-in [:wallet :send-transaction] db/transaction-send-default)))) (defmethod navigation/preload-data! :wallet-send-transaction [db [event]] diff --git a/src/status_im/ui/screens/wallet/request/events.cljs b/src/status_im/ui/screens/wallet/request/events.cljs index a9097bccbf..3312344cf8 100644 --- a/src/status_im/ui/screens/wallet/request/events.cljs +++ b/src/status_im/ui/screens/wallet/request/events.cljs @@ -18,13 +18,19 @@ (handlers/register-handler-fx :wallet-send-request [re-frame/trim-v] - (fn [{{:keys [wallet]} :db} [{:keys [whisper-identity]}]] + (fn [_ [whisper-identity amount]] + (assert whisper-identity) {:dispatch-n [[:navigate-back] [:navigate-to-clean :home] [:add-chat-loaded-event whisper-identity - [::wallet-send-chat-request (some-> wallet :request-transaction :amount money/wei->ether str)]] + [::wallet-send-chat-request (str (money/wei->ether amount))]] [:start-chat whisper-identity]]})) +(handlers/register-handler-fx + :wallet.request/set-recipient + (fn [{:keys [db]} [_ s]] + {:db (assoc-in db [:wallet :request-transaction :to] s)})) + (handlers/register-handler-fx :wallet.request/set-and-validate-amount (fn [{:keys [db]} [_ amount]] @@ -32,8 +38,3 @@ {:db (-> db (assoc-in [:wallet :request-transaction :amount] (money/ether->wei value)) (assoc-in [:wallet :request-transaction :amount-error] error))}))) - -(handlers/register-handler-fx - :wallet.request/set-symbol - (fn [{:keys [db]} [_ s]] - {:db (assoc-in db [:wallet :request-transaction :symbol] s)})) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/request/styles.cljs b/src/status_im/ui/screens/wallet/request/styles.cljs index f7ffaa61ce..ebbd16c43b 100644 --- a/src/status_im/ui/screens/wallet/request/styles.cljs +++ b/src/status_im/ui/screens/wallet/request/styles.cljs @@ -1,16 +1,25 @@ (ns status-im.ui.screens.wallet.request.styles - (:require-macros [status-im.utils.styles :refer [defstyle]]) - (:require [status-im.ui.components.styles :as styles])) + (:require [status-im.ui.components.colors :as colors])) -(def network-container - {:flex 1 - :align-items :center}) +(def hint + {:color colors/white-lighter-transparent}) -(def qr-container - {:margin-top 8 - :padding 16 - :background-color styles/color-white - :border-radius 8}) +(def footer + {:color colors/white}) -(def share-icon-container - {:margin-right 8}) +(def bottom-buttons + {:background-color colors/blue}) + +(def request-wrapper + {:flex 1 + :flex-direction :column + :margin-horizontal 16}) + +;; Request panel + +(def request-details-wrapper + {:padding-bottom 60}) + +(def send-request + {:background-color colors/black-transparent + :margin-bottom 12}) diff --git a/src/status_im/ui/screens/wallet/request/subs.cljs b/src/status_im/ui/screens/wallet/request/subs.cljs index 7ac225d5e5..0fbc839de7 100644 --- a/src/status_im/ui/screens/wallet/request/subs.cljs +++ b/src/status_im/ui/screens/wallet/request/subs.cljs @@ -1,23 +1,6 @@ (ns status-im.ui.screens.wallet.request.subs - (:require [re-frame.core :as re-frame] - [status-im.utils.ethereum.tokens :as tokens])) + (:require [re-frame.core :as re-frame])) -(re-frame/reg-sub ::request-transaction +(re-frame/reg-sub :wallet.request/transaction :<- [:wallet] :request-transaction) - -(re-frame/reg-sub :wallet.request/symbol - :<- [::request-transaction] - (fn [transaction] - (or (:symbol transaction) :ETH))) - -(re-frame/reg-sub - :wallet.request/request-enabled? - :<- [:get-in [:wallet :request-transaction :amount]] - :<- [:get-in [:wallet :request-transaction :amount-error]] - :<- [:wallet.request/symbol] - (fn [[amount amount-error symbol]] - (and - (or (nil? symbol) (tokens/ethereum? symbol)) - (nil? amount-error) - (not (nil? amount))))) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/request/views.cljs b/src/status_im/ui/screens/wallet/request/views.cljs index 0290031bad..d2f946efc0 100644 --- a/src/status_im/ui/screens/wallet/request/views.cljs +++ b/src/status_im/ui/screens/wallet/request/views.cljs @@ -2,80 +2,79 @@ (:require-macros [status-im.utils.views :as views]) (:require [re-frame.core :as re-frame] [status-im.i18n :as i18n] + [status-im.ui.components.bottom-buttons.view :as bottom-buttons] + [status-im.ui.components.button.view :as button] [status-im.ui.components.common.common :as common] [status-im.ui.components.icons.vector-icons :as vector-icons] + [status-im.ui.components.list-selection :as list-selection] + [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] [status-im.ui.components.react :as react] [status-im.ui.components.status-bar.view :as status-bar] - [status-im.ui.components.styles :as components.styles] - [status-im.ui.components.qr-code-viewer.views :as qr-code-viewer] [status-im.ui.components.toolbar.actions :as actions] [status-im.ui.components.toolbar.view :as toolbar] - [status-im.ui.screens.wallet.components.views :as components] [status-im.ui.screens.wallet.request.styles :as styles] [status-im.ui.screens.wallet.styles :as wallet.styles] + [status-im.ui.components.styles :as components.styles] + [status-im.ui.screens.wallet.components :as comp] + [status-im.ui.screens.wallet.components.views :as components] [status-im.utils.ethereum.core :as ethereum] [status-im.utils.ethereum.eip681 :as eip681] - [status-im.utils.ethereum.tokens :as tokens] + [status-im.utils.money :as money] [status-im.utils.utils :as utils])) -(defn toolbar-view [] - [toolbar/toolbar {:style wallet.styles/toolbar} - [toolbar/nav-button (actions/back-white actions/default-handler)] - [toolbar/content-title {:color :white} (i18n/label :t/request-transaction)]]) +;; Request screen -(defn send-request [] - (re-frame/dispatch [:navigate-to-modal - :contact-list-modal - {:handler #(re-frame/dispatch [:wallet-send-request %1]) - :action :request - :params {:hide-actions? true}}])) +(views/defview send-transaction-request [] + ;; TODO(jeluard) both send and request flows should be merged + (views/letsubs [{:keys [to to-name whisper-identity]} [:wallet.send/transaction] + {:keys [amount amount-error]} [:wallet.request/transaction] + scroll (atom nil)] + [comp/simple-screen {:avoid-keyboard? true} + [comp/toolbar (i18n/label :t/new-request)] + [react/view components.styles/flex + [common/network-info {:text-color :white}] + [react/scroll-view {:ref #(reset! scroll %) :keyboardShouldPersistTaps :always} + [react/view styles/request-details-wrapper + [components/recipient-selector {:contact-only? true + :address to + :name to-name}] + [components/asset-selector {:disabled? true + :symbol :ETH}] + [components/amount-selector {:error amount-error + :input-options {:default-value (str (money/to-fixed (money/wei->ether amount))) + :max-length 21 + :on-focus (fn [] (when @scroll (utils/set-timeout #(.scrollToEnd @scroll) 100))) + :on-change-text #(re-frame/dispatch [:wallet.request/set-and-validate-amount %])}}]]] + [bottom-buttons/bottom-buttons styles/bottom-buttons + nil ;; Force a phantom button to ensure consistency with other transaction screens which define 2 buttons + [button/button {:disabled? (not (and to amount)) + :on-press #(re-frame/dispatch [:wallet-send-request whisper-identity amount]) + :text-style {:padding-horizontal 0}} + (i18n/label :t/send-request) + [vector-icons/icon :icons/forward {:color :white}]]]]])) -(defn- generate-value [address {:keys [symbol] :as m}] - (if (tokens/ethereum? symbol) - (eip681/generate-uri address (dissoc m :symbol)) - (eip681/generate-erc20-uri address m))) +;; Main screen -(views/defview qr-code [amount symbol] - (views/letsubs [account [:get-current-account] - chain-id [:get-network-id]] - [qr-code-viewer/qr-code - (let [address (ethereum/normalized-address (:address account)) - params {:chain-id chain-id :value amount :symbol (or symbol :ETH)}] - {:value (generate-value address params) - :size 256})])) +(defn- qr-code [address chain-id] + (let [address (ethereum/normalized-address address)] + [qr-code-viewer/qr-code-viewer {:hint-style styles/hint :footer-style styles/footer} + (eip681/generate-uri address {:chain-id chain-id}) + (i18n/label :t/request-qr-legend) + address])) (views/defview request-transaction [] - ;;Because input field is in the end of view we will scroll to the end on input focus event - (views/letsubs [amount [:get-in [:wallet :request-transaction :amount]] - amount-error [:get-in [:wallet :request-transaction :amount-error]] - symbol [:wallet.request/symbol] - request-enabled? [:wallet.request/request-enabled?] - scroll (atom nil)] - [react/keyboard-avoiding-view wallet.styles/wallet-modal-container - [status-bar/status-bar {:type :wallet}] - [toolbar-view] - [common/network-info {:text-color :white}] - [react/scroll-view {:ref #(reset! scroll %)} - [react/view components.styles/flex - [react/view styles/network-container - [react/view styles/qr-container - [react/with-activity-indicator - {:style wallet.styles/qr-code-preview} - [qr-code amount symbol]]]] - [components/amount-selector - {:error amount-error - :input-options {:on-focus (fn [] (when @scroll (utils/set-timeout #(.scrollToEnd @scroll) 100))) - :on-change-text #(re-frame/dispatch [:wallet.request/set-and-validate-amount %])}}] - [components/asset-selector {:type :request - :symbol symbol}]]] - [components/separator] - [react/view wallet.styles/buttons-container - [react/touchable-highlight {:style wallet.styles/button :disabled true} - [react/view (wallet.styles/button-container false) - [vector-icons/icon :icons/share {:color :white :container-style styles/share-icon-container}] - [components/button-text (i18n/label :t/share)]]] - [react/view components.styles/flex] - [react/touchable-highlight {:style wallet.styles/button :disabled (not request-enabled?) :on-press send-request} - [react/view (wallet.styles/button-container request-enabled?) - [components/button-text (i18n/label :t/send-request)] - [vector-icons/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]])) + (views/letsubs [{:keys [address]} [:get-current-account] + chain-id [:get-network-id]] + [comp/simple-screen + [comp/toolbar comp/default-action + (i18n/label :t/receive) + [toolbar/actions [{:icon :icons/share + :icon-opts {:color :white} + :handler #(list-selection/open-share {:message address})}]]] + [react/view {:flex 1} + [common/network-info {:text-color :white}] + [react/scroll-view styles/request-wrapper + [qr-code address chain-id] + [button/primary-button {:on-press #(re-frame/dispatch [:navigate-to :wallet-send-transaction-request]) + :style styles/send-request} + (i18n/label :t/send-transaction-request)]]]])) diff --git a/src/status_im/ui/screens/wallet/send/db.cljs b/src/status_im/ui/screens/wallet/send/db.cljs index 4eac7ff76a..9e710e9613 100644 --- a/src/status_im/ui/screens/wallet/send/db.cljs +++ b/src/status_im/ui/screens/wallet/send/db.cljs @@ -22,10 +22,11 @@ (spec/def ::gas (spec/nilable money/valid?)) (spec/def ::gas-price (spec/nilable money/valid?)) (spec/def ::advanced? boolean?) +(spec/def ::whisper-identity (spec/nilable string?)) (spec/def :wallet/send-transaction (allowed-keys :opt-un [::amount ::to ::to-name ::amount-error ::password ::waiting-signal? ::signing? ::id ::later? ::camera-flashlight ::in-progress? ::wrong-password? ::from-chat? ::symbol ::advanced? - ::gas ::gas-price])) + ::gas ::gas-price ::whisper-identity])) diff --git a/src/status_im/ui/screens/wallet/send/events.cljs b/src/status_im/ui/screens/wallet/send/events.cljs index 42b63c0092..c04b9377e1 100644 --- a/src/status_im/ui/screens/wallet/send/events.cljs +++ b/src/status_im/ui/screens/wallet/send/events.cljs @@ -143,7 +143,7 @@ ;;TRANSACTION FAILED signal from status-go (handlers/register-handler-fx :transaction-failed - (fn [{{:keys [view-id modal] :as db} :db} [_ {:keys [id error_code error_message] :as event}]] + (fn [{{:keys [view-id modal] :as db} :db} [_ {:keys [id error_code error_message]}]] (let [send-transaction (get-in db [:wallet :send-transaction])] (case error_code @@ -200,7 +200,7 @@ :accounts/keys [accounts current-account-id] :as db} :db} [_ later?]] (let [db' (assoc-in db [:wallet :send-transaction :wrong-password?] false) network (:network db) - {:keys [amount id password to symbol gas gas-price] :as m} (get-in db [:wallet :send-transaction])] + {:keys [amount id password to symbol gas gas-price]} (get-in db [:wallet :send-transaction])] (if id {::accept-transaction {:id id :password password diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index fbf6fa6ad1..d63c11603f 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -64,7 +64,7 @@ [button/button {:style (wallet.styles/button-container sign-enabled?) :on-press sign-handler} (i18n/label :t/transactions-sign-transaction) - [vector-icons/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]])) + [vector-icons/icon :icons/forward {:color :white}]]])) (defn- sign-enabled? [amount-error to amount] (and @@ -87,7 +87,7 @@ :on-press #(re-frame/dispatch [:wallet.send/set-signing? true]) :text-style {:color :white}} (i18n/label :t/transactions-sign-transaction) - [vector-icons/icon :icons/forward {:color (if immediate-sign-enabled? :white :gray) :container-style wallet.styles/forward-icon-container}]]])) + [vector-icons/icon :icons/forward {:color (if immediate-sign-enabled? :white :gray)}]]])) (defn handler [discard?] (if discard? @@ -163,11 +163,11 @@ (defn- send-transaction-panel [{:keys [modal? transaction scroll advanced? symbol]}] (let [{:keys [amount amount-error signing? to to-name sufficient-funds? in-progress? from-chat?]} transaction] - [react/keyboard-avoiding-view wallet.styles/wallet-modal-container + [wallet.components/simple-screen {:avoid-keyboard? true + :status-bar-type (if modal? :modal-wallet :wallet)} + [toolbar from-chat? (if modal? act/close-white act/back-white) + (i18n/label :t/send-transaction)] [react/view components.styles/flex - [status-bar/status-bar {:type (if modal? :modal-wallet :wallet)}] - [toolbar from-chat? (if modal? act/close-white act/back-white) - (i18n/label :t/send-transaction)] [common/network-info {:text-color :white}] [react/scroll-view (merge {:keyboardShouldPersistTaps :always} (when-not modal? {:ref #(reset! scroll %)})) [react/view send.styles/send-transaction-form diff --git a/src/status_im/ui/screens/wallet/styles.cljs b/src/status_im/ui/screens/wallet/styles.cljs index e57d732ac0..03387d0421 100644 --- a/src/status_im/ui/screens/wallet/styles.cljs +++ b/src/status_im/ui/screens/wallet/styles.cljs @@ -3,65 +3,11 @@ (:require [status-im.ui.components.colors :as colors] [status-im.ui.components.styles :as styles])) -;; errors - -(defstyle error-container - {:align-self :center - :justify-content :center - :ios {:border-radius 20 - :margin-top 6} - :android { - :margin-top 18} - :background-color colors/blue}) - -(defstyle error-message-container - {:flex-direction :row - :align-items :center - :padding-horizontal 15 - :ios {:padding-vertical 8} - :android {:padding-vertical 10}}) - - -(defn exclamation [color] - {:background-color color - :border-radius 100 - :width 16 - :height 16 - :margin-right 6}) - -(def error-message - {:color colors/white - :font-size 13}) - -(def error-exclamation - (exclamation styles/color-red-2)) - -(def warning-exclamation - (exclamation :gold)) - ;; wallet -(def wallet-container - {:flex 1}) - (def toolbar {:background-color colors/blue}) -(defstyle toolbar-modal - {:background-color colors/blue - :android {:elevation 2}}) - -(def buttons-container - {:flex-direction :row - :align-items :center}) - -(def button - {:padding-vertical 15 - :padding-horizontal 12}) - -(def forward-icon-container - {:margin-left 8}) - (defn button-container [enabled?] (merge {:flex-direction :row :align-items :center} @@ -72,11 +18,7 @@ {:flex 1 :background-color colors/blue}) -(def amount-container - {:margin-top 16 - :margin-bottom 16 - :margin-horizontal 15 - :flex-direction :row}) +;; Components (def cartouche-container {:flex 1 @@ -104,12 +46,88 @@ :justify-content :space-between :align-items :center}) +(def cartouche-text-wrapper + {:flex-direction :row + :justify-content :space-between + :padding-horizontal 15 + :padding-vertical 15}) + (def cartouche-primary-text {:color styles/color-white}) (def cartouche-secondary-text {:color styles/color-white-transparent}) +;; Main section + +(def main-section + {:background-color colors/blue}) + +(def total-balance-container + {:align-items :center + :justify-content :center}) + +(def total-balance + {:flex-direction :row}) + +(def total-balance-value + {:font-size 37 + :color colors/white}) + +(def total-value + {:font-size 14 + :color styles/color-white-transparent}) + +(defstyle total-balance-currency + {:font-size 37 + :margin-left 9 + :color styles/color-white-transparent-5 + :android {:letter-spacing 1.5} + :ios {:letter-spacing 1.16}}) + +;; Actions section + +(def action-section + {:background-color colors/blue}) + +(def action + {:background-color colors/white-transparent + :border-radius 50}) + +(def action-label + {:color :white}) + +(def action-separator + {:height 1 + :background-color colors/white-light-transparent + :margin-left 70}) + +;; Assets section + +(def asset-section + {:flex 1 + :padding-vertical 16}) + +(def asset-section-title + {:font-size 14 + :margin-left 16 + :color styles/color-gray4}) + +(def asset-item-value-container + {:flex 1 + :flex-direction :row + :align-items :center}) + +(def asset-item-value + {:flex -1 + :font-size 16 + :color styles/color-black}) + +(def asset-item-currency + {:font-size 16 + :color styles/color-gray4 + :margin-left 6}) + (def qr-code-preview {:width 256 :height 256 diff --git a/src/status_im/ui/screens/wallet/subs.cljs b/src/status_im/ui/screens/wallet/subs.cljs index f4176b8cb9..63674291a5 100644 --- a/src/status_im/ui/screens/wallet/subs.cljs +++ b/src/status_im/ui/screens/wallet/subs.cljs @@ -19,12 +19,6 @@ (fn [db] (get-in db [:prices :last-day]))) -(reg-sub :wallet/error-message? - :<- [:wallet] - (fn [wallet] - (or (get-in wallet [:errors :balance-update]) - (get-in wallet [:errors :prices-update])))) - (reg-sub :portfolio-value :<- [:balance] :<- [:price] diff --git a/src/status_im/ui/screens/wallet/transactions/events.cljs b/src/status_im/ui/screens/wallet/transactions/events.cljs index 2e2e29741f..ea6619774e 100644 --- a/src/status_im/ui/screens/wallet/transactions/events.cljs +++ b/src/status_im/ui/screens/wallet/transactions/events.cljs @@ -4,7 +4,7 @@ (defn- mark-all-checked [filters] (update filters :type #(map (fn [m] (assoc m :checked? true)) %))) -(defn- mark-checked [filters {:keys [type] :as m} checked?] +(defn- mark-checked [filters {:keys [type]} checked?] (update filters :type #(map (fn [{:keys [id] :as m}] (if (= type id) (assoc m :checked? checked?) m)) %))) (defn- update-filters [db f] @@ -18,4 +18,4 @@ (handlers/register-handler-db :wallet.transactions/filter-all (fn [db] - (update-filters db mark-all-checked))) \ No newline at end of file + (update-filters db mark-all-checked))) diff --git a/src/status_im/ui/screens/wallet/transactions/styles.cljs b/src/status_im/ui/screens/wallet/transactions/styles.cljs index 3d85c42578..dfc3722433 100644 --- a/src/status_im/ui/screens/wallet/transactions/styles.cljs +++ b/src/status_im/ui/screens/wallet/transactions/styles.cljs @@ -4,20 +4,6 @@ [status-im.ui.components.styles :as styles] [status-im.ui.screens.main-tabs.styles :as tabs.styles])) -(def error-container - {:align-self :center - :justify-content :center - :border-radius 8 - :padding-vertical 4 - :flex-direction :row - :background-color styles/color-gray9}) - -(def error-message - {:color styles/color-black - :padding-top 3 - :padding-right 10 - :font-size 13}) - (defnstyle tab [active?] {:flex 1 :height tabs.styles/tab-height @@ -112,14 +98,6 @@ :margin-horizontal 12 :border-radius 8}) -(def sign-all-popup-sign-phrase - {:border-radius 8 - :margin-top 12 - :margin-horizontal 12 - :text-align :center - :padding-vertical 9 - :background-color styles/color-light-gray}) - (def sign-all-popup-text {:margin-top 8 :margin-horizontal 12}) diff --git a/src/status_im/ui/screens/wallet/transactions/subs.cljs b/src/status_im/ui/screens/wallet/transactions/subs.cljs index 56f77de69d..9ccd28abe7 100644 --- a/src/status_im/ui/screens/wallet/transactions/subs.cljs +++ b/src/status_im/ui/screens/wallet/transactions/subs.cljs @@ -2,27 +2,21 @@ (:require [re-frame.core :refer [reg-sub subscribe]] [status-im.i18n :as i18n] [status-im.utils.datetime :as datetime] + [status-im.utils.hex :as utils.hex] [status-im.utils.money :as money] - [status-im.utils.transactions :as transactions] - [status-im.utils.hex :as utils.hex])) + [status-im.utils.transactions :as transactions])) (reg-sub :wallet.transactions/transactions-loading? :<- [:wallet] (fn [wallet] (:transactions-loading? wallet))) -(reg-sub :wallet.transactions/error-message? - :<- [:wallet] - (fn [wallet] - (get-in wallet [:errors :transactions-update]))) - (reg-sub :wallet.transactions/current-tab :<- [:wallet] (fn [wallet] (get wallet :current-tab 0))) (defn enrich-transaction [{:keys [type to from timestamp] :as transaction} contacts] - ;; TODO (yenda) proper wallet logic when wallet switching is implemented (let [[contact-address key-contact key-wallet] (if (= type :inbound) [from :from-contact :to-wallet] [to :to-contact :from-wallet]) diff --git a/src/status_im/ui/screens/wallet/transactions/views.cljs b/src/status_im/ui/screens/wallet/transactions/views.cljs index d599562ed0..5a348de6d2 100644 --- a/src/status_im/ui/screens/wallet/transactions/views.cljs +++ b/src/status_im/ui/screens/wallet/transactions/views.cljs @@ -10,7 +10,6 @@ [status-im.ui.components.toolbar.actions :as actions] [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.screens.wallet.transactions.styles :as styles] - [status-im.ui.screens.wallet.views :as wallet.views] [status-im.utils.money :as money])) (defn on-delete-transaction @@ -102,11 +101,8 @@ (defview history-list [] (letsubs [transactions-history-list [:wallet.transactions/transactions-history-list] transactions-loading? [:wallet.transactions/transactions-loading?] - error-message [:wallet.transactions/error-message?] filter-data [:wallet.transactions/filters]] [react/view components.styles/flex - (when error-message - [wallet.views/error-message-view styles/error-container styles/error-message]) [list/section-list {:sections (map #(update-transactions % filter-data) transactions-history-list) :render-fn render-transaction :empty-component [react/text {:style styles/empty-text} diff --git a/src/status_im/ui/screens/wallet/views.cljs b/src/status_im/ui/screens/wallet/views.cljs index 42f319d323..31dfdbb711 100644 --- a/src/status_im/ui/screens/wallet/views.cljs +++ b/src/status_im/ui/screens/wallet/views.cljs @@ -1,17 +1,101 @@ (ns status-im.ui.screens.wallet.views - (:require [status-im.ui.components.react :as react] + (:require-macros [status-im.utils.views :refer [defview letsubs]]) + (:require [re-frame.core :as re-frame] + [status-im.i18n :as i18n] + [status-im.ui.components.styles :as components.styles] + [status-im.ui.components.list.views :as list] + [status-im.ui.components.react :as react] + [status-im.ui.components.toolbar.actions :as act] + [status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.screens.wallet.styles :as styles] - [status-im.ui.components.icons.vector-icons :as vector-icons] - [status-im.i18n :as i18n])) + [status-im.ui.screens.wallet.utils :as wallet.utils] + [status-im.utils.ethereum.core :as ethereum] + [status-im.utils.ethereum.tokens :as tokens] + [status-im.utils.platform :as platform])) -(defn- message-view [icon-container-style label] - [react/view {:style styles/error-container} - [react/view {:style styles/error-message-container} - [vector-icons/icon :icons/exclamation_mark {:color :white - :container-style icon-container-style}] - [react/text {:style styles/error-message} - label]]]) +(defn toolbar-view [] + [toolbar/toolbar {:style styles/toolbar :flat? true} + nil + [toolbar/content-wrapper] + [toolbar/actions + [(assoc (act/opts [{:label (i18n/label :t/wallet-manage-assets) + :action #(re-frame/dispatch [:navigate-to-modal :wallet-settings-assets])}]) + :icon-opts {:color :white})]]]) -(def error-message-view [message-view styles/error-exclamation (i18n/label :t/wallet-error)]) +(defn- total-section [usd-value] + [react/view {:style styles/main-section} + [react/view {:style styles/total-balance-container} + [react/view {:style styles/total-balance} + [react/text {:style styles/total-balance-value} usd-value] + [react/text {:style styles/total-balance-currency} (i18n/label :t/usd-currency)]] + [react/text {:style styles/total-value} (i18n/label :t/wallet-total-value)]]]) -(def wallet-syncing [message-view styles/warning-exclamation (i18n/label :t/sync-in-progress)]) +(defn- render-action [{:keys [label icon action]}] + [react/touchable-highlight {:on-press action} + [react/view + [list/item + [list/item-icon {:icon icon :style styles/action :icon-opts {:color :white}}] + [list/item-primary-only {:style styles/action-label} + label] + list/item-icon-forward]]]) + +(def actions + [{:label (i18n/label :t/send-transaction) + :icon :icons/arrow-right + :action #(re-frame/dispatch [:navigate-to :wallet-send-transaction])} + {:label (i18n/label :t/receive-transaction) + :icon :icons/arrow-left + :action #(re-frame/dispatch [:navigate-to :wallet-request-transaction])} + {:label (i18n/label :t/transaction-history) + :icon :icons/transaction-history + :action #(re-frame/dispatch [:navigate-to :transactions-history])}]) + +(defn- action-section [] + [react/view styles/action-section + [list/flat-list + {:separator (when platform/ios? [react/view styles/action-separator]) + :data actions + :render-fn render-action}]]) + +(defn- render-asset [{:keys [symbol icon decimals amount]}] + [react/view + [list/item + [list/item-image icon] + [react/view {:style styles/asset-item-value-container} + [react/text {:style styles/asset-item-value + :number-of-lines 1 + :ellipsize-mode :tail} + (wallet.utils/format-amount amount decimals)] + [react/text {:style styles/asset-item-currency + :uppercase? true + :number-of-lines 1} + (clojure.core/name symbol)]]]]) + +(defn current-tokens [visible-tokens network] + (filter #(contains? visible-tokens (:symbol %)) (tokens/tokens-for (ethereum/network->chain-keyword network)))) + +(defn- asset-section [network balance visible-tokens prices-loading? balance-loading?] + (let [tokens (current-tokens visible-tokens network) + assets (map #(assoc % :amount (get balance (:symbol %))) (concat [tokens/ethereum] tokens))] + [react/view styles/asset-section + [react/text {:style styles/asset-section-title} (i18n/label :t/wallet-assets)] + [list/flat-list + {:default-separator? true + :data assets + :render-fn render-asset + :on-refresh #(re-frame/dispatch [:update-wallet (map :symbol tokens)]) + :refreshing (boolean (or prices-loading? balance-loading?))}]])) + +(defview wallet [] + (letsubs [network [:network] + balance [:balance] + visible-tokens [:wallet.settings/visible-tokens] + portfolio-value [:portfolio-value] + prices-loading? [:prices-loading?] + balance-loading? [:wallet/balance-loading?]] + [react/view {:style components.styles/flex} + [toolbar-view] + [react/view components.styles/flex + [total-section portfolio-value] + [action-section] + [asset-section network balance visible-tokens prices-loading? balance-loading?]]])) diff --git a/src/status_im/utils/ethereum/tokens.cljs b/src/status_im/utils/ethereum/tokens.cljs index 63044b578b..d1cba0ad45 100644 --- a/src/status_im/utils/ethereum/tokens.cljs +++ b/src/status_im/utils/ethereum/tokens.cljs @@ -392,4 +392,4 @@ (defn asset-for [chain symbol] (if (= (:symbol ethereum) symbol) ethereum - (symbol->token chain symbol))) \ No newline at end of file + (symbol->token chain symbol))) diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index 698522776d..212ecf3617 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -4,7 +4,6 @@ [status-im.test.contacts.events] [status-im.test.accounts.events] [status-im.test.data-store.realm.core] - [status-im.test.wallet.events] [status-im.test.wallet.transactions.subs] [status-im.test.wallet.transactions.views] [status-im.test.profile.events] @@ -39,7 +38,6 @@ 'status-im.test.accounts.events 'status-im.test.contacts.events 'status-im.test.profile.events - 'status-im.test.wallet.events 'status-im.test.data-store.realm.core 'status-im.test.bots.events 'status-im.test.wallet.transactions.subs diff --git a/test/cljs/status_im/test/wallet/events.cljs b/test/cljs/status_im/test/wallet/events.cljs deleted file mode 100644 index 7071b52a6e..0000000000 --- a/test/cljs/status_im/test/wallet/events.cljs +++ /dev/null @@ -1,33 +0,0 @@ -(ns status-im.test.wallet.events - (:require [cljs.test :refer [deftest is testing]] - reagent.core - [re-frame.core :as re-frame] - [day8.re-frame.test :refer [run-test-sync]] - status-im.ui.screens.db - status-im.ui.screens.subs - [status-im.ui.screens.events :as events] - [status-im.ui.screens.wallet.events :as wallet-events])) - -(deftest wallet-events - "update-balance-fail - update-prices-fail - clear-error" - (run-test-sync - (re-frame/reg-fx ::events/init-store #()) - (re-frame/reg-fx :get-prices #()) - (re-frame/reg-fx :get-balance #()) - (re-frame/dispatch [:initialize-db]) - (let [error (re-frame/subscribe [:wallet/error-message?]) - message "failed balance update"] - (re-frame/dispatch [:update-balance-fail message]) - (is (= message @error))) - (let [error (re-frame/subscribe [:wallet/error-message?])] - (re-frame/dispatch [:update-wallet]) - (is (nil? @error))) - (let [error (re-frame/subscribe [:wallet/error-message?]) - message "failed price update"] - (re-frame/dispatch [:update-prices-fail message]) - (is (= message @error))) - (let [error (re-frame/subscribe [:wallet/error-message?])] - (re-frame/dispatch [:update-wallet]) - (is (nil? @error)))))