From 3b4d140ef66a76a55827262b151f4d58eb0bfdcf Mon Sep 17 00:00:00 2001 From: angusiguess Date: Wed, 6 Sep 2017 16:55:49 -0400 Subject: [PATCH] Initial Commit for first send screen: - Update toolbar text - Add frame for camera/qr - Add button for choose contacts - Add button for address from clipboard - Add button for browse photos Set recipient from clipboard. Added functionality and event handling necessary to set recipient from clipboard. Add choose-recipient event to assoc into the database Add QR code scanning to first screen Add vector icons for copy and select image Fix svg Fix rebase, localize labels Add checkmark icon (this is a placeholder, current svg won't render) Remove leak from develop Vertical alignment fixes Vertically align maps in view Address review comments Fix rebase reference problems/styling issues Small style tweaks, fix icon Fix small design issues Indentation fixes Address review points Fix indentation Prevent permissions request on ios On ios, a permissions request results in a null reference error, do a platform check before performing a permissions request. Fix compile error --- resources/icons/copy_from.svg | 7 ++ resources/icons/flash_active.svg | 4 + .../components/icons/vector_icons.cljs | 4 +- src/status_im/components/react.cljs | 5 ++ src/status_im/components/styles.cljs | 1 + .../components/toolbar_new/styles.cljs | 6 +- .../components/toolbar_new/view.cljs | 7 +- src/status_im/translations/en.cljs | 9 ++- src/status_im/ui/screens/events.cljs | 1 + src/status_im/ui/screens/subs.cljs | 1 + src/status_im/ui/screens/wallet/db.cljs | 4 + .../ui/screens/wallet/main/views.cljs | 12 ++- .../ui/screens/wallet/send/events.cljs | 8 ++ .../ui/screens/wallet/send/styles.cljs | 80 +++++++++++++++++-- .../ui/screens/wallet/send/subs.cljs | 6 ++ .../ui/screens/wallet/send/views.cljs | 79 +++++++++++++++--- 16 files changed, 210 insertions(+), 24 deletions(-) create mode 100644 resources/icons/copy_from.svg create mode 100644 resources/icons/flash_active.svg create mode 100644 src/status_im/ui/screens/wallet/send/events.cljs create mode 100644 src/status_im/ui/screens/wallet/send/subs.cljs diff --git a/resources/icons/copy_from.svg b/resources/icons/copy_from.svg new file mode 100644 index 0000000000..7f8e9f618e --- /dev/null +++ b/resources/icons/copy_from.svg @@ -0,0 +1,7 @@ + + + + + + diff --git a/resources/icons/flash_active.svg b/resources/icons/flash_active.svg new file mode 100644 index 0000000000..98c30cb28a --- /dev/null +++ b/resources/icons/flash_active.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/status_im/components/icons/vector_icons.cljs b/src/status_im/components/icons/vector_icons.cljs index 6ad6f2f5b5..730744c447 100644 --- a/src/status_im/components/icons/vector_icons.cljs +++ b/src/status_im/components/icons/vector_icons.cljs @@ -39,10 +39,12 @@ :icons/address (slurp-svg "./resources/icons/address.svg") :icons/arrow-left (slurp-svg "./resources/icons/arrow_left.svg") :icons/arrow-right (slurp-svg "./resources/icons/arrow_right.svg") + :icons/flash-active (slurp-svg "./resources/icons/flash_active.svg") :icons/attach (slurp-svg "./resources/icons/attach.svg") :icons/back (slurp-svg "./resources/icons/back.svg") :icons/browse (slurp-svg "./resources/icons/browse.svg") :icons/close (slurp-svg "./resources/icons/close.svg") + :icons/copy-from (slurp-svg "./resources/icons/copy_from.svg") :icons/dots-horizontal (slurp-svg "./resources/icons/dots_horizontal.svg") :icons/dots-vertical (slurp-svg "./resources/icons/dots_vertical.svg") :icons/exclamation_mark (slurp-svg "./resources/icons/exclamation_mark.svg") @@ -100,4 +102,4 @@ color :else styles/icon-dark-color)))) - (throw (js/Error. (str "Unknown icon: " name))))])) + (throw (js/Error. (str "Unknown icon: " name))))])) \ No newline at end of file diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index 7c67dd058c..fe63e8228d 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -155,6 +155,11 @@ (defn copy-to-clipboard [text] (.setString (.-Clipboard rn-dependencies/react-native) text)) +(defn get-from-clipboard [clbk] + (let [clipboard-contents (.getString (.-Clipboard rn-dependencies/react-native))] + (.then clipboard-contents #(clbk %)))) + + ;; Emoji (def emoji-picker-class rn-dependencies/emoji-picker) diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs index 1bd4382fcd..1392d0c92d 100644 --- a/src/status_im/components/styles.cljs +++ b/src/status_im/components/styles.cljs @@ -11,6 +11,7 @@ (def color-black "#000000") (def color-purple "#a187d5") (def color-gray-transparent-light "rgba(0, 0, 0, 0.1)") +(def color-gray-transparent-medium-light "rgba(0, 0, 0, 0.2)") (def color-gray-transparent "rgba(0, 0, 0, 0.4)") (def color-gray4-transparent "rgba(147, 155, 161, 0.2)") (def color-gray10-transparent "rgba(184, 193, 199, 0.5)") diff --git a/src/status_im/components/toolbar_new/styles.cljs b/src/status_im/components/toolbar_new/styles.cljs index 2a49e2fd4a..b2bc42de16 100644 --- a/src/status_im/components/toolbar_new/styles.cljs +++ b/src/status_im/components/toolbar_new/styles.cljs @@ -30,6 +30,11 @@ :android {:padding-left 18} :ios {:align-items :center}}) +(def toolbar-title-container + {:flex 1 + :flex-direction :column + :margin-left 6}) + (defstyle toolbar-title-text {:color styles/text1-color :letter-spacing -0.2 @@ -101,4 +106,3 @@ (def toolbar-text-action-disabled {:color styles/color-gray7}) (def item-text-white-background {:color styles/color-blue4}) - diff --git a/src/status_im/components/toolbar_new/view.cljs b/src/status_im/components/toolbar_new/view.cljs index bee14ac57d..2dfd411f00 100644 --- a/src/status_im/components/toolbar_new/view.cljs +++ b/src/status_im/components/toolbar_new/view.cljs @@ -48,10 +48,13 @@ (defn content-title ([title] (content-title nil title)) ([title-style title] - [content-wrapper + (content-title title-style title nil nil)) + ([title-style title subtitle-style subtitle] + [rn/view {:style tst/toolbar-title-container} [rn/text {:style (merge tst/toolbar-title-text title-style) :font :toolbar-title} - title]])) + title] + (when subtitle [rn/text {:style subtitle-style} subtitle])])) ;; Actions diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index c9f9400ff4..ca83702060 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -374,6 +374,13 @@ :transactions-filter-tokens "Tokens" :transactions-filter-type "Type" :transactions-filter-select-all "Select all" + ;; Wallet Send + :wallet-send-transaction "Send Transaction" + :wallet-send-step-one "Step 1 of 3" + :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" ;network settings :new-network "New network" @@ -393,4 +400,4 @@ :remove-network "Remove network" :network-settings "Network settings" :edit-network-warning "Be careful, editing the network data may disable this network for you" - :connecting-requires-login "Connecting to another network requires login"}) + :connecting-requires-login "Connecting to another network requires login"}) \ No newline at end of file diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index 8c3fe3e7c0..b0c0651bf0 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -17,6 +17,7 @@ status-im.ui.screens.profile.events status-im.ui.screens.qr-scanner.events status-im.ui.screens.wallet.events + status-im.ui.screens.wallet.send.events [re-frame.core :refer [dispatch reg-fx reg-cofx]] [status-im.native-module.core :as status] [status-im.components.permissions :as permissions] diff --git a/src/status_im/ui/screens/subs.cljs b/src/status_im/ui/screens/subs.cljs index 7367d1b581..07595530b4 100644 --- a/src/status_im/ui/screens/subs.cljs +++ b/src/status_im/ui/screens/subs.cljs @@ -10,6 +10,7 @@ status-im.ui.screens.profile.subs status-im.ui.screens.wallet.subs status-im.ui.screens.wallet.transactions.subs + status-im.ui.screens.wallet.send.subs status-im.ui.screens.network-settings.subs status-im.transactions.subs status-im.bots.subs)) diff --git a/src/status_im/ui/screens/wallet/db.cljs b/src/status_im/ui/screens/wallet/db.cljs index 8158f9a2a5..7639b9e0f9 100644 --- a/src/status_im/ui/screens/wallet/db.cljs +++ b/src/status_im/ui/screens/wallet/db.cljs @@ -4,6 +4,10 @@ ;; (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])) ;; Placeholder namespace for wallet specs, which are a WIP depending on data diff --git a/src/status_im/ui/screens/wallet/main/views.cljs b/src/status_im/ui/screens/wallet/main/views.cljs index f7d87c6fad..6adb06301d 100644 --- a/src/status_im/ui/screens/wallet/main/views.cljs +++ b/src/status_im/ui/screens/wallet/main/views.cljs @@ -12,7 +12,9 @@ [status-im.components.toolbar-new.actions :as act] [status-im.i18n :as i18n] [status-im.react-native.resources :as resources] + [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.views :as wallet.views])) @@ -69,9 +71,13 @@ [change-display change]] [btn/buttons {:style wallet.styles/buttons :button-text-style wallet.styles/main-button-text} [{:text (i18n/label :t/wallet-send) - :on-press show-not-implemented!} - {:text (i18n/label :t/wallet-request) - :on-press show-not-implemented!} + :on-press #(do (rf/dispatch [:navigate-to :wallet-send-transaction]) + (when platform/android? + (rf/dispatch [:request-permissions [:camera]]))) + :disabled? (not config/wallet-wip-enabled?)} + {:text (i18n/label :t/wallet-request) + :on-press #(rf/dispatch [:navigate-to :wallet-request-transaction]) + :disabled? (not config/wallet-wip-enabled?)} {:text (i18n/label :t/wallet-exchange) :disabled? true}]]]]) diff --git a/src/status_im/ui/screens/wallet/send/events.cljs b/src/status_im/ui/screens/wallet/send/events.cljs new file mode 100644 index 0000000000..085d32f666 --- /dev/null +++ b/src/status_im/ui/screens/wallet/send/events.cljs @@ -0,0 +1,8 @@ +(ns status-im.ui.screens.wallet.send.events + (:require [re-frame.core :as re-frame] + [status-im.ui.screens.wallet.db :as wallet.db])) + +(re-frame/reg-event-db + :choose-recipient + (fn [db [_ recipient]] + (assoc-in db [:wallet :send :recipient] recipient))) diff --git a/src/status_im/ui/screens/wallet/send/styles.cljs b/src/status_im/ui/screens/wallet/send/styles.cljs index 91345cc568..ccb39475a5 100644 --- a/src/status_im/ui/screens/wallet/send/styles.cljs +++ b/src/status_im/ui/screens/wallet/send/styles.cljs @@ -4,16 +4,16 @@ (def wallet-container {:flex 1 - :background-color styles/color-white}) + :background-color styles/color-blue2}) (def wallet-modal-container {:flex 1 :background-color styles/color-blue4}) -(defstyle toolbar - {:ios {:background-color styles/color-blue4} - :android {:background-color styles/color-blue5 - :elevation 0}}) +(def toolbar + {:background-color styles/color-blue5 + :elevation 0 + :padding-bottom 10}) (def toolbar-title-container {:flex 1 @@ -30,4 +30,72 @@ :height 24}) (def toolbar-title-icon - (merge toolbar-icon {:opacity 0.4})) \ No newline at end of file + (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}) + +(def choose-recipient-container + {:flex-direction :row + :padding-top 20 + :padding-bottom 20 + :justify-content :center}) + +(def choose-recipient-label + {:color :white}) + +(def recipient-buttons + {:flex-direction :column + :margin-horizontal 28 + :margin-vertical 10 + :border-radius 5 + :background-color styles/color-blue5}) + +(def recipient-icon {:margin-right 20}) + +(def recipient-button + {:flex-direction :row + :justify-content :space-between + :margin-vertical 10 + :margin-left 20}) + +(def recipient-button-text + {:color :white + :font-size 17}) + +(defn recipient-touchable [divider?] + (cond-> {:border-color styles/color-gray-transparent-medium-light} + divider? (assoc :border-bottom-width 1))) + +(def qr-container + {:flex 1 + :margin-horizontal 32}) + +(def preview + {:flex 1 + :justify-content :flex-end + :align-items :center}) + +(defn outer-bezel [{:keys [height width]}] + {:position :absolute + :top -10 + :left -10 + :border-radius 20 + :border-color styles/color-blue2 + :border-width 20 + :height (+ height 20) + :width (+ width 20)}) + +(defn inner-bezel [{:keys [height width]}] + {:top 5 + :left 5 + :position :absolute + :border-radius 20 + :border-color :white + :border-width 5 + :height (- height 10) + :width (- width 10)}) diff --git a/src/status_im/ui/screens/wallet/send/subs.cljs b/src/status_im/ui/screens/wallet/send/subs.cljs new file mode 100644 index 0000000000..bef5f27b80 --- /dev/null +++ b/src/status_im/ui/screens/wallet/send/subs.cljs @@ -0,0 +1,6 @@ +(ns status-im.ui.screens.wallet.send.subs + (:require [re-frame.core :as re-frame])) + +(re-frame/reg-sub :camera-dimensions + (fn [db] + (get-in db [:wallet :camera-dimensions]))) diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index 47b7e97684..7acdbe75ca 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -1,17 +1,76 @@ (ns status-im.ui.screens.wallet.send.views - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [status-im.components.react :as rn] + (:require-macros [status-im.utils.views :refer [defview letsubs]]) + (:require [clojure.string :as str] + [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] - [status-im.ui.screens.wallet.send.styles :as cst])) + [status-im.components.camera :as camera] + [status-im.utils.utils :as utils] + [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])) + +(defn- show-not-implemented! [] + (utils/show-popup "TODO" "Not implemented yet!")) (defn toolbar-view [] - [toolbar/toolbar2 {:style cst/toolbar} - [toolbar/nav-button (act/back-white act/default-handler)] - [toolbar/content-title {:color :white} "Send Transaction"]]) + [toolbar/toolbar2 {:style send.styles/toolbar} + [toolbar/nav-button (act/close-white act/default-handler)] + [toolbar/content-title {:color :white} (i18n/label :t/wallet-send-transaction) + {:color styles/color-light-blue} (i18n/label :t/wallet-send-step-one)] + [toolbar/actions [{:icon :icons/flash-active + :icon-opts {:color :white} + :handler show-not-implemented!}]]]) + +(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/contacts {: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 false)} + [react/view {:style send.styles/recipient-button} + [react/text {:style send.styles/recipient-button-text} + (i18n/label :t/wallet-browse-photos)] + [vector-icons/icon :icons/browse {:color :white + :container-style send.styles/recipient-icon}]]]]) (defview send-transaction [] - [] - [rn/view {:style cst/wallet-container} - [toolbar-view] - [rn/text "Nothing here yet!"]]) + (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/choose-recipient-container} + [react/text {:style send.styles/choose-recipient-label} (i18n/label :t/wallet-choose-recipient)]] + [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])))}] + [react/view {:style (send.styles/outer-bezel camera-dimensions)}] + [react/view {:style (send.styles/inner-bezel camera-dimensions)}]] + [recipient-buttons]]))