send transaction layer 1
This commit is contained in:
parent
62affda881
commit
9246d7df21
|
@ -0,0 +1,3 @@
|
|||
<svg width="16px" height="8px" viewBox="0 0 16 8">
|
||||
<path fill="none" d="M0,0 L15.969209,0.0223819541 L9.39011025,6.60148066 C8.60906167,7.38252924 7.34273171,7.38252924 6.56168312,6.60148066 L6.55741249,6.59719708 L0,0 Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 234 B |
|
@ -55,3 +55,5 @@
|
|||
|
||||
(defn create-value-xy [x y]
|
||||
(js/ReactNative.Animated.ValueXY. (clj->js {:x x, :y y})))
|
||||
|
||||
(def easing js/ReactNative.Easing)
|
|
@ -67,6 +67,7 @@
|
|||
:icons/dropdown (slurp-svg "./resources/icons/dropdown.svg")
|
||||
:icons/grab (slurp-svg "./resources/icons/grab.svg")
|
||||
:icons/share (slurp-svg "./resources/icons/share.svg")
|
||||
:icons/tooltip-triangle (slurp-svg "./resources/icons/tooltip-triangle.svg")
|
||||
:icons/network (slurp-svg "./resources/icons/network.svg")})
|
||||
|
||||
(defn normalize-property-name [n]
|
||||
|
|
|
@ -106,3 +106,5 @@
|
|||
(def toolbar-text-action-disabled {:color styles/color-gray7})
|
||||
|
||||
(def item-text-white-background {:color styles/color-blue4})
|
||||
|
||||
(def ios-content-item {:position :absolute :right 90 :left 90})
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
[status-im.components.context-menu :as context-menu]
|
||||
[status-im.components.toolbar-new.actions :as act]
|
||||
[status-im.components.toolbar-new.styles :as tst]
|
||||
[status-im.components.icons.vector-icons :as vi]))
|
||||
[status-im.components.icons.vector-icons :as vi]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
;; Navigation item
|
||||
|
||||
|
@ -103,10 +104,15 @@
|
|||
action-items]
|
||||
[rn/view {:style (merge (tst/toolbar-wrapper background-color flat?) style)}
|
||||
[rn/view {:style tst/toolbar}
|
||||
(when platform/ios?
|
||||
[rn/view tst/ios-content-item
|
||||
content-item])
|
||||
(when nav-item
|
||||
[rn/view {:style (tst/toolbar-nav-actions-container 0)}
|
||||
nav-item])
|
||||
content-item
|
||||
(if platform/ios?
|
||||
[rn/view st/flex]
|
||||
content-item)
|
||||
action-items]
|
||||
(when-not no-sync-bar? [sync-state-gradient-view/sync-state-gradient-view])]))
|
||||
|
||||
|
|
|
@ -127,8 +127,7 @@
|
|||
(status/discard-transaction id)))))
|
||||
|
||||
(register-handler ::transaction-queued
|
||||
(after #(dispatch [:navigate-to-modal :unsigned-transactions]))
|
||||
(fn [db [_ {:keys [id message_id args] :as transaction}]]
|
||||
(fn [{:wallet/keys [send-transaction] :as db} [_ {:keys [id message_id args] :as transaction}]]
|
||||
(let [{:keys [from to value data gas gasPrice]} args]
|
||||
(if (transaction-valid? transaction)
|
||||
(let [transaction {:id id
|
||||
|
@ -140,6 +139,9 @@
|
|||
:gas-price (.toDecimal js/Web3.prototype gasPrice)
|
||||
:timestamp (time/now-ms)
|
||||
:message-id message_id}]
|
||||
(if (:waiting-signal? send-transaction)
|
||||
(dispatch [:wallet/transaction-queued id])
|
||||
(dispatch [:navigate-to-modal :unsigned-transactions]))
|
||||
(assoc-in db [:transactions-queue id] transaction))
|
||||
db))))
|
||||
|
||||
|
@ -147,7 +149,7 @@
|
|||
(u/side-effect!
|
||||
(fn [{:keys [transactions modal]} [_ {:keys [id response]}]]
|
||||
(let [{:keys [hash error]} response
|
||||
{:keys [message-id]} (transactions id)]
|
||||
{:keys [message-id]} (get transactions id)]
|
||||
(log/debug :parsed-response response)
|
||||
(when-not (and error (string? error) (not (s/blank? error)))
|
||||
(if (and message-id (not (s/blank? message-id)))
|
||||
|
|
|
@ -3,50 +3,52 @@
|
|||
(def translations
|
||||
{
|
||||
;;common
|
||||
:members-title "Members"
|
||||
:not-implemented "!not implemented"
|
||||
:chat-name "Chat name"
|
||||
:notifications-title "Notifications and sounds"
|
||||
:offline "Offline"
|
||||
:search-for "Search for..."
|
||||
:cancel "Cancel"
|
||||
:next "Next"
|
||||
:type-a-message "Type a message..."
|
||||
:type-a-command "Start typing a command..."
|
||||
:error "Error"
|
||||
:unknown-status-go-error "Unknown status-go error"
|
||||
:node-unavailable "No ethereum node running"
|
||||
:members-title "Members"
|
||||
:not-implemented "!not implemented"
|
||||
:chat-name "Chat name"
|
||||
:notifications-title "Notifications and sounds"
|
||||
:offline "Offline"
|
||||
:search-for "Search for..."
|
||||
:cancel "Cancel"
|
||||
:next "Next"
|
||||
:type-a-message "Type a message..."
|
||||
:type-a-command "Start typing a command..."
|
||||
:error "Error"
|
||||
:unknown-status-go-error "Unknown status-go error"
|
||||
:node-unavailable "No ethereum node running"
|
||||
:yes "Yes"
|
||||
:no "No"
|
||||
|
||||
:camera-access-error "To grant the required camera permission, please, go to your system settings and make sure that Status > Camera is selected."
|
||||
:photos-access-error "To grant the required photos permission, please, go to your system settings and make sure that Status > Photos is selected."
|
||||
:camera-access-error "To grant the required camera permission, please, go to your system settings and make sure that Status > Camera is selected."
|
||||
:photos-access-error "To grant the required photos permission, please, go to your system settings and make sure that Status > Photos is selected."
|
||||
|
||||
;;drawer
|
||||
:invite-friends "Invite friends"
|
||||
:faq "FAQ"
|
||||
:switch-users "Switch users"
|
||||
:feedback "Got feedback?\nShake your phone!"
|
||||
:view-all "View all"
|
||||
:current-network "Current network"
|
||||
:invite-friends "Invite friends"
|
||||
:faq "FAQ"
|
||||
:switch-users "Switch users"
|
||||
:feedback "Got feedback?\nShake your phone!"
|
||||
:view-all "View all"
|
||||
:current-network "Current network"
|
||||
|
||||
;;chat
|
||||
:is-typing "is typing"
|
||||
:and-you "and you"
|
||||
:search-chat "Search chat"
|
||||
:members {:one "1 member"
|
||||
:other "{{count}} members"
|
||||
:zero "no members"}
|
||||
:members-active {:one "1 member"
|
||||
:other "{{count}} members"
|
||||
:zero "no members"}
|
||||
:public-group-status "Public"
|
||||
:active-online "Online"
|
||||
:active-unknown "Unknown"
|
||||
:available "Available"
|
||||
:no-messages "No messages"
|
||||
:suggestions-requests "Requests"
|
||||
:suggestions-commands "Commands"
|
||||
:faucet-success "Faucet request has been received"
|
||||
:faucet-error "Faucet request error"
|
||||
:is-typing "is typing"
|
||||
:and-you "and you"
|
||||
:search-chat "Search chat"
|
||||
:members {:one "1 member"
|
||||
:other "{{count}} members"
|
||||
:zero "no members"}
|
||||
:members-active {:one "1 member"
|
||||
:other "{{count}} members"
|
||||
:zero "no members"}
|
||||
:public-group-status "Public"
|
||||
:active-online "Online"
|
||||
:active-unknown "Unknown"
|
||||
:available "Available"
|
||||
:no-messages "No messages"
|
||||
:suggestions-requests "Requests"
|
||||
:suggestions-commands "Commands"
|
||||
:faucet-success "Faucet request has been received"
|
||||
:faucet-error "Faucet request error"
|
||||
|
||||
;;sync
|
||||
:sync-in-progress "Syncing..."
|
||||
|
@ -275,6 +277,7 @@
|
|||
:sign-in-to-status "Sign in to Status"
|
||||
:sign-in "Sign in"
|
||||
:wrong-password "Wrong password"
|
||||
:enter-password "Enter password"
|
||||
|
||||
;;recover
|
||||
:recover-from-passphrase "Recover from passphrase"
|
||||
|
@ -356,6 +359,7 @@
|
|||
:wallet-add-asset "Add asset"
|
||||
:wallet-total-value "Total value"
|
||||
:wallet-settings "Wallet Settings"
|
||||
:signing-phrase-description "Sign the transaction by entering your password. Make sure that the words above match your secret signing phrase"
|
||||
:request-transaction "Request Transaction"
|
||||
:send-request "Send request"
|
||||
:share "Share"
|
||||
|
@ -364,6 +368,8 @@
|
|||
:transaction-details "Transaction details"
|
||||
:transactions-sign "Sign"
|
||||
:transactions-sign-all "Sign all"
|
||||
:transactions-sign-transaction "Sign Transaction"
|
||||
:transactions-sign-later "Sign Later"
|
||||
:transactions-sign-all-text "Sign the transaction by entering your password.\nMake sure that the words above match your secret signing phrase"
|
||||
:transactions-sign-input-placeholder "Enter your password"
|
||||
:transactions-history "History"
|
||||
|
@ -374,15 +380,26 @@
|
|||
:transactions-filter-tokens "Tokens"
|
||||
:transactions-filter-type "Type"
|
||||
:transactions-filter-select-all "Select all"
|
||||
:view-transaction-details "View Transaction Details"
|
||||
:transaction-description "If you want to be sure you transaction will not be compromised wait until it gets at least 10 block confirmations"
|
||||
:transaction-sent "Transaction Sent"
|
||||
:transaction-moved-text "The transaction has ben successfully moved to “Unsigned”"
|
||||
:transaction-moved-title "Transaction Moved"
|
||||
:sign-later-title "Sign Transaction Later?"
|
||||
:sign-later-text "You will be able to sign in in the transaction history"
|
||||
:not-applicable "Not applicable for unsigned transactions"
|
||||
|
||||
;; Wallet Send
|
||||
:wallet-send-transaction "Send a Transaction"
|
||||
:wallet-send-step-one "Step 1 of 3"
|
||||
:wallet-send-transaction "Send Transaction"
|
||||
:wallet-send-step "Step {{step}} of {{number}}"
|
||||
:wallet-choose-recipient "Choose Recipient"
|
||||
:wallet-choose-from-contacts "Choose From Contacts"
|
||||
:wallet-address-from-clipboard "Use Address From Clipboard"
|
||||
:wallet-browse-photos "Browse Photos"
|
||||
:validation-amount-invalid-number "Amount is not valid number"
|
||||
:validation-amount-is-too-precise "Amount is too precise. The smallest unit you can send is 1 Wei (1x10^-18 ETH)"
|
||||
|
||||
|
||||
|
||||
;network settings
|
||||
:new-network "New network"
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
:my-profile/profile
|
||||
:my-profile/default-name
|
||||
:wallet/request-transaction
|
||||
:wallet/send-transaction
|
||||
:networks/selected-network
|
||||
:networks/networks
|
||||
:node/after-start
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
status-im.ui.screens.wallet.subs
|
||||
status-im.ui.screens.wallet.transactions.subs
|
||||
status-im.ui.screens.wallet.send.subs
|
||||
status-im.ui.screens.wallet.request.subs
|
||||
status-im.ui.screens.network-settings.subs
|
||||
status-im.transactions.subs
|
||||
status-im.bots.subs))
|
||||
|
|
|
@ -43,9 +43,12 @@
|
|||
[status-im.ui.screens.profile.qr-code.views :refer [qr-code-view]]
|
||||
|
||||
[status-im.ui.screens.wallet.send.views :refer [send-transaction]]
|
||||
[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.wallet-list.views :refer [wallet-list-screen]]
|
||||
[status-im.ui.screens.wallet.transactions.views :as wallet-transactions]
|
||||
[status-im.ui.screens.wallet.send.transaction-sent.views :refer [transaction-sent]]
|
||||
|
||||
[status-im.components.status-bar :as status-bar]
|
||||
[status-im.ui.screens.network-settings.views :refer [network-settings]]
|
||||
[status-im.ui.screens.network-settings.add-rpc.views :refer [add-rpc-url]]
|
||||
|
@ -69,6 +72,8 @@
|
|||
(:wallet :chat-list :discover :contact-list) main-tabs
|
||||
:wallet-list wallet-list-screen
|
||||
:wallet-send-transaction send-transaction
|
||||
:wallet-transaction-sent transaction-sent
|
||||
:choose-recipient choose-recipient
|
||||
:wallet-request-transaction request-transaction
|
||||
:wallet-transactions wallet-transactions/transactions
|
||||
:wallet-transaction-details wallet-transactions/transaction-details
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
(ns status-im.ui.screens.wallet.choose-recipient.styles
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
||||
(:require [status-im.components.styles :as styles]))
|
||||
|
||||
(def wallet-container
|
||||
{:flex 1
|
||||
:background-color styles/color-blue4})
|
||||
|
||||
(def toolbar-buttons-container
|
||||
{:flex-direction :row
|
||||
:flex-shrink 1
|
||||
:justify-content :space-between
|
||||
:width 68
|
||||
:margin-right 12})
|
||||
|
||||
(def choose-recipient-container
|
||||
{:flex-direction :row
|
||||
:padding-top 20
|
||||
:padding-bottom 20
|
||||
:justify-content :center})
|
||||
|
||||
(def choose-recipient-label
|
||||
{:color :white})
|
||||
|
||||
(defstyle recipient-buttons
|
||||
{:flex-direction :column
|
||||
:margin-horizontal 28
|
||||
:margin-vertical 20
|
||||
:border-radius 8
|
||||
:ios {:background-color styles/color-blue6}})
|
||||
|
||||
(def recipient-icon {:margin-right 20})
|
||||
|
||||
(def recipient-icon-disabled {:margin-right 20
|
||||
:opacity 0.3})
|
||||
|
||||
(def recipient-button
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:margin-vertical 10
|
||||
:margin-left 20})
|
||||
|
||||
(def recipient-button-text
|
||||
{:color :white
|
||||
:align-self :center
|
||||
:font-size 14})
|
||||
|
||||
(def recipient-button-text-disabled
|
||||
(merge recipient-button-text {:color "rgba(255, 255, 255, 0.3)"}))
|
||||
|
||||
(defnstyle recipient-touchable [divider?]
|
||||
(cond-> {:border-color styles/color-gray-transparent-light}
|
||||
divider? (assoc :ios {:border-bottom-width 1})))
|
||||
|
||||
(def recipient-touchable-disabled
|
||||
{:background-color styles/color-blue4
|
||||
:border-bottom-left-radius 8
|
||||
:border-bottom-right-radius 8
|
||||
:border-left-width 1
|
||||
:border-bottom-width 1
|
||||
:border-right-width 1
|
||||
:border-color "rgba(255, 255, 255, 0.3)"})
|
||||
|
||||
(def qr-container
|
||||
{:flex 1})
|
||||
|
||||
(def preview
|
||||
{:flex 1
|
||||
:justify-content :flex-end
|
||||
:align-items :center})
|
||||
|
||||
(def corner-dimensions
|
||||
{:position :absolute
|
||||
:width 40
|
||||
:height 40})
|
||||
|
||||
(defn corner-left-bottom [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:bottom (* viewport-offset dimension)
|
||||
:left (* viewport-offset dimension)})))
|
||||
|
||||
(defn corner-right-bottom [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:right (* viewport-offset dimension)
|
||||
:bottom (* viewport-offset dimension)})))
|
||||
|
||||
(defn corner-left-top [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:top (* viewport-offset dimension)
|
||||
:left (* viewport-offset dimension)})))
|
||||
|
||||
(defn corner-right-top [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:top (* viewport-offset dimension)
|
||||
:right (* viewport-offset dimension)})))
|
||||
|
||||
(def viewfinder-port {:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:right 0
|
||||
:flex 1})
|
||||
|
||||
(defn viewfinder-translucent [height width side]
|
||||
(let [viewport-offset 0.1666
|
||||
height-offset (* viewport-offset height)
|
||||
width-offset (* viewport-offset width)]
|
||||
(cond-> {:position :absolute
|
||||
:background-color :black
|
||||
:opacity 0.7}
|
||||
(= :top side) (assoc :height height-offset
|
||||
:width width)
|
||||
(= :right side) (assoc :height (- height height-offset)
|
||||
:width width-offset
|
||||
:bottom 0
|
||||
:right 0)
|
||||
(= :bottom side) (assoc :height height-offset
|
||||
:width (- width width-offset)
|
||||
:bottom 0
|
||||
:left 0)
|
||||
(= :left side) (assoc :height (- height (* 2 height-offset))
|
||||
:width width-offset
|
||||
:top height-offset
|
||||
:left 0))))
|
|
@ -0,0 +1,95 @@
|
|||
(ns status-im.ui.screens.wallet.choose-recipient.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.components.toolbar-new.view :as toolbar]
|
||||
[status-im.components.toolbar-new.actions :as act]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.components.react :as react]
|
||||
[status-im.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.screens.wallet.choose-recipient.styles :as styles]
|
||||
[status-im.components.status-bar :as status-bar]
|
||||
[status-im.components.camera :as camera]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(defn- show-not-implemented! []
|
||||
(utils/show-popup "TODO" "Not implemented yet!"))
|
||||
|
||||
(defn choose-from-contacts []
|
||||
(re-frame/dispatch [:navigate-to-modal
|
||||
:contact-list-modal
|
||||
{:handler #(re-frame/dispatch [:wallet-open-send-transaction (:address %1) (:name %1)])
|
||||
:action :send
|
||||
:params {:hide-actions? true}}]))
|
||||
|
||||
(defn toolbar-view []
|
||||
[toolbar/toolbar2 {:style wallet.styles/toolbar
|
||||
:no-sync-bar? true}
|
||||
[toolbar/nav-button (act/back-white act/default-handler)]
|
||||
[toolbar/content-title {:color :white} (i18n/label :t/wallet-choose-recipient)]
|
||||
[toolbar/actions [{:icon :icons/flash-active
|
||||
:icon-opts {:color :white}
|
||||
:handler show-not-implemented!}]]])
|
||||
|
||||
(defn recipient-buttons []
|
||||
[react/view {:style styles/recipient-buttons}
|
||||
[react/touchable-highlight {:style (styles/recipient-touchable true)
|
||||
:on-press choose-from-contacts}
|
||||
[react/view {:style styles/recipient-button}
|
||||
[react/text {:style styles/recipient-button-text}
|
||||
(i18n/label :t/wallet-choose-from-contacts)]
|
||||
[vector-icons/icon :icons/qr {:color :white
|
||||
:container-style styles/recipient-icon}]]]
|
||||
[react/touchable-highlight {:style (styles/recipient-touchable true)
|
||||
:on-press #(react/get-from-clipboard
|
||||
(fn [clipboard]
|
||||
(re-frame/dispatch [:choose-recipient clipboard])))}
|
||||
[react/view {:style styles/recipient-button}
|
||||
[react/text {:style styles/recipient-button-text}
|
||||
(i18n/label :t/wallet-address-from-clipboard)]
|
||||
[vector-icons/icon :icons/copy-from {:color :white
|
||||
:container-style styles/recipient-icon}]]]
|
||||
[react/touchable-highlight {:style styles/recipient-touchable-disabled}
|
||||
[react/view {:style styles/recipient-button}
|
||||
[react/text {:style styles/recipient-button-text-disabled}
|
||||
(i18n/label :t/wallet-browse-photos)]
|
||||
[vector-icons/icon :icons/browse {:color :white
|
||||
:container-style styles/recipient-icon-disabled}]]]])
|
||||
|
||||
(defn viewfinder [{:keys [height width]}]
|
||||
(let [min-dimension (min height width)]
|
||||
[react/view {:style styles/viewfinder-port}
|
||||
[react/view {:style (styles/viewfinder-translucent height width :top)}]
|
||||
[react/view {:style (styles/viewfinder-translucent height width :right)}]
|
||||
[react/view {:style (styles/viewfinder-translucent height width :bottom)}]
|
||||
[react/view {:style (styles/viewfinder-translucent height width :left)}]
|
||||
[react/image {:source {:uri :corner_left_top}
|
||||
:style (styles/corner-left-top min-dimension)}]
|
||||
[react/image {:source {:uri :corner_right_top}
|
||||
:style (styles/corner-right-top min-dimension)}]
|
||||
[react/image {:source {:uri :corner_left_bottom}
|
||||
:style (styles/corner-left-bottom min-dimension)}]
|
||||
[react/image {:source {:uri :corner_right_bottom}
|
||||
:style (styles/corner-right-bottom min-dimension)}]]))
|
||||
|
||||
(defview choose-recipient []
|
||||
(letsubs [camera-dimensions [:camera-dimensions]]
|
||||
[react/view {:style styles/wallet-container}
|
||||
[status-bar/status-bar {:type :wallet}]
|
||||
[toolbar-view]
|
||||
[react/view {:style styles/qr-container
|
||||
:on-layout #(let [layout (.. % -nativeEvent -layout)]
|
||||
(re-frame/dispatch [:set-in [:wallet :camera-dimensions]
|
||||
{:width (.-width layout)
|
||||
:height (.-height layout)}]))}
|
||||
[camera/camera {:style styles/preview
|
||||
:aspect :fill
|
||||
:captureAudio false
|
||||
:onBarCodeRead (fn [code]
|
||||
(let [data (-> code
|
||||
.-data
|
||||
(string/replace #"ethereum:" ""))]
|
||||
(re-frame/dispatch [:choose-recipient data])))}]
|
||||
[viewfinder camera-dimensions]]
|
||||
[recipient-buttons]]))
|
|
@ -0,0 +1,12 @@
|
|||
(ns status-im.ui.screens.wallet.components.animations
|
||||
(:require [status-im.components.animation :as animation]))
|
||||
|
||||
(defn animate-tooltip [bottom-value opacity-value]
|
||||
(fn []
|
||||
(animation/start
|
||||
(animation/parallel
|
||||
[(animation/timing opacity-value {:toValue 1
|
||||
:duration 500})
|
||||
(animation/timing bottom-value {:toValue 8.5
|
||||
:easing (.bezier animation/easing 0.685, 0.000, 0.025, 1.185)
|
||||
:duration 500})]))))
|
|
@ -12,15 +12,23 @@
|
|||
:height 52
|
||||
:letter-spacing -0.2})
|
||||
|
||||
(def label
|
||||
{:color :white
|
||||
:font-size 14
|
||||
:line-height 16
|
||||
:letter-spacing -0.2})
|
||||
(defstyle label
|
||||
{:color :white
|
||||
:ios {:font-size 14
|
||||
:line-height 16
|
||||
:letter-spacing -0.2}
|
||||
:android {:font-size 12
|
||||
:line-height 12}})
|
||||
|
||||
(def amount-text-input-container
|
||||
{:margin-top 8})
|
||||
|
||||
(def label-transparent
|
||||
(merge label
|
||||
{:color styles/color-white-transparent}))
|
||||
|
||||
(defnstyle amount-container [active?]
|
||||
{:margin-top 8
|
||||
:height 52
|
||||
{:height 52
|
||||
:background-color (if active?
|
||||
styles/color-white-transparent-4
|
||||
styles/color-white-transparent-3)
|
||||
|
@ -42,31 +50,100 @@
|
|||
:justify-content :center})
|
||||
|
||||
(defstyle currency-container
|
||||
{:margin-top 8
|
||||
{:margin-top 8
|
||||
:height 52
|
||||
;;TODO disabled
|
||||
:border-width 1
|
||||
:border-color styles/color-white-transparent-4
|
||||
;:background-color styles/color-white-transparent-3
|
||||
:justify-content :center
|
||||
:padding 14
|
||||
:ios {:border-radius 8}
|
||||
:android {:border-radius 4}})
|
||||
|
||||
(defstyle recipient-container
|
||||
{:flex-direction :row
|
||||
:flex 1
|
||||
:margin-top 8
|
||||
:height 52
|
||||
:align-items :center
|
||||
:background-color styles/color-white-transparent-3
|
||||
:justify-content :center
|
||||
:padding 14
|
||||
:padding-vertical 14
|
||||
:padding-left 14
|
||||
:padding-right 8
|
||||
:ios {:border-radius 8}
|
||||
:android {:border-radius 4}})
|
||||
|
||||
(defstyle wallet-container
|
||||
{:flex-direction :row
|
||||
:margin-top 8
|
||||
:height 52
|
||||
:background-color styles/color-white-transparent-3
|
||||
:align-items :center
|
||||
:padding 14
|
||||
:ios {:border-radius 8}
|
||||
:android {:border-radius 4}})
|
||||
{:flex-direction :row
|
||||
:margin-top 8
|
||||
:height 52
|
||||
;;TODO disabled
|
||||
:border-width 1
|
||||
:border-color styles/color-white-transparent-4
|
||||
;:background-color styles/color-white-transparent-3
|
||||
:align-items :center
|
||||
:padding 14
|
||||
:ios {:border-radius 8}
|
||||
:android {:border-radius 4}})
|
||||
|
||||
(def wallet-name
|
||||
{:color :white
|
||||
:font-size 15
|
||||
:letter-spacing -0.2})
|
||||
|
||||
(defn participant [address?]
|
||||
{:color (if address? :white styles/color-white-transparent)
|
||||
:flex-shrink 1
|
||||
:font-size 15
|
||||
:letter-spacing -0.2})
|
||||
|
||||
(def wallet-value
|
||||
{:padding-left 6
|
||||
:color styles/color-white-transparent-5
|
||||
:font-size 15
|
||||
:letter-spacing -0.2})
|
||||
|
||||
(def separator
|
||||
{:height 1
|
||||
:margin-horizontal 15
|
||||
:background-color styles/color-white-transparent-1
|
||||
:margin-top 16})
|
||||
|
||||
(def button-text
|
||||
{:color :white
|
||||
:font-size 15
|
||||
:letter-spacing -0.2})
|
||||
|
||||
(def tooltip-container
|
||||
{:position :absolute
|
||||
:align-items :center
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0})
|
||||
|
||||
(defn tooltip-animated [bottom-value opacity-value]
|
||||
{:position :absolute
|
||||
:align-items :center
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom bottom-value
|
||||
:opacity opacity-value})
|
||||
|
||||
(def tooltip-text-container
|
||||
{:padding-horizontal 16
|
||||
:padding-vertical 9
|
||||
:background-color :white
|
||||
:border-radius 8})
|
||||
|
||||
(def tooltip-text
|
||||
{:color styles/color-red-2
|
||||
:font-size 15})
|
||||
|
||||
(def tooltip-triangle
|
||||
{:width 16
|
||||
:height 8
|
||||
:viewBox "0 0 16 8"})
|
||||
|
||||
(def recipient-name-container
|
||||
{:padding-right 6})
|
|
@ -1,29 +1,48 @@
|
|||
(ns status-im.ui.screens.wallet.components.views
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [status-im.components.react :as react]
|
||||
[status-im.components.styles :as components.styles]
|
||||
[status-im.ui.screens.wallet.components.styles :as styles]
|
||||
[status-im.i18n :as i18n]
|
||||
[reagent.core :as reagent]))
|
||||
[reagent.core :as reagent]
|
||||
[status-im.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.components.animation :as animation]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet.components.animations :as animations]))
|
||||
|
||||
(views/defview tooltip [label & [style]]
|
||||
(views/letsubs [bottom-value (animation/create-value 16)
|
||||
opacity-value (animation/create-value 0)]
|
||||
{:component-did-mount (animations/animate-tooltip bottom-value opacity-value)}
|
||||
[react/view styles/tooltip-container
|
||||
[react/animated-view {:style (merge (styles/tooltip-animated bottom-value opacity-value) style)}
|
||||
[react/view styles/tooltip-text-container
|
||||
[react/text {:style styles/tooltip-text} label]]
|
||||
[vector-icons/icon :icons/tooltip-triangle {:color :white :style styles/tooltip-triangle}]]]))
|
||||
|
||||
(defn amount-input []
|
||||
(let [active? (reagent/atom false)]
|
||||
(fn [& [{:keys [input-options style error]}]]
|
||||
(let [{:keys [on-focus on-blur]} input-options]
|
||||
[react/view components.styles/flex
|
||||
[react/text {:style styles/label} (i18n/label :t/amount)]
|
||||
[react/view styles/amount-text-input-container
|
||||
[react/view (merge (styles/amount-container @active?) style)
|
||||
[react/text-input
|
||||
(merge
|
||||
{:keyboard-type :numeric
|
||||
:placeholder "0.000"
|
||||
:placeholder-text-color "#ffffff66"
|
||||
:selection-color :white
|
||||
:style styles/text-input
|
||||
:on-focus #(do (reset! active? true)
|
||||
(when on-focus (on-focus)))
|
||||
:on-blur #(do (reset! active? false)
|
||||
(when on-blur (on-blur)))}
|
||||
(dissoc input-options :on-focus :on-blur))]]
|
||||
(when-not (nil? error)
|
||||
[tooltip error])]]))))
|
||||
|
||||
(defn amount-input [& [{:keys [input-options style]}]]
|
||||
(let [active? (reagent/atom false)
|
||||
{:keys [on-focus on-blur]} input-options]
|
||||
(fn []
|
||||
[react/view {:flex 1}
|
||||
[react/text {:style styles/label} (i18n/label :t/amount)]
|
||||
[react/view (merge (styles/amount-container @active?) style)
|
||||
[react/text-input
|
||||
(merge
|
||||
{:keyboard-type :numeric
|
||||
:placeholder "0.000"
|
||||
:placeholder-text-color "#ffffff66"
|
||||
:selection-color :white
|
||||
:style styles/text-input
|
||||
:on-focus #(do (reset! active? true)
|
||||
(when on-focus (on-focus)))
|
||||
:on-blur #(do (reset! active? false)
|
||||
(when on-blur (on-blur)))}
|
||||
(dissoc input-options :on-focus :on-blur))]]])))
|
||||
|
||||
;;TODO (andrey) this should be choose component with the list of currencies
|
||||
(defn choose-currency [& [style]]
|
||||
|
@ -33,6 +52,25 @@
|
|||
style)
|
||||
[react/text {:style styles/wallet-name} "ETH"]]])
|
||||
|
||||
(defn choose-recipient [{:keys [address name on-press style]}]
|
||||
(let [address? (and (not (nil? address)) (not= address ""))]
|
||||
[react/touchable-highlight {:on-press on-press}
|
||||
[react/view
|
||||
[react/text {:style styles/label} (i18n/label :t/recipient)]
|
||||
[react/view (merge styles/recipient-container
|
||||
style)
|
||||
(when name
|
||||
[react/view styles/recipient-name-container
|
||||
[react/text {:style (styles/participant true)
|
||||
:number-of-lines 1}
|
||||
name]])
|
||||
[react/view components.styles/flex
|
||||
[react/text {:style (styles/participant (and (not name) address?))
|
||||
:number-of-lines 1
|
||||
:ellipsizeMode :middle}
|
||||
(if address? address "Choose recipient...")]]
|
||||
[vector-icons/icon :icons/forward {:color :white}]]]]))
|
||||
|
||||
;;TODO (andrey) this should be choose component with the list of wallets
|
||||
(views/defview choose-wallet [& [style]]
|
||||
(views/letsubs [eth-balance [:eth-balance]]
|
||||
|
@ -41,10 +79,21 @@
|
|||
[react/view (merge styles/wallet-container
|
||||
style)
|
||||
[react/text {:style styles/wallet-name} "Main wallet"]
|
||||
[react/text {:style styles/wallet-value} (str eth-balance " ETH")]]]))
|
||||
[react/text {:style styles/wallet-value
|
||||
:number-of-lines 1
|
||||
:ellipsizeMode :middle}
|
||||
(str eth-balance " ETH")]]]))
|
||||
|
||||
(defn network-label
|
||||
([n] (network-label [{} n]))
|
||||
([style n] [react/view (merge styles/network-container
|
||||
style)
|
||||
[react/text {:style styles/network} n]]))
|
||||
[react/text {:style styles/network} n]]))
|
||||
|
||||
(defn separator []
|
||||
[react/view styles/separator])
|
||||
|
||||
(defn button-text [label]
|
||||
[react/text {:style styles/button-text
|
||||
:font (if platform/android? :medium :default)
|
||||
:uppercase? (get-in platform/platform-specific [:uppercase?])} label])
|
|
@ -1,6 +1,10 @@
|
|||
(ns status-im.ui.screens.wallet.db
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
status-im.ui.screens.wallet.request.db))
|
||||
status-im.ui.screens.wallet.request.db
|
||||
status-im.ui.screens.wallet.send.db
|
||||
[status-im.i18n :as i18n]
|
||||
[clojure.string :as string]))
|
||||
|
||||
;; (angusiguess) If we add more error types we can treat them as 'one-of' the following
|
||||
(spec/def :wallet/error #{:error})
|
||||
|
||||
|
@ -15,3 +19,20 @@
|
|||
|
||||
;; 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 get-amount-validation-error [amount web3]
|
||||
(let [amount' (string/replace amount #"," ".")
|
||||
amount-splited (string/split amount' #"[.]")]
|
||||
(cond
|
||||
(or (nil? amount) (= amount "") (= amount "0") (re-matches #"0[,.]0*$" amount))
|
||||
nil
|
||||
|
||||
(or (js/isNaN (js/parseFloat amount'))
|
||||
(try (when (<= (.toWei web3 amount' "ether") 0) true)
|
||||
(catch :default err true)))
|
||||
(i18n/label :t/validation-amount-invalid-number)
|
||||
|
||||
(and (= (count amount-splited) 2) (> (count (last amount-splited)) 18))
|
||||
(i18n/label :t/validation-amount-is-too-precise)
|
||||
|
||||
:else nil)))
|
|
@ -3,9 +3,6 @@
|
|||
(:require [status-im.components.styles :as styles]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(def wallet-container
|
||||
{:flex 1})
|
||||
|
||||
(def error-container
|
||||
{:align-self :center
|
||||
:justify-content :center
|
||||
|
@ -19,12 +16,9 @@
|
|||
:padding-right 10
|
||||
:font-size 13})
|
||||
|
||||
(def toolbar
|
||||
{:background-color (if platform/ios? styles/color-blue4 styles/color-blue5)
|
||||
:elevation 0})
|
||||
|
||||
(def toolbar-title-container
|
||||
{:flex-direction :row})
|
||||
{:flex-direction :row
|
||||
:padding-left 24})
|
||||
|
||||
(def toolbar-title-text
|
||||
{:color styles/color-white
|
||||
|
@ -59,21 +53,21 @@
|
|||
:color styles/color-white})
|
||||
|
||||
(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}})
|
||||
{:font-size 37
|
||||
:margin-left 9
|
||||
:color styles/color-white-transparent-5
|
||||
:android {:letter-spacing 1.5}
|
||||
:ios {:letter-spacing 1.16}})
|
||||
|
||||
(def value-variation
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(defstyle value-variation-title
|
||||
{:font-size 14
|
||||
:color styles/color-white-transparent-6
|
||||
:android {:letter-spacing -0.18}
|
||||
:ios {:letter-spacing -0.2}})
|
||||
{:font-size 14
|
||||
:color styles/color-white-transparent-6
|
||||
:android {:letter-spacing -0.18}
|
||||
:ios {:letter-spacing -0.2}})
|
||||
|
||||
(def today-variation-container
|
||||
{:border-radius 100
|
||||
|
@ -101,9 +95,9 @@
|
|||
{:color styles/color-red-4}))
|
||||
|
||||
(defstyle buttons
|
||||
{:margin-top 34
|
||||
:android {:margin-horizontal 21}
|
||||
:ios {:margin-horizontal 29}})
|
||||
{:margin-top 34
|
||||
:android {:margin-horizontal 21}
|
||||
:ios {:margin-horizontal 29}})
|
||||
|
||||
(defstyle main-button-text
|
||||
{:padding-vertical 13
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
[status-im.components.drawer.view :as drawer]
|
||||
[status-im.components.list.views :as list]
|
||||
[status-im.components.react :as react]
|
||||
[status-im.components.styles :as styles]
|
||||
[status-im.components.icons.vector-icons :as vi]
|
||||
[status-im.components.toolbar-new.view :as toolbar]
|
||||
[status-im.components.toolbar-new.actions :as act]
|
||||
|
@ -15,7 +14,9 @@
|
|||
[status-im.utils.config :as config]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet.main.styles :as wallet.styles]
|
||||
[status-im.ui.screens.wallet.main.styles :as styles]
|
||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.components.styles :as components.styles]
|
||||
[status-im.ui.screens.wallet.views :as wallet.views]))
|
||||
|
||||
(defn- show-not-implemented! []
|
||||
|
@ -23,18 +24,18 @@
|
|||
|
||||
(defn toolbar-title []
|
||||
[react/touchable-highlight {:on-press #(rf/dispatch [:navigate-to :wallet-list])}
|
||||
[react/view {:style wallet.styles/toolbar-title-container}
|
||||
[react/text {:style wallet.styles/toolbar-title-text
|
||||
[react/view {:style styles/toolbar-title-container}
|
||||
[react/text {:style styles/toolbar-title-text
|
||||
:font :toolbar-title}
|
||||
(i18n/label :t/main-wallet)]
|
||||
[vi/icon
|
||||
:icons/dropdown
|
||||
{:container-style wallet.styles/toolbar-title-icon
|
||||
{:container-style styles/toolbar-title-icon
|
||||
:color :white}]]])
|
||||
|
||||
(def transaction-history-action
|
||||
{:icon :icons/transaction-history
|
||||
:icon-opts (merge {:color :white :style {:viewBox "-108 65.9 24 24"}} wallet.styles/toolbar-icon)
|
||||
:icon-opts (merge {:color :white :style {:viewBox "-108 65.9 24 24"}} styles/toolbar-icon)
|
||||
:handler #(rf/dispatch [:navigate-to :wallet-transactions])})
|
||||
|
||||
(defn toolbar-view []
|
||||
|
@ -49,27 +50,27 @@
|
|||
(defn- change-display [change]
|
||||
(let [pos-change? (or (pos? change) (zero? change))]
|
||||
[react/view {:style (if pos-change?
|
||||
wallet.styles/today-variation-container-positive
|
||||
wallet.styles/today-variation-container-negative)}
|
||||
styles/today-variation-container-positive
|
||||
styles/today-variation-container-negative)}
|
||||
[react/text {:style (if pos-change?
|
||||
wallet.styles/today-variation-positive
|
||||
wallet.styles/today-variation-negative)}
|
||||
styles/today-variation-positive
|
||||
styles/today-variation-negative)}
|
||||
(if change
|
||||
(str (when pos-change? "+") change "%")
|
||||
"-%")]]))
|
||||
|
||||
(defn main-section [usd-value change error-message]
|
||||
[react/view {:style wallet.styles/main-section}
|
||||
(when error-message [wallet.views/error-message-view wallet.styles/error-container wallet.styles/error-message])
|
||||
[react/view {:style wallet.styles/total-balance-container}
|
||||
[react/view {:style wallet.styles/total-balance}
|
||||
[react/text {:style wallet.styles/total-balance-value} usd-value]
|
||||
[react/text {:style wallet.styles/total-balance-currency} "USD"]]
|
||||
[react/view {:style wallet.styles/value-variation}
|
||||
[react/text {:style wallet.styles/value-variation-title}
|
||||
[react/view {:style styles/main-section}
|
||||
(when error-message [wallet.views/error-message-view styles/error-container styles/error-message])
|
||||
[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} "USD"]]
|
||||
[react/view {:style styles/value-variation}
|
||||
[react/text {:style styles/value-variation-title}
|
||||
(i18n/label :t/wallet-total-value)]
|
||||
[change-display change]]
|
||||
[btn/buttons {:style wallet.styles/buttons :button-text-style wallet.styles/main-button-text}
|
||||
[btn/buttons {:style styles/buttons :button-text-style styles/main-button-text}
|
||||
[{:text (i18n/label :t/wallet-send)
|
||||
:on-press #(do (rf/dispatch [:navigate-to :wallet-send-transaction])
|
||||
(when platform/android?
|
||||
|
@ -83,15 +84,15 @@
|
|||
|
||||
(defn- token->image [id]
|
||||
(case id
|
||||
"eth" {:source (:ethereum resources/assets) :style (wallet.styles/asset-border styles/color-gray-transparent-light)}))
|
||||
"eth" {:source (:ethereum resources/assets) :style (styles/asset-border components.styles/color-gray-transparent-light)}))
|
||||
|
||||
(defn add-asset []
|
||||
[list/touchable-item show-not-implemented!
|
||||
[react/view
|
||||
[list/item
|
||||
[list/item-icon {:icon :icons/add :style wallet.styles/add-asset-icon :icon-opts {:color :blue}}]
|
||||
[react/view {:style wallet.styles/asset-item-value-container}
|
||||
[react/text {:style wallet.styles/add-asset-text}
|
||||
[list/item-icon {:icon :icons/add :style styles/add-asset-icon :icon-opts {:color :blue}}]
|
||||
[react/view {:style styles/asset-item-value-container}
|
||||
[react/text {:style styles/add-asset-text}
|
||||
(i18n/label :t/wallet-add-asset)]]]]])
|
||||
|
||||
(defn render-asset [{:keys [id currency amount]}]
|
||||
|
@ -101,9 +102,9 @@
|
|||
[react/view
|
||||
[list/item
|
||||
[list/item-image {:uri :launch_logo}]
|
||||
[react/view {:style wallet.styles/asset-item-value-container}
|
||||
[react/text {:style wallet.styles/asset-item-value} (str amount)]
|
||||
[react/text {:style wallet.styles/asset-item-currency
|
||||
[react/view {:style styles/asset-item-value-container}
|
||||
[react/text {:style styles/asset-item-value} (str amount)]
|
||||
[react/text {:style styles/asset-item-currency
|
||||
:uppercase? true}
|
||||
id]]
|
||||
[list/item-icon {:icon :icons/forward}]]]]
|
||||
|
@ -112,17 +113,17 @@
|
|||
[list/item
|
||||
(let [{:keys [source style]} (token->image id)]
|
||||
[list/item-image source style])
|
||||
[react/view {:style wallet.styles/asset-item-value-container}
|
||||
[react/text {:style wallet.styles/asset-item-value} (str amount)]
|
||||
[react/text {:style wallet.styles/asset-item-currency
|
||||
[react/view {:style styles/asset-item-value-container}
|
||||
[react/text {:style styles/asset-item-value} (str amount)]
|
||||
[react/text {:style styles/asset-item-currency
|
||||
:uppercase? true}
|
||||
id]]]]
|
||||
[add-asset]))
|
||||
|
||||
(defn asset-section [eth prices-loading? balance-loading?]
|
||||
(let [assets [{:id "eth" :currency :eth :amount eth}]]
|
||||
[react/view {:style wallet.styles/asset-section}
|
||||
[react/text {:style wallet.styles/asset-section-title} (i18n/label :t/wallet-assets)]
|
||||
[react/view {:style styles/asset-section}
|
||||
[react/text {:style styles/asset-section-title} (i18n/label :t/wallet-assets)]
|
||||
[list/flat-list
|
||||
{:data (conj assets {}) ;; Extra map triggers rendering for add-asset
|
||||
:render-fn render-asset
|
||||
|
@ -138,6 +139,6 @@
|
|||
error-message [:wallet/error-message?]]
|
||||
[react/view {:style wallet.styles/wallet-container}
|
||||
[toolbar-view]
|
||||
[react/view {:style styles/flex}
|
||||
[react/view components.styles/flex
|
||||
[main-section portfolio-value portfolio-change error-message]
|
||||
[asset-section eth-balance prices-loading? balance-loading?]]]))
|
||||
|
|
|
@ -15,3 +15,9 @@
|
|||
(defmethod navigation/preload-data! :wallet-request-transaction
|
||||
[db _]
|
||||
(dissoc db :wallet/request-transaction))
|
||||
|
||||
(defmethod navigation/preload-data! :wallet-send-transaction
|
||||
[db [event]]
|
||||
(if (= event :navigate-back)
|
||||
db
|
||||
(dissoc db :wallet/send-transaction)))
|
|
@ -3,6 +3,7 @@
|
|||
(:require [cljs.spec.alpha :as spec]))
|
||||
|
||||
(spec/def ::amount (spec/nilable string?))
|
||||
(spec/def ::amount-error (spec/nilable string?))
|
||||
|
||||
(spec/def :wallet/request-transaction (allowed-keys
|
||||
:opt-un [::amount]))
|
||||
:opt-un [::amount ::amount-error]))
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.ui.screens.wallet.request.events
|
||||
(:require
|
||||
[re-frame.core :as re-frame :refer [dispatch reg-fx]]
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.ui.screens.wallet.db :as wallet.db]))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet-send-request
|
||||
|
@ -10,4 +10,11 @@
|
|||
[:navigate-to-clean :chat-list]
|
||||
[:chat-with-command whisper-identity :request
|
||||
{:contact contact
|
||||
:amount (:amount request-transaction)}]]}))
|
||||
:amount (:amount request-transaction)}]]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet-validate-request-amount
|
||||
(fn [{{:keys [web3] :wallet/keys [request-transaction] :as db} :db} _]
|
||||
(let [amount (:amount request-transaction)
|
||||
error (wallet.db/get-amount-validation-error amount web3)]
|
||||
{:db (assoc-in db [:wallet/request-transaction :amount-error] error)})))
|
|
@ -1,9 +1,6 @@
|
|||
(ns status-im.ui.screens.wallet.request.styles
|
||||
(:require [status-im.components.styles :as styles]))
|
||||
|
||||
(def main-container
|
||||
{:flex 1})
|
||||
|
||||
(def network-label
|
||||
{:margin-top 27})
|
||||
|
||||
|
@ -14,44 +11,5 @@
|
|||
(def qr-container
|
||||
{:margin-top 16})
|
||||
|
||||
(def choose-wallet-container
|
||||
{:margin-top 27
|
||||
:margin-horizontal 15})
|
||||
|
||||
(def amount-container
|
||||
{:margin-top 16
|
||||
:margin-horizontal 15
|
||||
:flex-direction :row})
|
||||
|
||||
(def choose-currency-container
|
||||
{:margin-left 8})
|
||||
|
||||
(def choose-currency
|
||||
{:width 116})
|
||||
|
||||
(def separator
|
||||
{:height 1
|
||||
:margin-horizontal 15
|
||||
:background-color styles/color-white-transparent-1
|
||||
:margin-top 16})
|
||||
|
||||
(def buttons-container
|
||||
{:margin-vertical 15
|
||||
:padding-horizontal 12
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def share-icon-container
|
||||
{:margin-right 8})
|
||||
|
||||
(def forward-icon-container
|
||||
{:margin-left 8})
|
||||
|
||||
(def button-text
|
||||
{:color :white
|
||||
:font-size 15
|
||||
:letter-spacing -0.2})
|
||||
|
||||
(def button-container
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
|
@ -0,0 +1,11 @@
|
|||
(ns status-im.ui.screens.wallet.request.subs
|
||||
(:require [re-frame.core :as re-frame]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.request/request-enabled?
|
||||
:<- [:get-in [:wallet/request-transaction :amount]]
|
||||
:<- [:get-in [:wallet/request-transaction :amount-error]]
|
||||
(fn [[amount amount-error]]
|
||||
(and
|
||||
(nil? amount-error)
|
||||
(not (nil? amount)) (not= amount ""))))
|
|
@ -7,7 +7,7 @@
|
|||
[status-im.components.toolbar-new.actions :as actions]
|
||||
[status-im.components.toolbar-new.view :as toolbar]
|
||||
[status-im.components.status-bar :as status-bar]
|
||||
[status-im.ui.screens.wallet.send.styles :as wallet-styles]
|
||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.components.icons.vector-icons :as vi]
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
[status-im.ui.screens.wallet.request.styles :as styles]
|
||||
|
@ -16,7 +16,7 @@
|
|||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(defn toolbar-view []
|
||||
[toolbar/toolbar2 {:style wallet-styles/toolbar :hide-border? true}
|
||||
[toolbar/toolbar2 {:style wallet.styles/toolbar :hide-border? true}
|
||||
[toolbar/nav-button (actions/back-white actions/default-handler)]
|
||||
[toolbar/content-title {:color :white} (i18n/label :t/request-transaction)]])
|
||||
|
||||
|
@ -36,41 +36,40 @@
|
|||
:fgColor "#4360df"
|
||||
:size 256}]))
|
||||
|
||||
(defn button-text [label]
|
||||
[react/text {:style styles/button-text
|
||||
:font (if platform/android? :medium :default)
|
||||
:uppercase? (get-in platform/platform-specific [:uppercase?])} label])
|
||||
|
||||
(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 [scroll (atom nil)]
|
||||
[react/keyboard-avoiding-view wallet-styles/wallet-modal-container
|
||||
(views/letsubs [amount-error [:get-in [:wallet/request-transaction :amount-error]]
|
||||
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]
|
||||
[react/scroll-view {:ref #(reset! scroll %)}
|
||||
[react/view styles/main-container
|
||||
[react/view components.styles/flex
|
||||
[react/view styles/network-container
|
||||
;;TODO (andrey) name of active network should be used
|
||||
[components/network-label styles/network-label "Testnet"]
|
||||
[react/view styles/qr-container
|
||||
[qr-code]]]
|
||||
[react/view styles/choose-wallet-container
|
||||
[react/view wallet.styles/choose-wallet-container
|
||||
[components/choose-wallet]]
|
||||
[react/view styles/amount-container
|
||||
[react/view wallet.styles/amount-container
|
||||
[components/amount-input
|
||||
{:input-options {:on-focus (fn [] (when @scroll (js/setTimeout #(.scrollToEnd @scroll) 100)))
|
||||
{:error amount-error
|
||||
:input-options {:on-focus (fn [] (when @scroll (js/setTimeout #(.scrollToEnd @scroll) 100)))
|
||||
:on-change-text
|
||||
#(re-frame/dispatch [:set-in [:wallet/request-transaction :amount] %])}}]
|
||||
[react/view styles/choose-currency-container
|
||||
[components/choose-currency styles/choose-currency]]]]]
|
||||
[react/view styles/separator]
|
||||
[react/view styles/buttons-container
|
||||
#(do (re-frame/dispatch [:set-in [:wallet/request-transaction :amount] %])
|
||||
(re-frame/dispatch [:wallet-validate-request-amount]))}}]
|
||||
[react/view wallet.styles/choose-currency-container
|
||||
[components/choose-currency wallet.styles/choose-currency]]]]]
|
||||
[components/separator]
|
||||
[react/view wallet.styles/buttons-container
|
||||
[react/touchable-highlight {:on-press #()}
|
||||
[react/view styles/button-container
|
||||
[react/view (wallet.styles/button-container false)
|
||||
[vi/icon :icons/share {:color :white :container-style styles/share-icon-container}]
|
||||
[button-text (i18n/label :t/share)]]]
|
||||
[components/button-text (i18n/label :t/share)]]]
|
||||
[react/view components.styles/flex]
|
||||
[react/touchable-highlight {:on-press send-request}
|
||||
[react/view styles/button-container
|
||||
[button-text (i18n/label :t/send-request)]
|
||||
[vi/icon :icons/forward {:color :white :container-style styles/forward-icon-container}]]]]]))
|
||||
[react/touchable-highlight {:on-press (when request-enabled? send-request)}
|
||||
[react/view (wallet.styles/button-container request-enabled?)
|
||||
[components/button-text (i18n/label :t/send-request)]
|
||||
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]]))
|
|
@ -0,0 +1,11 @@
|
|||
(ns status-im.ui.screens.wallet.send.animations
|
||||
(:require [status-im.components.animation :as animation]))
|
||||
|
||||
(defn animate-sign-panel [opacity-value bottom-value]
|
||||
(animation/start
|
||||
(animation/parallel
|
||||
[(animation/timing opacity-value {:toValue 1
|
||||
:duration 500})
|
||||
(animation/timing bottom-value {:toValue 53
|
||||
:easing (.bezier animation/easing 0.685, 0.000, 0.025, 1.185)
|
||||
:duration 500})])))
|
|
@ -0,0 +1,17 @@
|
|||
(ns status-im.ui.screens.wallet.send.db
|
||||
(:require-macros [status-im.utils.db :refer [allowed-keys]])
|
||||
(:require [cljs.spec.alpha :as spec]))
|
||||
|
||||
(spec/def ::amount (spec/nilable string?))
|
||||
(spec/def ::to-address (spec/nilable string?))
|
||||
(spec/def ::to-name (spec/nilable string?))
|
||||
(spec/def ::amount-error (spec/nilable string?))
|
||||
(spec/def ::password (spec/nilable string?))
|
||||
(spec/def ::transaction-id (spec/nilable string?))
|
||||
(spec/def ::waiting-signal? (spec/nilable boolean?))
|
||||
(spec/def ::signing? (spec/nilable boolean?))
|
||||
(spec/def ::later? (spec/nilable boolean?))
|
||||
|
||||
(spec/def :wallet/send-transaction (allowed-keys
|
||||
:opt-un [::amount ::to-address ::to-name ::amount-error ::password
|
||||
::waiting-signal? ::signing? ::transaction-id ::later?]))
|
|
@ -1,8 +1,123 @@
|
|||
(ns status-im.ui.screens.wallet.send.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.screens.wallet.db :as wallet.db]))
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.ui.screens.wallet.db :as wallet.db]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.utils.types :as types]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
;;;; FX
|
||||
|
||||
(re-frame/reg-fx
|
||||
::accept-transaction
|
||||
(fn [{:keys [password id on-completed]}]
|
||||
(status/complete-transactions (list id) password on-completed)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::send-transaction
|
||||
(fn [{:keys [web3] :as params}]
|
||||
(when web3
|
||||
(.sendTransaction
|
||||
(.-eth web3)
|
||||
(clj->js (select-keys params [:from :to :value]))
|
||||
#()))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::show-transaction-moved
|
||||
(fn []
|
||||
(utils/show-popup (i18n/label :t/transaction-moved-title) (i18n/label :t/transaction-moved-text))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::discard-transaction
|
||||
(fn [id]
|
||||
(status/discard-transaction id)))
|
||||
|
||||
;;;; Handlers
|
||||
|
||||
(handlers/register-handler-db
|
||||
:choose-recipient
|
||||
(fn [db [_ recipient]]
|
||||
(assoc-in db [:wallet :send :recipient] recipient)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet-open-send-transaction
|
||||
(fn [{db :db} [_ address name]]
|
||||
{:db (update db :wallet/send-transaction
|
||||
#(assoc % :to-address address
|
||||
:to-name name))
|
||||
:dispatch-n [[:navigate-back]
|
||||
[:navigate-back]]}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet-validate-amount
|
||||
(fn [{{:keys [web3] :wallet/keys [send-transaction] :as db} :db} _]
|
||||
(let [amount (:amount send-transaction)
|
||||
error (wallet.db/get-amount-validation-error amount web3)]
|
||||
{:db (assoc-in db [:wallet/send-transaction :amount-error] error)})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::transaction-completed
|
||||
(fn [{db :db} [_ {:keys [id response]}]]
|
||||
(let [{:keys [hash error]} response]
|
||||
(when-not (and error (string? error) (not (string/blank? error)))
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet/send-transaction :transaction-id] nil)
|
||||
(assoc :wrong-password? false))
|
||||
:dispatch [:navigate-to :wallet-transaction-sent]}))))
|
||||
|
||||
(defn on-transactions-completed [raw-results]
|
||||
(let [results (:results (types/json->clj raw-results))]
|
||||
(doseq [result results]
|
||||
;;TODO (andrey) legacy, should be removed with old transactions screens
|
||||
(re-frame/dispatch [:transaction-completed {:id (name (key result)) :response (second result)}])
|
||||
(re-frame/dispatch [::transaction-completed {:id (name (key result)) :response (second result)}]))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet/transaction-queued
|
||||
(fn [{{:wallet/keys [send-transaction] :as db} :db} [_ transaction-id]]
|
||||
(let [{:keys [later? password]} send-transaction]
|
||||
(if later?
|
||||
{:db (-> db
|
||||
(assoc-in [:wallet/send-transaction :waiting-signal?] false)
|
||||
(assoc :transactions (:transactions-queue db)))
|
||||
:dispatch [:navigate-back]
|
||||
::show-transaction-moved nil}
|
||||
{:db (assoc-in db [:wallet/send-transaction :transaction-id] transaction-id)
|
||||
::accept-transaction {:id transaction-id
|
||||
:password password
|
||||
:on-completed on-transactions-completed}}))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet/sign-transaction
|
||||
(fn [{{:keys [web3]
|
||||
:wallet/keys [send-transaction]
|
||||
:accounts/keys [accounts current-account-id] :as db} :db} [_ later?]]
|
||||
(let [{:keys [amount transaction-id password]} send-transaction
|
||||
amount' (money/to-wei (string/replace amount #"," "."))]
|
||||
(if transaction-id
|
||||
{::accept-transaction {:id transaction-id
|
||||
:password password
|
||||
:on-completed on-transactions-completed}}
|
||||
{:db (update-in db [:wallet/send-transaction]
|
||||
#(assoc % :waiting-signal? true
|
||||
:later? later?))
|
||||
::send-transaction {:web3 web3
|
||||
:from (get-in accounts [current-account-id :address])
|
||||
:to (:to-address send-transaction)
|
||||
:value amount'}}))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet/discard-transaction
|
||||
(fn [{{:wallet/keys [send-transaction] :as db} :db} _]
|
||||
(let [{:keys [transaction-id]} send-transaction]
|
||||
(merge {:db (-> db
|
||||
(update-in [:wallet/send-transaction]
|
||||
#(assoc % :signing? false :transaction-id nil))
|
||||
(assoc :wrong-password? false))}
|
||||
(when transaction-id
|
||||
;;TODO (andrey) use ::discard-transaction fx instead
|
||||
{:dispatch-n [[:deny-transaction transaction-id]
|
||||
[:status-im.transactions.handlers/remove-transaction transaction-id]]})))))
|
|
@ -1,18 +1,9 @@
|
|||
(ns status-im.ui.screens.wallet.send.styles
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
||||
(:require [status-im.components.styles :as styles]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(def wallet-container
|
||||
{:flex 1
|
||||
:background-color styles/color-blue4})
|
||||
|
||||
(def wallet-modal-container
|
||||
{:flex 1
|
||||
:background-color styles/color-blue3})
|
||||
(:require [status-im.components.styles :as styles]))
|
||||
|
||||
(def toolbar
|
||||
{:background-color styles/color-blue4
|
||||
{:background-color styles/color-blue5
|
||||
:elevation 0
|
||||
:padding-bottom 10})
|
||||
|
||||
|
@ -33,119 +24,40 @@
|
|||
(def toolbar-title-icon
|
||||
(merge toolbar-icon {:opacity 0.4}))
|
||||
|
||||
(def toolbar-buttons-container
|
||||
{:flex-direction :row
|
||||
:flex-shrink 1
|
||||
:justify-content :space-between
|
||||
:width 68
|
||||
:margin-right 12})
|
||||
(defn animated-sign-panel [bottom-value]
|
||||
{:position :absolute
|
||||
:left 12
|
||||
:right 12
|
||||
:bottom bottom-value})
|
||||
|
||||
(def choose-recipient-container
|
||||
{:flex-direction :row
|
||||
:padding-top 20
|
||||
:padding-bottom 20
|
||||
:justify-content :center})
|
||||
(defn sign-panel [opacity-value]
|
||||
{:opacity opacity-value
|
||||
:border-radius 8
|
||||
:background-color :white
|
||||
:padding-top 12
|
||||
:padding-horizontal 12})
|
||||
|
||||
(def choose-recipient-label
|
||||
{:color :white})
|
||||
(def signing-phrase-container
|
||||
{:border-radius 8
|
||||
:height 36
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:background-color styles/color-light-gray})
|
||||
|
||||
(defstyle recipient-buttons
|
||||
{:flex-direction :column
|
||||
:margin-horizontal 28
|
||||
:margin-vertical 20
|
||||
:border-radius 8
|
||||
:ios {:background-color styles/color-blue6}})
|
||||
(def signing-phrase
|
||||
{:font-size 15
|
||||
:letter-spacing -0.2
|
||||
:color :black})
|
||||
|
||||
(def recipient-icon {:margin-right 20})
|
||||
(def signing-phrase-description
|
||||
{:padding-top 8})
|
||||
|
||||
(def recipient-icon-disabled {:margin-right 20
|
||||
:opacity 0.3})
|
||||
(def password-container
|
||||
{:flex 1
|
||||
:padding-vertical 20})
|
||||
|
||||
(def recipient-button
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:margin-vertical 10
|
||||
:margin-left 20})
|
||||
|
||||
(def recipient-button-text
|
||||
{:color :white
|
||||
:align-self :center
|
||||
:font-size 14})
|
||||
|
||||
(def recipient-button-text-disabled
|
||||
(merge recipient-button-text {:color "rgba(255, 255, 255, 0.3)"}))
|
||||
|
||||
(defnstyle recipient-touchable [divider?]
|
||||
(cond-> {:border-color styles/color-gray-transparent-light}
|
||||
divider? (assoc :ios {:border-bottom-width 1})))
|
||||
|
||||
(def recipient-touchable-disabled
|
||||
{:background-color styles/color-blue4
|
||||
:border-bottom-left-radius 8
|
||||
:border-bottom-right-radius 8
|
||||
:border-left-width 1
|
||||
:border-bottom-width 1
|
||||
:border-right-width 1
|
||||
:border-color "rgba(255, 255, 255, 0.3)"})
|
||||
|
||||
(def qr-container
|
||||
{:flex 1})
|
||||
|
||||
(def preview
|
||||
{:flex 1
|
||||
:justify-content :flex-end
|
||||
:align-items :center})
|
||||
|
||||
(def corner-dimensions
|
||||
{:position :absolute
|
||||
:width 40
|
||||
:height 40})
|
||||
|
||||
(defn corner-left-bottom [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:bottom (* viewport-offset dimension)
|
||||
:left (* viewport-offset dimension)})))
|
||||
|
||||
(defn corner-right-bottom [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:right (* viewport-offset dimension)
|
||||
:bottom (* viewport-offset dimension)})))
|
||||
|
||||
(defn corner-left-top [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:top (* viewport-offset dimension)
|
||||
:left (* viewport-offset dimension)})))
|
||||
|
||||
(defn corner-right-top [dimension]
|
||||
(let [viewport-offset 0.1666]
|
||||
(merge corner-dimensions {:top (* viewport-offset dimension)
|
||||
:right (* viewport-offset dimension)})))
|
||||
|
||||
(def viewfinder-port {:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:right 0
|
||||
:flex 1})
|
||||
|
||||
(defn viewfinder-translucent [height width side]
|
||||
(let [viewport-offset 0.1666
|
||||
height-offset (* viewport-offset height)
|
||||
width-offset (* viewport-offset width)]
|
||||
(cond-> {:position :absolute
|
||||
:background-color :black
|
||||
:opacity 0.7}
|
||||
(= :top side) (assoc :height height-offset
|
||||
:width width)
|
||||
(= :right side) (assoc :height (- height height-offset)
|
||||
:width width-offset
|
||||
:bottom 0
|
||||
:right 0)
|
||||
(= :bottom side) (assoc :height height-offset
|
||||
:width (- width width-offset)
|
||||
:bottom 0
|
||||
:left 0)
|
||||
(= :left side) (assoc :height (- height (* 2 height-offset))
|
||||
:width width-offset
|
||||
:top height-offset
|
||||
:left 0))))
|
||||
(def password
|
||||
{:padding 0
|
||||
:font-size 15
|
||||
:letter-spacing -0.2
|
||||
:height 20})
|
|
@ -4,3 +4,20 @@
|
|||
(re-frame/reg-sub :camera-dimensions
|
||||
(fn [db]
|
||||
(get-in db [:wallet :camera-dimensions])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.send/sign-enabled?
|
||||
:<- [:get-in [:wallet/send-transaction :amount]]
|
||||
:<- [:get-in [:wallet/send-transaction :to-address]]
|
||||
:<- [:get-in [:wallet/send-transaction :amount-error]]
|
||||
(fn [[amount to-address amount-error]]
|
||||
(and
|
||||
(nil? amount-error)
|
||||
(not (nil? to-address)) (not= to-address "")
|
||||
(not (nil? amount)) (not= amount ""))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.send/sign-password-enabled?
|
||||
:<- [:get-in [:wallet/send-transaction :password]]
|
||||
(fn [password]
|
||||
(and (not (nil? password)) (not= password ""))))
|
|
@ -0,0 +1,50 @@
|
|||
(ns status-im.ui.screens.wallet.send.transaction-sent.styles
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]]))
|
||||
|
||||
(def transaction-sent-container
|
||||
{:align-items :center})
|
||||
|
||||
(def ok-icon-container
|
||||
{:width 56
|
||||
:height 56
|
||||
:border-radius 28
|
||||
:background-color :white
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:margin-top 57
|
||||
:margin-bottom 16})
|
||||
|
||||
(def transaction-sent
|
||||
{:color :white
|
||||
:font-size 17})
|
||||
|
||||
(def gap
|
||||
{:height 8})
|
||||
|
||||
(def transaction-sent-description
|
||||
{:color :white
|
||||
:opacity 0.6
|
||||
:font-size 14
|
||||
:text-align :center
|
||||
:padding-horizontal 16})
|
||||
|
||||
(def transaction-details-container
|
||||
{:height 42
|
||||
:background-color "#00000033"
|
||||
:margin-horizontal 16
|
||||
:opacity 0.2
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius 8})
|
||||
|
||||
(def transaction-details
|
||||
{:color :white
|
||||
:font-size 15})
|
||||
|
||||
(def got-it-container
|
||||
{:align-items :center
|
||||
:padding-vertical 18})
|
||||
|
||||
(def got-it
|
||||
{:color :white
|
||||
:font-size 15})
|
|
@ -0,0 +1,38 @@
|
|||
(ns status-im.ui.screens.wallet.send.transaction-sent.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.components.react :as react]
|
||||
[status-im.components.status-bar :as status-bar]
|
||||
[status-im.components.icons.vector-icons :as vi]
|
||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.ui.screens.wallet.send.transaction-sent.styles :as styles]
|
||||
[status-im.components.styles :as components.styles]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(defview transaction-sent []
|
||||
[react/view wallet.styles/wallet-modal-container
|
||||
[status-bar/status-bar {:type :transparent}]
|
||||
[react/view styles/transaction-sent-container
|
||||
[react/view styles/ok-icon-container
|
||||
[vi/icon :icons/ok {:color components.styles/color-blue4}]]
|
||||
[react/text {:style styles/transaction-sent
|
||||
:font (if platform/android? :medium :default)}
|
||||
(i18n/label :t/transaction-sent)]
|
||||
[react/view styles/gap]
|
||||
[react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]]
|
||||
[react/view components.styles/flex]
|
||||
[react/touchable-highlight {:on-press #()}; TODO (andrey) #(re-frame/dispatch [:navigate-to-clean :wallet-transaction-details])}
|
||||
[react/view styles/transaction-details-container
|
||||
[react/text {:style styles/transaction-details
|
||||
:font (if platform/android? :medium :default)
|
||||
:uppercase? (get-in platform/platform-specific [:uppercase?])}
|
||||
(i18n/label :t/view-transaction-details)]]]
|
||||
[components/separator]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to-clean :wallet])}
|
||||
[react/view styles/got-it-container
|
||||
[react/text {:style styles/got-it
|
||||
:font (if platform/android? :medium :default)
|
||||
:uppercase? (get-in platform/platform-specific [:uppercase?])}
|
||||
(i18n/label :t/got-it)]]]])
|
|
@ -4,7 +4,6 @@
|
|||
[status-im.components.react :as react]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.components.button.view :as button]
|
||||
[status-im.components.styles :as styles]
|
||||
[status-im.components.status-bar :as status-bar]
|
||||
[status-im.components.toolbar-new.actions :as act]
|
||||
[status-im.components.toolbar-new.view :as toolbar]
|
||||
|
@ -13,77 +12,113 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.wallet.send.styles :as send.styles]
|
||||
[status-im.components.icons.vector-icons :as vector-icons]
|
||||
[reagent.core :as r]))
|
||||
[reagent.core :as r]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.screens.wallet.request.styles :as request.styles]
|
||||
[status-im.ui.screens.wallet.send.styles :as styles]
|
||||
[status-im.ui.screens.wallet.components.views :as components]
|
||||
[status-im.components.styles :as components.styles]
|
||||
[status-im.components.icons.vector-icons :as vi]
|
||||
[status-im.components.animation :as animation]
|
||||
[status-im.ui.screens.wallet.styles :as wallet.styles]
|
||||
[status-im.ui.screens.wallet.send.animations :as send.animations]))
|
||||
|
||||
(defn- show-not-implemented! []
|
||||
(utils/show-popup "TODO" "Not implemented yet!"))
|
||||
(defn toolbar-view [signing?]
|
||||
[toolbar/toolbar2 {:style wallet.styles/toolbar}
|
||||
[toolbar/nav-button (act/back-white (if signing?
|
||||
#(do (re-frame/dispatch [:wallet/discard-transaction])
|
||||
(act/default-handler))
|
||||
act/default-handler))]
|
||||
[toolbar/content-title {:color :white} (i18n/label :t/send-transaction)]])
|
||||
|
||||
(defn toolbar-view []
|
||||
[toolbar/toolbar2 {:style send.styles/toolbar
|
||||
:no-sync-bar? true}
|
||||
[toolbar/nav-button (act/close-white act/default-handler)]
|
||||
[toolbar/content-title {:color :white} (i18n/label :t/wallet-choose-recipient)]
|
||||
[toolbar/actions [{:icon :icons/flash-active
|
||||
:icon-opts {:color :white}
|
||||
:handler show-not-implemented!}]]])
|
||||
(defn sign-later []
|
||||
(utils/show-question
|
||||
(i18n/label :t/sign-later-title)
|
||||
(i18n/label :t/sign-later-text)
|
||||
#(re-frame/dispatch [:wallet/sign-transaction true])))
|
||||
|
||||
(defn recipient-buttons []
|
||||
[react/view {:style send.styles/recipient-buttons}
|
||||
[react/touchable-highlight {:style (send.styles/recipient-touchable true)}
|
||||
[react/view {:style send.styles/recipient-button}
|
||||
[react/text {:style send.styles/recipient-button-text}
|
||||
(i18n/label :t/wallet-choose-from-contacts)]
|
||||
[vector-icons/icon :icons/qr {:color :white
|
||||
:container-style send.styles/recipient-icon}]]]
|
||||
[react/touchable-highlight {:style (send.styles/recipient-touchable true)
|
||||
:on-press #(react/get-from-clipboard
|
||||
(fn [clipboard]
|
||||
(re-frame/dispatch [:choose-recipient clipboard])))}
|
||||
[react/view {:style send.styles/recipient-button}
|
||||
[react/text {:style send.styles/recipient-button-text}
|
||||
(i18n/label :t/wallet-address-from-clipboard)]
|
||||
[vector-icons/icon :icons/copy-from {:color :white
|
||||
:container-style send.styles/recipient-icon}]]]
|
||||
[react/touchable-highlight {:style send.styles/recipient-touchable-disabled}
|
||||
[react/view {:style send.styles/recipient-button}
|
||||
[react/text {:style send.styles/recipient-button-text-disabled}
|
||||
(i18n/label :t/wallet-browse-photos)]
|
||||
[vector-icons/icon :icons/browse {:color :white
|
||||
:container-style send.styles/recipient-icon-disabled}]]]])
|
||||
(defview sign-panel []
|
||||
(letsubs [account [:get-current-account]
|
||||
;;TODO (andrey) use send-transaction map after we remove old transactions ui
|
||||
wrong-password? [:get :wrong-password?];[:get-in [:wallet/send-transaction :wrong-password?]]
|
||||
signing-phrase (:signing-phrase @account)
|
||||
bottom-value (animation/create-value -250)
|
||||
opacity-value (animation/create-value 0)]
|
||||
{:component-did-mount #(send.animations/animate-sign-panel opacity-value bottom-value)}
|
||||
[react/animated-view {:style (styles/animated-sign-panel bottom-value)}
|
||||
[react/animated-view {:style (styles/sign-panel opacity-value)}
|
||||
[react/view styles/signing-phrase-container
|
||||
[react/text {:style styles/signing-phrase} signing-phrase]]
|
||||
[react/text {:style styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)]
|
||||
[react/view styles/password-container
|
||||
[react/text-input
|
||||
{:auto-focus true
|
||||
:secure-text-entry true
|
||||
:placeholder (i18n/label :t/enter-password)
|
||||
:placeholder-text-color "#939ba1"
|
||||
:on-change-text #(do
|
||||
(re-frame/dispatch [:set-in [:wallet/send-transaction :password] %]))
|
||||
:style styles/password}]]]
|
||||
(when wrong-password?
|
||||
[components/tooltip (i18n/label :t/wrong-password)])]))
|
||||
|
||||
(defn viewfinder [{:keys [height width]}]
|
||||
(let [min-dimension (min height width)]
|
||||
[react/view {:style send.styles/viewfinder-port}
|
||||
[react/view {:style (send.styles/viewfinder-translucent height width :top)}]
|
||||
[react/view {:style (send.styles/viewfinder-translucent height width :right)}]
|
||||
[react/view {:style (send.styles/viewfinder-translucent height width :bottom)}]
|
||||
[react/view {:style (send.styles/viewfinder-translucent height width :left)}]
|
||||
[react/image {:source {:uri :corner_left_top}
|
||||
:style (send.styles/corner-left-top min-dimension)}]
|
||||
[react/image {:source {:uri :corner_right_top}
|
||||
:style (send.styles/corner-right-top min-dimension)}]
|
||||
[react/image {:source {:uri :corner_left_bottom}
|
||||
:style (send.styles/corner-left-bottom min-dimension)}]
|
||||
[react/image {:source {:uri :corner_right_bottom}
|
||||
:style (send.styles/corner-right-bottom min-dimension)}]]))
|
||||
|
||||
(defview signing-buttons []
|
||||
(letsubs [sign-enabled? [:wallet.send/sign-password-enabled?]]
|
||||
[react/view wallet.styles/buttons-container
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/discard-transaction])}
|
||||
[react/view (wallet.styles/button-container true)
|
||||
[components/button-text (i18n/label :t/cancel)]]]
|
||||
[react/view components.styles/flex]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet/sign-transaction])}
|
||||
[react/view (wallet.styles/button-container sign-enabled?)
|
||||
[components/button-text (i18n/label :t/transactions-sign-transaction)]
|
||||
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||
|
||||
(defview sign-buttons []
|
||||
(letsubs [sign-enabled? [:wallet.send/sign-enabled?]]
|
||||
[react/view wallet.styles/buttons-container
|
||||
(when sign-enabled?
|
||||
[react/touchable-highlight {:on-press sign-later}
|
||||
[react/view (wallet.styles/button-container sign-enabled?)
|
||||
[components/button-text (i18n/label :t/transactions-sign-later)]]])
|
||||
[react/view components.styles/flex]
|
||||
[react/touchable-highlight {:on-press (when sign-enabled? #(re-frame/dispatch [:set-in [:wallet/send-transaction :signing?] true]))}
|
||||
[react/view (wallet.styles/button-container sign-enabled?)
|
||||
[components/button-text (i18n/label :t/transactions-sign-transaction)]
|
||||
[vi/icon :icons/forward {:color :white :container-style wallet.styles/forward-icon-container}]]]]))
|
||||
|
||||
(defview send-transaction []
|
||||
(letsubs [camera-dimensions [:camera-dimensions]]
|
||||
[react/view {:style send.styles/wallet-container}
|
||||
[status-bar/status-bar {:type :wallet}]
|
||||
[toolbar-view]
|
||||
[react/view {:style send.styles/qr-container
|
||||
:on-layout #(let [layout (.. % -nativeEvent -layout)]
|
||||
(re-frame/dispatch [:set-in [:wallet :camera-dimensions]
|
||||
{:width (.-width layout)
|
||||
:height (.-height layout)}]))}
|
||||
[camera/camera {:style send.styles/preview
|
||||
:aspect :fill
|
||||
:captureAudio false
|
||||
:onBarCodeRead (fn [code]
|
||||
(let [data (-> code
|
||||
.-data
|
||||
(str/replace #"ethereum:" ""))]
|
||||
(re-frame/dispatch [:choose-recipient data])))}]
|
||||
[viewfinder camera-dimensions]]
|
||||
[recipient-buttons]]))
|
||||
(letsubs [amount [:get-in [:wallet/send-transaction :amount]]
|
||||
amount-error [:get-in [:wallet/send-transaction :amount-error]]
|
||||
signing? [:get-in [:wallet/send-transaction :signing?]]
|
||||
to-address [:get-in [:wallet/send-transaction :to-address]]
|
||||
to-name [:get-in [:wallet/send-transaction :to-name]]]
|
||||
[react/keyboard-avoiding-view wallet.styles/wallet-modal-container
|
||||
[react/view components.styles/flex
|
||||
[status-bar/status-bar {:type :wallet}]
|
||||
[toolbar-view signing?]
|
||||
[react/scroll-view {:keyboardShouldPersistTaps :always}
|
||||
[react/view components.styles/flex
|
||||
[react/view wallet.styles/choose-participant-container
|
||||
[components/choose-recipient {:address to-address
|
||||
:name to-name
|
||||
:on-press #(re-frame/dispatch [:navigate-to :choose-recipient])}]]
|
||||
[react/view wallet.styles/choose-wallet-container
|
||||
[components/choose-wallet]]
|
||||
[react/view wallet.styles/amount-container
|
||||
[components/amount-input
|
||||
{:error amount-error
|
||||
:input-options {:auto-focus true
|
||||
:default-value amount
|
||||
:on-change-text #(do
|
||||
(re-frame/dispatch [:set-in [:wallet/send-transaction :amount] %])
|
||||
(re-frame/dispatch [:wallet-validate-amount]))}}]
|
||||
[react/view wallet.styles/choose-currency-container
|
||||
[components/choose-currency wallet.styles/choose-currency]]]]]
|
||||
[components/separator]
|
||||
(if signing?
|
||||
[signing-buttons]
|
||||
[sign-buttons])
|
||||
(when signing?
|
||||
[sign-panel])]]))
|
|
@ -1,5 +1,15 @@
|
|||
(ns status-im.ui.screens.wallet.styles
|
||||
(:require [status-im.components.styles :as st]))
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||
(:require [status-im.components.styles :as st]
|
||||
[status-im.components.styles :as styles]))
|
||||
|
||||
(def wallet-container
|
||||
{:flex 1})
|
||||
|
||||
(defstyle toolbar
|
||||
{:ios {:background-color styles/color-blue4}
|
||||
:android {:background-color styles/color-blue5
|
||||
:elevation 0}})
|
||||
|
||||
(def wallet-exclamation-container
|
||||
{:background-color st/color-red-2
|
||||
|
@ -13,3 +23,42 @@
|
|||
(def wallet-error-exclamation
|
||||
{:width 16
|
||||
:height 16})
|
||||
|
||||
(def buttons-container
|
||||
{:margin-vertical 15
|
||||
:padding-horizontal 12
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def forward-icon-container
|
||||
{:margin-left 8})
|
||||
|
||||
(defn button-container [enabled?]
|
||||
(merge
|
||||
{:flex-direction :row
|
||||
:align-items :center}
|
||||
(when-not enabled?
|
||||
{:opacity 0.4})))
|
||||
|
||||
(def wallet-modal-container
|
||||
{:flex 1
|
||||
:background-color styles/color-blue4})
|
||||
|
||||
(def choose-participant-container
|
||||
{:margin-top 16
|
||||
:margin-horizontal 15})
|
||||
|
||||
(def choose-wallet-container
|
||||
{:margin-top 16
|
||||
:margin-horizontal 15})
|
||||
|
||||
(def amount-container
|
||||
{:margin-top 16
|
||||
:margin-horizontal 15
|
||||
:flex-direction :row})
|
||||
|
||||
(def choose-currency-container
|
||||
{:margin-left 8})
|
||||
|
||||
(def choose-currency
|
||||
{:width 116})
|
|
@ -23,6 +23,9 @@
|
|||
(defn bignumber [n]
|
||||
(dependencies/Web3.prototype.toBigNumber (str n)))
|
||||
|
||||
(defn to-wei [str]
|
||||
(dependencies/Web3.prototype.toWei str "ether"))
|
||||
|
||||
(def eth-units
|
||||
{:wei (bignumber "1")
|
||||
:kwei (bignumber "1000")
|
||||
|
|
|
@ -24,6 +24,18 @@
|
|||
(when on-cancel {:onPress on-cancel}))
|
||||
{:text (or s "OK") :onPress on-accept :style "destructive"})))))
|
||||
|
||||
(defn show-question
|
||||
([title content on-accept]
|
||||
(show-question title content on-accept nil))
|
||||
([title content on-accept on-cancel]
|
||||
(.alert (.-Alert rn-dependencies/react-native)
|
||||
title
|
||||
content
|
||||
(clj->js
|
||||
(vector (merge {:text (i18n/label :t/no)}
|
||||
(when on-cancel {:onPress on-cancel}))
|
||||
{:text (i18n/label :t/yes) :onPress on-accept})))))
|
||||
|
||||
(defn http-post
|
||||
([action data on-success]
|
||||
(http-post action data on-success nil))
|
||||
|
|
Loading…
Reference in New Issue