[ISSUE #2883] Migrate wallet/request to latest mockups

Signed-off-by: Goran Jovic <goranjovic@gmail.com>
This commit is contained in:
Julien Eluard 2018-01-26 10:29:36 +01:00 committed by Goran Jovic
parent 96f08abc7d
commit 748b0fcf09
No known key found for this signature in database
GPG Key ID: A778DE3CD7D2D10D
39 changed files with 466 additions and 694 deletions

View File

@ -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?]]

View File

@ -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"

View File

@ -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

View File

@ -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]])])

View File

@ -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})

View File

@ -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

View File

@ -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]]))

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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]]]))

View File

@ -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})))

View File

@ -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 []

View File

@ -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

View File

@ -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]}))

View File

@ -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]])

View File

@ -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]

View File

@ -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))))

View File

@ -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)

View File

@ -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})

View File

@ -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?]]]))

View File

@ -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]]

View File

@ -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)}))

View File

@ -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})

View File

@ -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)))))

View File

@ -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)]]]]))

View File

@ -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]))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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)))
(update-filters db mark-all-checked)))

View File

@ -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})

View File

@ -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])

View File

@ -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}

View File

@ -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?]]]))

View File

@ -392,4 +392,4 @@
(defn asset-for [chain symbol]
(if (= (:symbol ethereum) symbol)
ethereum
(symbol->token chain symbol)))
(symbol->token chain symbol)))

View File

@ -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

View File

@ -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)))))