transaction screens UI refresh
After Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 253 B After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 226 B |
Before Width: | Height: | Size: 201 B After Width: | Height: | Size: 251 B |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 934 B |
After Width: | Height: | Size: 549 B |
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 603 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 546 B After Width: | Height: | Size: 886 B |
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_arrow_left_white.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
ios/StatusIm/Images.xcassets/icon_arrow_left_white.imageset/icon_arrow_left_white.png
vendored
Normal file
After Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 384 B |
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "iconOkBig.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "iconOkBig@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "iconOkBig@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 934 B |
After Width: | Height: | Size: 1.5 KiB |
|
@ -22,7 +22,9 @@
|
|||
[status-im.accounts.login.screen :refer [login]]
|
||||
[status-im.accounts.recover.screen :refer [recover]]
|
||||
[status-im.accounts.screen :refer [accounts]]
|
||||
[status-im.transactions.screen :refer [confirm]]
|
||||
[status-im.transactions.screens.confirmation-success :refer [confirmation-success]]
|
||||
[status-im.transactions.screens.pending-transactions :refer [pending-transactions]]
|
||||
[status-im.transactions.screens.transaction-details :refer [transaction-details]]
|
||||
[status-im.chats-list.screen :refer [chats-list]]
|
||||
[status-im.new-chat.screen :refer [new-chat]]
|
||||
[status-im.new-group.screen-public :refer [new-public-group]]
|
||||
|
@ -149,7 +151,9 @@
|
|||
(let [component (case @modal-view
|
||||
:qr-scanner qr-scanner
|
||||
:qr-code-view qr-code-view
|
||||
:confirm confirm
|
||||
:pending-transactions pending-transactions
|
||||
:transaction-details transaction-details
|
||||
:confirmation-success confirmation-success
|
||||
:contact-list-modal contact-list-modal)]
|
||||
[component])]])]]))))})))
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
(if (:sent-to-jail? message)
|
||||
;; todo there could be other reasons for "long-running"
|
||||
;; hanling of the command besides sendTransaction
|
||||
(dispatch [:navigate-to-modal :confirm])
|
||||
(dispatch [:navigate-to-modal :pending-transactions])
|
||||
(cond
|
||||
(console-command? chat-id command-name)
|
||||
(dispatch [:invoke-console-command-handler! params'])
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
{:style st/gradient-top
|
||||
:colors st/gradient-top-colors}]))
|
||||
|
||||
(defn separator [style]
|
||||
[view st/separator-wrapper
|
||||
(defn separator [style wrapper-style]
|
||||
[view (merge st/separator-wrapper wrapper-style)
|
||||
[view (merge st/separator style)]])
|
||||
|
||||
(defn form-spacer []
|
||||
|
|
|
@ -13,12 +13,19 @@
|
|||
(def color-gray6 "#212121")
|
||||
(def color-steel "#838b91")
|
||||
(def color-white "white")
|
||||
(def color-white-transparent "#ffffff66")
|
||||
(def color-white-transparent-2 "#fefefe21")
|
||||
(def color-light-blue "#628fe3")
|
||||
(def color-light-blue-transparent "#628fe333")
|
||||
(def color-light-blue2 "#eff3fc")
|
||||
(def color-light-blue3 "#a0bcf0")
|
||||
(def color-dark-blue-1 "#252c4a")
|
||||
(def color-dark-blue-2 "#1f253f")
|
||||
(def color-dark-blue-3 "#191f37")
|
||||
(def color-light-gray "#EEF2F5")
|
||||
(def color-red "red")
|
||||
(def color-light-red "#e86363")
|
||||
(def color-light-red2 "#f47979")
|
||||
|
||||
(def color-separator "#D6D6D6")
|
||||
|
||||
|
|
|
@ -41,4 +41,5 @@
|
|||
(merge input-error-text-style
|
||||
{:color color
|
||||
:background-color :transparent
|
||||
:font-size 12})))
|
||||
:font-size 12
|
||||
:line-height 20})))
|
||||
|
|
|
@ -115,8 +115,8 @@
|
|||
max-length]} (r/state component)
|
||||
{:keys [wrapper-style input-style label-hidden? line-color focus-line-color focus-line-height
|
||||
secure-text-entry label-color error-color error label value on-focus on-blur validator
|
||||
auto-focus on-change-text on-change on-end-editing editable placeholder auto-capitalize
|
||||
multiline number-of-lines]}
|
||||
auto-focus on-change-text on-change on-end-editing editable placeholder
|
||||
placeholder-text-color auto-capitalize multiline number-of-lines]}
|
||||
(merge default-props (r/props component))
|
||||
line-color (if error error-color line-color)
|
||||
focus-line-color (if error error-color focus-line-color)
|
||||
|
@ -126,50 +126,51 @@
|
|||
[view (merge st/text-field-container wrapper-style)
|
||||
(when-not label-hidden?
|
||||
[animated-text {:style (st/label label-top label-font-size label-color)} label])
|
||||
[text-input {:ref #(reset! input-ref %)
|
||||
:style (merge st/text-input input-style)
|
||||
:placeholder (or placeholder "")
|
||||
:editable editable
|
||||
:multiline multiline
|
||||
:number-of-lines number-of-lines
|
||||
:secure-text-entry secure-text-entry
|
||||
:auto-capitalize auto-capitalize
|
||||
:on-focus #(on-input-focus {:component component
|
||||
:animation {:top label-top
|
||||
:to-top (:label-top config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-small config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-height focus-line-height}
|
||||
:onFocus on-focus})
|
||||
:on-blur #(on-input-blur {:component component
|
||||
:value (or current-value value)
|
||||
:animation {:top label-top
|
||||
:to-top (:label-bottom config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-large config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-width 0
|
||||
:to-line-height 1}
|
||||
:onBlur on-blur})
|
||||
:on-change-text (fn [text]
|
||||
(r/set-state component {:current-value text})
|
||||
(if (or (not validator) (validator text))
|
||||
(do
|
||||
(r/set-state component {:valid-value text
|
||||
:temp-value nil})
|
||||
(on-change-text text))
|
||||
(r/set-state component {:temp-value valid-value
|
||||
:max-length (count valid-value)})))
|
||||
:on-change #(on-change %)
|
||||
:default-value value
|
||||
:value temp-value
|
||||
:max-length max-length
|
||||
:on-submit-editing #(.blur @input-ref)
|
||||
:on-end-editing (when on-end-editing on-end-editing)
|
||||
:auto-focus (true? auto-focus)}]
|
||||
[text-input {:ref #(reset! input-ref %)
|
||||
:style (merge st/text-input input-style)
|
||||
:placeholder (or placeholder "")
|
||||
:placeholder-text-color placeholder-text-color
|
||||
:editable editable
|
||||
:multiline multiline
|
||||
:number-of-lines number-of-lines
|
||||
:secure-text-entry secure-text-entry
|
||||
:auto-capitalize auto-capitalize
|
||||
:on-focus #(on-input-focus {:component component
|
||||
:animation {:top label-top
|
||||
:to-top (:label-top config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-small config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-height focus-line-height}
|
||||
:onFocus on-focus})
|
||||
:on-blur #(on-input-blur {:component component
|
||||
:value (or current-value value)
|
||||
:animation {:top label-top
|
||||
:to-top (:label-bottom config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-large config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-width 0
|
||||
:to-line-height 1}
|
||||
:onBlur on-blur})
|
||||
:on-change-text (fn [text]
|
||||
(r/set-state component {:current-value text})
|
||||
(if (or (not validator) (validator text))
|
||||
(do
|
||||
(r/set-state component {:valid-value text
|
||||
:temp-value nil})
|
||||
(on-change-text text))
|
||||
(r/set-state component {:temp-value valid-value
|
||||
:max-length (count valid-value)})))
|
||||
:on-change #(on-change %)
|
||||
:default-value value
|
||||
:value temp-value
|
||||
:max-length max-length
|
||||
:on-submit-editing #(.blur @input-ref)
|
||||
:on-end-editing (when on-end-editing on-end-editing)
|
||||
:auto-focus (true? auto-focus)}]
|
||||
[view {:style (st/underline-container line-color)
|
||||
:onLayout #(r/set-state component {:max-line-width (get-width %)})}
|
||||
[animated-view {:style (st/underline focus-line-color line-width line-height)}]]
|
||||
|
|
|
@ -45,3 +45,7 @@
|
|||
:style st/action-default}
|
||||
:handler handler})
|
||||
|
||||
(defn close-white [handler]
|
||||
{:image {:source {:uri :icon_close_white}
|
||||
:style st/action-default}
|
||||
:handler handler})
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
background-color :background-color
|
||||
custom-content :custom-content
|
||||
hide-border? :hide-border?
|
||||
border-style :border-style
|
||||
style :style}]
|
||||
(let [style (merge (st/toolbar-wrapper background-color) style)]
|
||||
[view {:style style}
|
||||
|
@ -66,7 +67,7 @@
|
|||
custom-action)]]
|
||||
[sync-state-gradient-view]
|
||||
(when-not hide-border?
|
||||
[view st/toolbar-border-container
|
||||
[view (merge st/toolbar-border-container border-style)
|
||||
[view st/toolbar-border]])]))
|
||||
|
||||
(def search-text-input (r/atom nil))
|
||||
|
@ -122,4 +123,3 @@
|
|||
nav-action)
|
||||
:custom-content [toolbar-with-search-content opts]
|
||||
:actions actions}]))
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
[status-im.accounts.login.screen :refer [login]]
|
||||
[status-im.accounts.recover.screen :refer [recover]]
|
||||
[status-im.accounts.screen :refer [accounts]]
|
||||
[status-im.transactions.screen :refer [confirm]]
|
||||
[status-im.transactions.screens.confirmation-success :refer [confirmation-success]]
|
||||
[status-im.transactions.screens.pending-transactions :refer [pending-transactions]]
|
||||
[status-im.transactions.screens.transaction-details :refer [transaction-details]]
|
||||
[status-im.chats-list.screen :refer [chats-list]]
|
||||
[status-im.new-chat.screen :refer [new-chat]]
|
||||
[status-im.new-group.screen-private :refer [new-group
|
||||
|
@ -131,7 +133,9 @@
|
|||
(let [component (case @modal-view
|
||||
:qr-scanner qr-scanner
|
||||
:qr-code-view qr-code-view
|
||||
:confirm confirm
|
||||
:pending-transactions pending-transactions
|
||||
:transaction-details transaction-details
|
||||
:confirmation-success confirmation-success
|
||||
:contact-list-modal contact-list-modal)]
|
||||
[component])]])]))))})))
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
;; && :navigation-replace <- on success
|
||||
|
||||
|
||||
(defmethod nav/preload-data! :confirm
|
||||
(defmethod nav/preload-data! :pending-transactions
|
||||
[{:keys [transactions-queue] :as db} _]
|
||||
(-> db
|
||||
(assoc :transactions transactions-queue
|
||||
|
@ -30,6 +30,14 @@
|
|||
:wrong-password? false)
|
||||
(assoc-in [:confirm-transactions :password] "")))
|
||||
|
||||
(defmethod nav/preload-data! :transaction-details
|
||||
[db [_ _ transaction]]
|
||||
(-> db
|
||||
(assoc :selected-transaction transaction
|
||||
:wrong-password-counter 0
|
||||
:wrong-password? false)
|
||||
(assoc-in [:confirm-transactions :password] "")))
|
||||
|
||||
(defn on-unlock
|
||||
[ids password]
|
||||
(dispatch [:set :wrong-password? false])
|
||||
|
@ -47,6 +55,11 @@
|
|||
(let [ids (keys transactions)]
|
||||
(on-unlock ids password)))))
|
||||
|
||||
(register-handler :accept-transaction
|
||||
(u/side-effect!
|
||||
(fn [{:keys [transactions]} [_ password id]]
|
||||
(on-unlock (list id) password))))
|
||||
|
||||
(register-handler :deny-transactions
|
||||
(u/side-effect!
|
||||
(fn [{:keys [transactions]}]
|
||||
|
@ -56,8 +69,7 @@
|
|||
(dispatch [::remove-pending-messages messages-ids])
|
||||
(dispatch [::remove-transactions ids])
|
||||
(doseq [id ids]
|
||||
(dispatch [::discard-transaction id]))
|
||||
(dispatch [:navigate-back])))))
|
||||
(dispatch [::discard-transaction id]))))))
|
||||
|
||||
(register-handler :deny-transaction
|
||||
(u/side-effect!
|
||||
|
@ -80,9 +92,6 @@
|
|||
(update :transactions-queue #(apply dissoc % hashes)))))
|
||||
|
||||
(register-handler ::remove-transaction
|
||||
(after (fn [{:keys [modal]}]
|
||||
(when (= :confirm modal)
|
||||
(dispatch [:navigate-back]))))
|
||||
(fn [db [_ hash]]
|
||||
(-> db
|
||||
(update :transactions dissoc hash)
|
||||
|
@ -119,21 +128,22 @@
|
|||
(status/discard-transaction id)))))
|
||||
|
||||
(register-handler ::transaction-queued
|
||||
(after #(dispatch [:navigate-to-modal :confirm]))
|
||||
(after #(dispatch [:navigate-to-modal :pending-transactions]))
|
||||
(fn [db [_ {:keys [id message_id args]}]]
|
||||
(let [{:keys [from to value]} args]
|
||||
(let [{:keys [from to value data]} args]
|
||||
(if (valid-hex? to)
|
||||
(let [transaction {:id id
|
||||
:from from
|
||||
:to to
|
||||
:value (.toDecimal js/Web3.prototype value)
|
||||
:data data
|
||||
:message-id message_id}]
|
||||
(assoc-in db [:transactions-queue id] transaction))
|
||||
db))))
|
||||
|
||||
(register-handler :transaction-completed
|
||||
(u/side-effect!
|
||||
(fn [{:keys [transactions]} [_ {:keys [id response]}]]
|
||||
(fn [{:keys [transactions modal]} [_ {:keys [id response]}]]
|
||||
(let [{:keys [hash error] :as parsed-response} (t/json->clj response)
|
||||
{:keys [message-id]} (transactions id)]
|
||||
(log/debug :parsed-response parsed-response)
|
||||
|
@ -144,7 +154,10 @@
|
|||
:message-id message-id}])
|
||||
(dispatch [::check-completed-transaction!
|
||||
{:message-id message-id}]))
|
||||
(dispatch [::remove-transaction id])))))))
|
||||
(dispatch [::remove-transaction id]))
|
||||
(when (or (= modal :pending-transactions)
|
||||
(= modal :transaction-details))
|
||||
(dispatch [:navigate-to-modal :confirmation-success])))))))
|
||||
|
||||
(register-handler ::add-transactions-hash
|
||||
(fn [db [_ {:keys [id hash message-id]}]]
|
||||
|
@ -189,10 +202,15 @@
|
|||
(not= discard-code error_code)
|
||||
(do (when message_id
|
||||
(dispatch [::remove-pending-message message_id]))
|
||||
(dispatch [:clear-selected-transaction])
|
||||
(dispatch [::remove-transaction id]))
|
||||
|
||||
:else nil))))
|
||||
|
||||
(register-handler :clear-selected-transaction
|
||||
(fn [db _]
|
||||
(dissoc db :selected-transaction)))
|
||||
|
||||
(def attempts-limit 3)
|
||||
|
||||
(register-handler :set-wrong-password!
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
(ns status-im.transactions.screen
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
image
|
||||
icon
|
||||
scroll-view
|
||||
touchable-highlight
|
||||
touchable-opacity]]
|
||||
[status-im.components.styles :refer [icon-ok
|
||||
icon-close]]
|
||||
[status-im.components.carousel.carousel :refer [carousel]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-title-container]]
|
||||
[status-im.components.text-field.view :refer [text-field]]
|
||||
[status-im.transactions.views.transaction-page :refer [transaction-page]]
|
||||
[status-im.transactions.styles :as st]
|
||||
[status-im.i18n :refer [label label-pluralize]]
|
||||
[clojure.string :as s]))
|
||||
|
||||
(defview confirm []
|
||||
[transactions [:transactions]
|
||||
{:keys [password]} [:get :confirm-transactions]
|
||||
wrong-password? [:wrong-password?]]
|
||||
[view st/transactions-screen
|
||||
[status-bar {:type :transparent}]
|
||||
[toolbar
|
||||
{:style st/transactions-toolbar
|
||||
:nav-action {:image {:source {:uri :icon_close_white}
|
||||
:style icon-close}
|
||||
:handler #(dispatch [:deny-transactions])}
|
||||
:custom-content [view {:style toolbar-title-container}
|
||||
[text {:style st/toolbar-title-text}
|
||||
(label-pluralize (count transactions) :t/confirm-transactions)]]
|
||||
:actions [{:image {:source {:uri (if-not (s/blank? password)
|
||||
:icon_ok
|
||||
:icon_ok_disabled_inversed)}
|
||||
:style icon-ok}
|
||||
:handler (when-not (s/blank? password)
|
||||
#(dispatch [:accept-transactions password]))}]}]
|
||||
[view st/carousel-container
|
||||
[carousel {:pageStyle st/carousel-page-style
|
||||
:gap 8
|
||||
:sneak 16
|
||||
:count (count transactions)}
|
||||
(when transactions
|
||||
(for [transaction transactions]
|
||||
[transaction-page transaction]))]]
|
||||
[view st/form-container
|
||||
[text-field
|
||||
{:editable true
|
||||
:error (when wrong-password? (label :t/wrong-password))
|
||||
:error-color :#ffffff80 #_:#7099e6
|
||||
:label (label :t/password)
|
||||
:secure-text-entry true
|
||||
:label-color :#ffffff80
|
||||
:line-color :white
|
||||
:auto-capitalize :none
|
||||
:input-style st/password-style
|
||||
:on-change-text #(dispatch [:set-in [:confirm-transactions :password] %])}]]])
|
|
@ -0,0 +1,25 @@
|
|||
(ns status-im.transactions.screens.confirmation-success
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.components.react :as rn]
|
||||
[status-im.components.sticky-button :as sticky-button]
|
||||
[status-im.components.status-bar :as status-bar]
|
||||
[status-im.transactions.views.list-item :as transactions-list-item]
|
||||
[status-im.transactions.styles.screens :as st]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(defview confirmation-success []
|
||||
[quantity [:get :confirmed-transactions-count]]
|
||||
[rn/view {:style st/success-screen}
|
||||
[status-bar/status-bar {:type :transparent}]
|
||||
[rn/view {:style st/success-screen-content-container}
|
||||
[rn/view {:style st/success-icon-container}
|
||||
[rn/image {:source {:uri :icon_ok_white}
|
||||
:style st/success-icon}]]
|
||||
[rn/view
|
||||
[rn/text {:style st/success-text}
|
||||
(i18n/label-pluralize quantity :t/transactions-confirmed)]]]
|
||||
[sticky-button/sticky-button
|
||||
(i18n/label :t/got-it)
|
||||
#(do (rf/dispatch [:navigate-back])
|
||||
(rf/dispatch [:set :confirmed-transactions-count 0]))]])
|
|
@ -0,0 +1,69 @@
|
|||
(ns status-im.transactions.screens.pending-transactions
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.components.common.common :as common]
|
||||
[status-im.components.react :as rn]
|
||||
[status-im.components.sticky-button :as sticky-button]
|
||||
[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.transactions.views.list-item :as transactions-list-item]
|
||||
[status-im.transactions.views.password-form :as password-form]
|
||||
[status-im.transactions.styles.screens :as st]
|
||||
[status-im.utils.listview :as lw]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(defn toolbar-view [transactions]
|
||||
[toolbar/toolbar
|
||||
{:background-color st/transactions-toolbar-background
|
||||
:nav-action (act/close-white #(do (rf/dispatch [:deny-transactions])
|
||||
(rf/dispatch [:navigate-back])))
|
||||
:border-style st/toolbar-border
|
||||
:custom-content [rn/view {:style st/toolbar-title-container}
|
||||
[rn/text {:style st/toolbar-title-text
|
||||
:font :toolbar-title}
|
||||
(i18n/label :t/pending-transactions)]
|
||||
[rn/text {:style st/toolbar-title-count
|
||||
:font :toolbar-title}
|
||||
(count transactions)]]}])
|
||||
|
||||
(defn render-separator-fn [transactions-count]
|
||||
(fn [_ row-id _]
|
||||
(when (< row-id (dec transactions-count))
|
||||
(rn/list-item
|
||||
^{:key row-id}
|
||||
[common/separator {} st/transactions-list-separator]))))
|
||||
|
||||
(defn render-row-fn [row _ _]
|
||||
(rn/list-item
|
||||
[rn/touchable-highlight {:on-press #(rf/dispatch [:navigate-to-modal :transaction-details row])}
|
||||
[rn/view
|
||||
[transactions-list-item/view row]]]))
|
||||
|
||||
(defview pending-transactions []
|
||||
[transactions [:transactions]
|
||||
{:keys [password]} [:get :confirm-transactions]
|
||||
confirmed? [:get-in [:transactions-list-ui-props :confirmed?]]]
|
||||
|
||||
{:component-did-update #(when-not (seq transactions) (rf/dispatch [:navigate-back]))
|
||||
:component-will-unmount #(rf/dispatch [:set-in [:transactions-list-ui-props :confirmed?] false])}
|
||||
|
||||
[(if platform/ios? rn/keyboard-avoiding-view rn/view) (merge {:behavior :padding} st/transactions-screen)
|
||||
[status-bar/status-bar {:type (if platform/ios? :transparent :main)}]
|
||||
[toolbar-view transactions]
|
||||
[rn/view {:style st/transactions-screen-content-container}
|
||||
[rn/list-view {:style st/transactions-list
|
||||
:dataSource (lw/to-datasource transactions)
|
||||
:renderSeparator (render-separator-fn (count transactions))
|
||||
:renderRow render-row-fn}]
|
||||
(when confirmed?
|
||||
[password-form/view (count transactions)])]
|
||||
(let [confirm-text (if confirmed?
|
||||
(i18n/label :t/confirm)
|
||||
(i18n/label-pluralize (count transactions) :t/confirm-transactions))
|
||||
confirm-fn (if confirmed?
|
||||
#(do (rf/dispatch [:accept-transactions password])
|
||||
(rf/dispatch [:set :confirmed-transactions-count (count transactions)]))
|
||||
#(rf/dispatch [:set-in [:transactions-list-ui-props :confirmed?] true]))]
|
||||
[sticky-button/sticky-button confirm-text confirm-fn])])
|
|
@ -0,0 +1,70 @@
|
|||
(ns status-im.transactions.screens.transaction-details
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.components.react :as rn]
|
||||
[status-im.components.common.common :as common]
|
||||
[status-im.components.sticky-button :as sticky-button]
|
||||
[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.i18n :as i18n]
|
||||
[status-im.transactions.styles.screens :as st]
|
||||
[status-im.transactions.views.list-item :as transactions-list-item]
|
||||
[status-im.transactions.views.password-form :as password-form]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(defn toolbar-view []
|
||||
[toolbar/toolbar
|
||||
{:background-color st/transactions-toolbar-background
|
||||
:nav-action (act/back-white #(rf/dispatch [:navigate-to-modal :pending-transactions]))
|
||||
:border-style st/toolbar-border
|
||||
:custom-content [rn/view {:style st/toolbar-title-container}
|
||||
[rn/text {:style st/toolbar-title-text
|
||||
:font :toolbar-title}
|
||||
(i18n/label :t/transaction)]]}])
|
||||
|
||||
(defn detail-item [title content name?]
|
||||
[rn/view {:style st/details-item}
|
||||
[rn/text {:style st/details-item-title} title]
|
||||
[rn/text {:style (st/details-item-content name?)
|
||||
:number-of-lines 1}
|
||||
content]])
|
||||
|
||||
(defn detail-data [content]
|
||||
[rn/view {:style st/details-data}
|
||||
[rn/text {:style st/details-data-title} (i18n/label :t/data)]
|
||||
[rn/text {:style st/details-data-content} content]])
|
||||
|
||||
(defview details [{:keys [to data] :as transaction}]
|
||||
[current-account [:get-current-account]
|
||||
recipient [:contact-by-address to]]
|
||||
(let [recipient-name (or (:name recipient) to)]
|
||||
[rn/view
|
||||
[detail-item (i18n/label :t/to) recipient-name true]
|
||||
[detail-item (i18n/label :t/from) (:name current-account) true]
|
||||
[detail-data data]]))
|
||||
|
||||
(defview transaction-details []
|
||||
[{:keys [id] :as transaction} [:get :selected-transaction]
|
||||
{:keys [password]} [:get :confirm-transactions]
|
||||
confirmed? [:get-in [:transaction-details-ui-props :confirmed?]]]
|
||||
|
||||
{:component-did-update #(when-not transaction (rf/dispatch [:navigate-to-modal :pending-transactions]))
|
||||
:component-will-unmount #(rf/dispatch [:set-in [:transaction-details-ui-props :confirmed?] false])}
|
||||
|
||||
[(if platform/ios? rn/keyboard-avoiding-view rn/view) (merge {:behavior :padding} st/transactions-screen)
|
||||
[status-bar/status-bar {:type (if platform/ios? :transparent :main)}]
|
||||
[toolbar-view]
|
||||
[rn/scroll-view st/details-screen-content-container
|
||||
[transactions-list-item/view transaction #(rf/dispatch [:navigate-to-modal :pending-transactions])]
|
||||
(when platform/ios? [common/separator {} st/details-separator])
|
||||
[details transaction]]
|
||||
(when confirmed? [password-form/view 1])
|
||||
(let [confirm-text (if confirmed?
|
||||
(i18n/label :t/confirm)
|
||||
(i18n/label-pluralize 1 :t/confirm-transactions))
|
||||
confirm-fn (if confirmed?
|
||||
#(do (rf/dispatch [:accept-transaction password id])
|
||||
(rf/dispatch [:set :confirmed-transactions-count 1]))
|
||||
#(rf/dispatch [:set-in [:transaction-details-ui-props :confirmed?] true]))]
|
||||
[sticky-button/sticky-button confirm-text confirm-fn])])
|
|
@ -1,105 +0,0 @@
|
|||
(ns status-im.transactions.styles
|
||||
(:require [status-im.components.styles :refer [color-gray
|
||||
color-black]]))
|
||||
|
||||
(def transactions-screen
|
||||
{:flex 1
|
||||
:backgroundColor "#828b92"})
|
||||
|
||||
(def transactions-toolbar
|
||||
{:backgroundColor "#828b92"
|
||||
:elevation 0})
|
||||
|
||||
(def toolbar-title-text
|
||||
{:color :white
|
||||
:fontSize 16})
|
||||
|
||||
(def carousel-page-style
|
||||
{})
|
||||
|
||||
(def form-container
|
||||
{:flex 1
|
||||
:paddingLeft 16})
|
||||
|
||||
(def password-style
|
||||
{:color :white
|
||||
:font-size 12})
|
||||
|
||||
;transaction-page
|
||||
|
||||
(def transaction-page
|
||||
{:flex 1
|
||||
:backgroundColor "#f3f4f4"})
|
||||
|
||||
(def title-bar
|
||||
{:backgroundColor :white
|
||||
:height 39
|
||||
:justifyContent :center})
|
||||
|
||||
(def title-bar-text
|
||||
{:color "#838c93"
|
||||
:font-size 13
|
||||
:margin-left 12
|
||||
:margin-right 30})
|
||||
|
||||
(def icon-close-container
|
||||
{:position :absolute
|
||||
:right 12
|
||||
:top 13})
|
||||
|
||||
(def icon-close
|
||||
{:width 12
|
||||
:height 12})
|
||||
|
||||
(def transaction-info-container
|
||||
{:flex 1
|
||||
:paddingTop 6})
|
||||
|
||||
(def scroll-view-container
|
||||
{:flex 1})
|
||||
|
||||
(def scroll-view
|
||||
{:flex 1
|
||||
:height 175})
|
||||
|
||||
(def scroll-view-content
|
||||
{:paddingVertical 6})
|
||||
|
||||
(def transaction-info-row
|
||||
{:flex 1
|
||||
:flexDirection :row})
|
||||
|
||||
(def transaction-info-column-title
|
||||
{:flex 0.4
|
||||
:flexDirection :column
|
||||
:paddingHorizontal 6})
|
||||
|
||||
(def transaction-info-column-value
|
||||
{:flex 0.6
|
||||
:flexDirection :column
|
||||
:paddingHorizontal 6})
|
||||
|
||||
(def transaction-info-item
|
||||
{:flex 1
|
||||
:padding 6})
|
||||
|
||||
(def transaction-info-title
|
||||
{:textAlign :right
|
||||
:color color-gray
|
||||
:fontSize 14
|
||||
:lineHeight 20})
|
||||
|
||||
(def transaction-info-value
|
||||
{:color color-black
|
||||
:fontSize 14
|
||||
:lineHeight 20
|
||||
})
|
||||
|
||||
(def scroll-view-item
|
||||
{:flex 1
|
||||
:height 20
|
||||
:padding 6 })
|
||||
|
||||
(def carousel-container
|
||||
{:min-height 215
|
||||
:flex 1})
|
|
@ -0,0 +1,52 @@
|
|||
(ns status-im.transactions.styles.list-item
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||
(:require [status-im.components.styles :as st]))
|
||||
|
||||
(def item
|
||||
{:padding-vertical 20
|
||||
:padding-horizontal 16
|
||||
:flex 1
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def item-photo
|
||||
{:width 86
|
||||
:height 48
|
||||
:border-radius 100
|
||||
:background-color st/color-dark-blue-3
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def item-info
|
||||
{:margin-left 16
|
||||
:flex 1})
|
||||
|
||||
(defstyle item-info-recipient
|
||||
{:color st/color-light-blue
|
||||
:font-size 15
|
||||
:flex-shrink 1
|
||||
:android {:margin-bottom 5}
|
||||
:ios {:margin-bottom 4}})
|
||||
|
||||
(defstyle item-info-amount
|
||||
{:color st/color-white
|
||||
:android {:font-size 19}
|
||||
:ios {:font-size 20}})
|
||||
|
||||
(def item-deny-btn
|
||||
{:margin-left 16})
|
||||
|
||||
(def item-deny-btn-icon
|
||||
{:width 24
|
||||
:height 24})
|
||||
|
||||
(def photo-size 48)
|
||||
|
||||
(def photo-placeholder
|
||||
{:width 48
|
||||
:height 48})
|
||||
|
||||
(def item-photo-icon
|
||||
{:margin-left 4
|
||||
:width 24
|
||||
:height 24})
|
|
@ -0,0 +1,30 @@
|
|||
(ns status-im.transactions.styles.password-form
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
||||
(:require [status-im.components.styles :as st]))
|
||||
|
||||
(defnstyle password-container [error?]
|
||||
{:margin-bottom (if error? 42 24)
|
||||
:padding-left 16
|
||||
:ios {:border-top-width 1
|
||||
:border-top-color st/color-white-transparent-2}})
|
||||
|
||||
(def password-title
|
||||
{:color st/color-white
|
||||
:font-size 15
|
||||
:margin-top 16
|
||||
:margin-bottom 12})
|
||||
|
||||
(def password-input-wrapper
|
||||
{:position :relative
|
||||
:height 52
|
||||
:padding-top 0
|
||||
:padding-bottom 0
|
||||
:margin-bottom 0})
|
||||
|
||||
(defstyle password-input
|
||||
{:color :white
|
||||
:height 52
|
||||
:padding-left 0
|
||||
:padding-top 24
|
||||
:android {:font-size 16}
|
||||
:ios {:font-size 17}})
|
|
@ -0,0 +1,129 @@
|
|||
(ns status-im.transactions.styles.screens
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||
(:require [status-im.components.styles :as st]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
;; common
|
||||
|
||||
(def transactions-toolbar-background (if platform/ios?
|
||||
st/color-dark-blue-2
|
||||
st/color-dark-blue-1))
|
||||
|
||||
(defstyle toolbar-title-container
|
||||
{:flex 1
|
||||
:flex-direction :row
|
||||
:align-self :stretch
|
||||
:padding-left 30
|
||||
:ios {:align-items :center
|
||||
:justify-content :center
|
||||
:padding-bottom 16}})
|
||||
|
||||
(def toolbar-title-text
|
||||
{:color st/color-white
|
||||
:font-size 17})
|
||||
|
||||
(defstyle toolbar-title-count
|
||||
{:color st/color-white
|
||||
:font-size 17
|
||||
:margin-left 8
|
||||
:android {:opacity 0.2}
|
||||
:ios {:opacity 0.6}})
|
||||
|
||||
(defstyle toolbar-border
|
||||
{:ios {:background-color st/color-white
|
||||
:opacity 0.1}})
|
||||
|
||||
;; pending-transactions
|
||||
|
||||
(def transactions-screen
|
||||
{:flex 1
|
||||
:background-color st/color-dark-blue-2})
|
||||
|
||||
(def transactions-screen-content-container
|
||||
{:flex 1
|
||||
:justify-content :space-between})
|
||||
|
||||
(defstyle transactions-list
|
||||
{:flex 1
|
||||
:android {:padding-vertical 8}})
|
||||
|
||||
(def transactions-list-separator
|
||||
{:margin-left 16
|
||||
:opacity 0.1})
|
||||
|
||||
;; transaction-details
|
||||
|
||||
(defstyle details-screen-content-container
|
||||
{:flex 1
|
||||
:android {:padding-top 8}})
|
||||
|
||||
(def details-separator
|
||||
{:margin-bottom 10
|
||||
:margin-left 16
|
||||
:opacity 0.1})
|
||||
|
||||
(def details-item
|
||||
{:margin-top 10
|
||||
:padding-left 16
|
||||
:padding-right 16
|
||||
:flex-direction :row})
|
||||
|
||||
(defstyle details-item-title
|
||||
{:width 80
|
||||
:font-size 15
|
||||
:color st/color-white
|
||||
:android {:opacity 0.2
|
||||
:margin-right 24}
|
||||
:ios {:opacity 0.5
|
||||
:margin-right 8
|
||||
:text-align :right}})
|
||||
|
||||
(defn details-item-content [name?]
|
||||
{:font-size 15
|
||||
:flex-shrink 1
|
||||
:color (if name? st/color-light-blue st/color-white)})
|
||||
|
||||
(defstyle details-data
|
||||
{:margin-top 16
|
||||
:padding 16
|
||||
:background-color st/color-dark-blue-3
|
||||
:ios {:margin-horizontal 16}})
|
||||
|
||||
(defstyle details-data-title
|
||||
{:font-size 15
|
||||
:color st/color-white
|
||||
:android {:opacity 0.2}
|
||||
:ios {:opacity 0.5}})
|
||||
|
||||
(def details-data-content
|
||||
{:font-size 15
|
||||
:color st/color-white
|
||||
:margin-top 8})
|
||||
|
||||
;; confirmation-success
|
||||
|
||||
(def success-screen
|
||||
{:flex 1
|
||||
:background-color st/color-dark-blue-2})
|
||||
|
||||
(def success-screen-content-container
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def success-icon-container
|
||||
{:background-color st/color-light-blue
|
||||
:border-radius 100
|
||||
:height 133
|
||||
:width 133
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(def success-icon
|
||||
{:height 40
|
||||
:width 54})
|
||||
|
||||
(def success-text
|
||||
{:font-size 17
|
||||
:color st/color-light-blue3
|
||||
:margin-top 26})
|
|
@ -0,0 +1,39 @@
|
|||
(ns status-im.transactions.views.list-item
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.components.chat-icon.screen :as chat-icon]
|
||||
[status-im.components.react :as rn]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.transactions.styles.list-item :as st]))
|
||||
|
||||
(defview item-image [contact]
|
||||
[rn/view {:style st/item-photo}
|
||||
(if-not (empty? contact)
|
||||
[chat-icon/chat-icon (:photo-path contact) {:size st/photo-size}]
|
||||
[rn/view {:style st/photo-placeholder}])
|
||||
[rn/image {:source {:uri :icon_arrow_left_white}
|
||||
:style st/item-photo-icon}]])
|
||||
|
||||
(defn item-info [recipient-name value]
|
||||
[rn/view {:style st/item-info}
|
||||
[rn/text {:style st/item-info-recipient
|
||||
:number-of-lines 1}
|
||||
recipient-name]
|
||||
[rn/text {:style st/item-info-amount} value]])
|
||||
|
||||
(defn deny-btn [transaction-id on-deny]
|
||||
[rn/touchable-highlight {:on-press #(do (rf/dispatch [:deny-transaction transaction-id])
|
||||
(when on-deny (on-deny)))}
|
||||
[rn/view {:style st/item-deny-btn}
|
||||
[rn/image {:source {:uri :icon_close_white}
|
||||
:style st/item-deny-btn-icon}]]])
|
||||
|
||||
(defview view [{:keys [to value id] :as transaction} on-deny]
|
||||
[recipient [:contact-by-address to]]
|
||||
(let [eth-value (.fromWei js/Web3.prototype value "ether")
|
||||
value (str (i18n/label-number eth-value) " ETH")
|
||||
recipient-name (or (:name recipient) to)]
|
||||
[rn/view {:style st/item}
|
||||
[item-image recipient]
|
||||
[item-info recipient-name value]
|
||||
[deny-btn id on-deny]]))
|
|
@ -0,0 +1,29 @@
|
|||
(ns status-im.transactions.views.password-form
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as rf]
|
||||
[status-im.components.react :as rn]
|
||||
[status-im.components.styles :as common-st]
|
||||
[status-im.components.text-field.view :as text-field]
|
||||
[status-im.transactions.styles.password-form :as st]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(defview view [transaction-quantity]
|
||||
[wrong-password? [:wrong-password?]]
|
||||
(let [error? wrong-password?]
|
||||
[rn/view (st/password-container error?)
|
||||
[rn/text {:style st/password-title}
|
||||
(i18n/label-pluralize transaction-quantity :t/enter-password-transactions)]
|
||||
[text-field/text-field
|
||||
{:editable true
|
||||
:secure-text-entry true
|
||||
:label-hidden? true
|
||||
:error (when error? (i18n/label :t/wrong-password))
|
||||
:error-color common-st/color-light-red2
|
||||
:placeholder (i18n/label :t/password)
|
||||
:placeholder-text-color common-st/color-white-transparent
|
||||
:line-color common-st/color-light-blue
|
||||
:focus-line-height 2
|
||||
:wrapper-style st/password-input-wrapper
|
||||
:input-style st/password-input
|
||||
:auto-focus true
|
||||
:on-change-text #(rf/dispatch [:set-in [:confirm-transactions :password] %])}]]))
|
|
@ -1,50 +0,0 @@
|
|||
(ns status-im.transactions.views.transaction-page
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
image
|
||||
icon
|
||||
scroll-view
|
||||
touchable-highlight
|
||||
touchable-opacity]]
|
||||
[status-im.components.styles :refer [icon-close]]
|
||||
[status-im.transactions.styles :as st]
|
||||
[status-im.i18n :refer [label label-pluralize label-number]]))
|
||||
|
||||
(defn title-bar [title id]
|
||||
[view st/title-bar
|
||||
[text {:style st/title-bar-text
|
||||
:font :medium
|
||||
:number-of-lines 1}
|
||||
title]
|
||||
[touchable-highlight {:style st/icon-close-container
|
||||
:on-press #(dispatch [:deny-transaction id])}
|
||||
[view [image {:source {:uri :icon_close_gray}
|
||||
:style st/icon-close}]]]])
|
||||
|
||||
(defn transaction-info [index [name value]]
|
||||
[view {:style st/transaction-info-item
|
||||
:key index}
|
||||
[view {:style st/transaction-info-row}
|
||||
[view st/transaction-info-column-title
|
||||
[text {:style st/transaction-info-title} name]]
|
||||
[view st/transaction-info-column-value
|
||||
[text {:style st/transaction-info-value} value]]]])
|
||||
|
||||
(defview transaction-page [{:keys [id from to value] :as transaction}]
|
||||
[{:keys [name] :as contact} [:contact-by-address to]]
|
||||
(let [eth-value (.fromWei js/Web3.prototype value "ether")
|
||||
title (str (label-number eth-value) " ETH to " (or name to))
|
||||
transactions-info [[(label :t/status) (label :t/pending-confirmation)]
|
||||
[(label :t/recipient) (or name to)]
|
||||
[(label :t/value) (str (label-number eth-value) " ETH")]]]
|
||||
[view {:style st/transaction-page
|
||||
:key id}
|
||||
[title-bar title id]
|
||||
[view st/scroll-view-container
|
||||
[scroll-view {:style st/scroll-view
|
||||
:contentContainerStyle st/scroll-view-content
|
||||
:showsVerticalScrollIndicator true
|
||||
:scrollEnabled true}
|
||||
(map-indexed transaction-info transactions-info)]]]))
|
|
@ -269,15 +269,27 @@
|
|||
:not-enough-eth (str "Not enough ETH on balance "
|
||||
"({{balance}} ETH)")
|
||||
;transactions
|
||||
:confirm "Confirm"
|
||||
:confirm-transactions {:one "Confirm transaction"
|
||||
:other "Confirm {{count}} transactions"
|
||||
:zero "No transactions"}
|
||||
:transactions-confirmed {:one "Transaction confirmed"
|
||||
:other "{{count}} transactions confirmed"
|
||||
:zero "No transactions confirmed"}
|
||||
:transaction "Transaction"
|
||||
:pending-transactions "Pending transactions"
|
||||
:enter-password-transactions {:one "Enter your password to confirm the transaction"
|
||||
:other "Enter your password to confirm the transactions"}
|
||||
:status "Status"
|
||||
:pending-confirmation "Pending confirmation"
|
||||
:recipient "Recipient"
|
||||
:one-more-item "One more item"
|
||||
:fee "Fee"
|
||||
:value "Value"
|
||||
:to "To"
|
||||
:from "From"
|
||||
:data "Data"
|
||||
:got-it "Got it"
|
||||
|
||||
;:webview
|
||||
:web-view-error "oops, error"})
|
||||
|
|