[Fix #3394] Add accessibility labels for Wallet screens

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
Foo Pang 2018-03-04 10:56:39 +08:00 committed by Julien Eluard
parent 25ac067375
commit 2653cebd7d
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
16 changed files with 276 additions and 166 deletions

View File

@ -3,12 +3,14 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]))
(defn button [{:keys [on-press style disabled? fit-to-text? text-style] :or {fit-to-text? true}} label icon] (defn button [{:keys [on-press style disabled? fit-to-text? text-style accessibility-label] :or {fit-to-text? true}} label icon]
[react/touchable-highlight (merge {:underlay-color styles/border-color-high} [react/touchable-highlight (merge {:underlay-color styles/border-color-high}
(when-not fit-to-text? (when-not fit-to-text?
{:style styles/button-container}) {:style styles/button-container})
(when (and on-press (not disabled?)) (when (and on-press (not disabled?))
{:on-press on-press})) {:on-press on-press})
(when accessibility-label
{:accessibility-label accessibility-label}))
[react/view {:style (merge styles/button [react/view {:style (merge styles/button
style)} style)}
[react/text {:style (merge styles/button-text [react/text {:style (merge styles/button-text

View File

@ -3,12 +3,14 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]))
(defn checkbox [{:keys [on-value-change checked?]}] (defn checkbox [{:keys [on-value-change checked? accessibility-label] :or {accessibility-label :checkbox}}]
(if platform/android? (if platform/android?
[react/view {:style styles/wrapper} [react/view {:style styles/wrapper}
[react/check-box {:on-value-change on-value-change [react/check-box {:on-value-change on-value-change
:value checked?}]] :value checked?
[react/touchable-highlight (merge {:style styles/wrapper} :accessibility-label accessibility-label}]]
[react/touchable-highlight (merge {:style styles/wrapper
:accessibility-label accessibility-label}
(when on-value-change {:on-press #(on-value-change (not checked?))})) (when on-value-change {:on-press #(on-value-change (not checked?))}))
[react/view (styles/icon-check-container checked?) [react/view (styles/icon-check-container checked?)
(when checked? (when checked?

View File

@ -60,13 +60,17 @@
:style (merge styles/item-image image-style)}]]) :style (merge styles/item-image image-style)}]])
(defn item-primary (defn item-primary
[primary] ([s] (item-primary nil s))
[react/text {:style styles/primary-text} primary]) ([{:keys [style] :as props} s]
[react/text (merge {:style styles/primary-text}
(dissoc props :style))
s]))
(defn item-primary-only (defn item-primary-only
([s] (item-primary-only nil s)) ([s] (item-primary-only nil s))
([{:keys [style]} s] ([{:keys [style] :as props} s]
[react/text {:style (merge styles/primary-text-only style)} [react/text (merge {:style (merge styles/primary-text-only style)}
(dissoc props :style))
s])) s]))
(defn item-secondary (defn item-secondary
@ -176,10 +180,10 @@
:renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)} :renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)}
(when platform/ios? {:SectionSeparatorComponent (fn [] (reagent/as-element section-separator))}))]) (when platform/ios? {:SectionSeparatorComponent (fn [] (reagent/as-element section-separator))}))])
(defn- render-action [{:keys [label icon action disabled?]} (defn- render-action [{:keys [label accessibility-label icon action disabled?]}
{:keys [action-style action-label-style icon-opts]}] {:keys [action-style action-label-style icon-opts]}]
[react/touchable-highlight {:on-press action} [react/touchable-highlight {:on-press action}
[react/view [react/view {:accessibility-label accessibility-label}
[item [item
[item-icon {:icon icon [item-icon {:icon icon
:style (merge styles/action :style (merge styles/action

View File

@ -12,7 +12,8 @@
(defn- footer [style value] (defn- footer [style value]
[react/view styles/footer [react/view styles/footer
[react/view styles/wallet-info [react/view styles/wallet-info
[react/text {:style (merge styles/hash-value-text style)} [react/text {:style (merge styles/hash-value-text style)
:accessibility-label :address-text}
value]]]) value]]])
(defn qr-code-viewer [{:keys [style hint-style footer-style]} value hint legend] (defn qr-code-viewer [{:keys [style hint-style footer-style]} value hint legend]
@ -23,7 +24,8 @@
hint] hint]
(when width (when width
(let [size (int (* 0.7 (min width height)))] (let [size (int (* 0.7 (min width height)))]
[react/view {:style (styles/qr-code-container size)} [react/view {:style (styles/qr-code-container size)
:accessibility-label :qr-code-image}
[qr-code {:value value [qr-code {:value value
:size (- size (* 2 styles/qr-code-padding))}]])) :size (- size (* 2 styles/qr-code-padding))}]]))
[footer footer-style legend]])) [footer footer-style legend]]))

View File

@ -14,7 +14,7 @@
(defn back [handler] (defn back [handler]
{:icon :icons/back {:icon :icons/back
:handler handler :handler handler
:accessibility-label :toolbar-back-button}) :accessibility-label :back-button})
(def default-handler #(re-frame/dispatch [:navigate-back])) (def default-handler #(re-frame/dispatch [:navigate-back]))
@ -24,7 +24,8 @@
(defn back-white [handler] (defn back-white [handler]
{:icon :icons/back {:icon :icons/back
:icon-opts {:color :white} :icon-opts {:color :white}
:handler handler}) :handler handler
:accessibility-label :back-button})
(defn close [handler] (defn close [handler]
{:icon :icons/close {:icon :icons/close

View File

@ -72,11 +72,13 @@
;; Actions ;; Actions
(defn text-action [{:keys [style handler disabled?]} title] (defn text-action [{:keys [style handler disabled? accessibility-label]} title]
[react/text {:style (merge styles/item styles/item-text-action style [react/text (cond-> {:style (merge styles/item styles/item-text style
(when disabled? styles/toolbar-text-action-disabled)) (when disabled? styles/toolbar-text-action-disabled))
:on-press (when-not disabled? handler) :on-press (when-not disabled? handler)
:uppercase? components.styles/uppercase?} :uppercase? components.styles/uppercase?}
accessibility-label
(assoc :accessibility-label accessibility-label))
title]) title])
(def blank-action [react/view {:style (merge styles/item styles/toolbar-action)}]) (def blank-action [react/view {:style (merge styles/item styles/toolbar-action)}])

View File

@ -50,7 +50,8 @@
[react/view {:style styles/qr-code} [react/view {:style styles/qr-code}
[status-bar/status-bar {:type :transparent}] [status-bar/status-bar {:type :transparent}]
[toolbar-view camera-flashlight] [toolbar-view camera-flashlight]
[react/text {:style (styles/qr-code-text dimensions)} [react/text {:style (styles/qr-code-text dimensions)
:accessibility-label :scan-qr-code-with-wallet-address-text}
(i18n/label :t/scan-qr-code)] (i18n/label :t/scan-qr-code)]
[react/view {:style styles/qr-container [react/view {:style styles/qr-container
:pointer-events :none} :pointer-events :none}
@ -63,5 +64,7 @@
:onBarCodeRead #(re-frame/dispatch [:wallet/fill-request-from-url (camera/get-qr-code-data %) nil])}]] :onBarCodeRead #(re-frame/dispatch [:wallet/fill-request-from-url (camera/get-qr-code-data %) nil])}]]
[viewfinder dimensions (size dimensions)]] [viewfinder dimensions (size dimensions)]]
[bottom-buttons/bottom-button [bottom-buttons/bottom-button
[button/button {:disabled? false :on-press #(re-frame/dispatch [:navigate-back])} [button/button {:disabled? false
:on-press #(re-frame/dispatch [:navigate-back])
:accessibility-label :cancel-button}
(i18n/label :t/cancel)]]])) (i18n/label :t/cancel)]]]))

View File

@ -56,7 +56,7 @@
[react/view {:flex 1} [react/view {:flex 1}
content]]) content]])
(defn cartouche [{:keys [disabled? on-press icon] :or {icon :icons/forward} :as m} header content] (defn cartouche [{:keys [disabled? on-press icon icon-opts] :or {icon :icons/forward} :as m} header content]
[react/view {:style styles/cartouche-container} [react/view {:style styles/cartouche-container}
[react/text {:style styles/cartouche-header} [react/text {:style styles/cartouche-header}
header] header]
@ -69,7 +69,7 @@
[react/view styles/cartouche-icon-wrapper [react/view styles/cartouche-icon-wrapper
[react/view {:flex 1} ;; Let content shrink if needed [react/view {:flex 1} ;; Let content shrink if needed
content] content]
[vector-icons/icon icon {:color :white}]] [vector-icons/icon icon (merge {:color :white} icon-opts)]]
content)]]])]) content)]]])])
(defn- cartouche-primary-text [s] (defn- cartouche-primary-text [s]

View File

@ -80,7 +80,8 @@
(let [{:keys [name icon decimals]} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)] (let [{:keys [name icon decimals]} (tokens/asset-for (ethereum/network->chain-keyword network) symbol)]
[components/cartouche {:disabled? disabled? :on-press #(re-frame/dispatch [:navigate-to (type->view type)])} [components/cartouche {:disabled? disabled? :on-press #(re-frame/dispatch [:navigate-to (type->view type)])}
(i18n/label :t/wallet-asset) (i18n/label :t/wallet-asset)
[react/view styles/asset-content-container [react/view {:style styles/asset-content-container
:accessibility-label :choose-asset-button}
[list/item-image (assoc icon :style styles/asset-icon :image-style {:width 32 :height 32})] [list/item-image (assoc icon :style styles/asset-icon :image-style {:width 32 :height 32})]
[react/view styles/asset-text-content [react/view styles/asset-text-content
[react/view styles/asset-label-content [react/view styles/asset-label-content
@ -92,20 +93,23 @@
(str (wallet.utils/format-amount (symbol balance) decimals))]]]]))) (str (wallet.utils/format-amount (symbol balance) decimals))]]]])))
(defn- recipient-address [address] (defn- recipient-address [address]
[react/text {:style (merge styles/recipient-address (when-not address styles/recipient-no-address))} [react/text {:style (merge styles/recipient-address (when-not address styles/recipient-no-address))
:accessibility-label :recipient-address-text}
(or (ethereum/normalized-address address) (i18n/label :t/specify-recipient))]) (or (ethereum/normalized-address address) (i18n/label :t/specify-recipient))])
(views/defview recipient-contact [address name] (views/defview recipient-contact [address name request?]
(views/letsubs [contact [:contact/by-address address]] (views/letsubs [contact [:contact/by-address address]]
(let [address? (and (not (nil? address)) (not= address ""))] (let [address? (and (not (nil? address)) (not= address ""))]
[react/view styles/recipient-container [react/view styles/recipient-container
[react/view styles/recipient-icon [react/view styles/recipient-icon
[chat-icon/chat-icon (:photo-path contact) {:size list.styles/image-size}]] [chat-icon/chat-icon (:photo-path contact) {:size list.styles/image-size}]]
[react/view styles/recipient-name [react/view {:style styles/recipient-name}
[react/text {:style (styles/participant true) [react/text {:style (styles/participant true)
:accessibility-label (if request? :contact-name-text :recipient-name-text)
:number-of-lines 1} :number-of-lines 1}
name] name]
[react/text {:style (styles/participant (and (not name) address?))} [react/text {:style (styles/participant (and (not name) address?))
:accessibility-label (if request? :contact-address-text :recipient-address-text)}
(ethereum/normalized-address address)]]]))) (ethereum/normalized-address address)]]])))
(defn render-contact [contact] (defn render-contact [contact]
@ -113,8 +117,10 @@
[list/item [list/item
[chat-icon/chat-icon (:photo-path contact) {:size list.styles/image-size}] [chat-icon/chat-icon (:photo-path contact) {:size list.styles/image-size}]
[list/item-content [list/item-content
[list/item-primary (:name contact)] [list/item-primary {:accessibility-label :contact-name-text}
[react/text {:style list.styles/secondary-text} (:name contact)]
[react/text {:style list.styles/secondary-text
:accessibility-label :contact-address-text}
(ethereum/normalized-address (:address contact))]]]]) (ethereum/normalized-address (:address contact))]]]])
(views/defview recent-recipients [] (views/defview recent-recipients []
@ -138,7 +144,8 @@
[components/text-input {:multiline true [components/text-input {:multiline true
:style styles/contact-code-text-input :style styles/contact-code-text-input
:placeholder (i18n/label :t/recipient-code) :placeholder (i18n/label :t/recipient-code)
:on-change-text #(reset! content %)}]] :on-change-text #(reset! content %)
:accessibility-label :recipient-address-input}]]
[bottom-buttons/bottom-button [bottom-buttons/bottom-button
[button/button {:disabled? (string/blank? @content) [button/button {:disabled? (string/blank? @content)
:on-press #(re-frame/dispatch [:wallet/fill-request-from-url @content])} :on-press #(re-frame/dispatch [:wallet/fill-request-from-url @content])}
@ -162,22 +169,28 @@
{:label (i18n/label :t/recipient-code) {:label (i18n/label :t/recipient-code)
:action #(re-frame/dispatch [:navigate-to :contact-code])}]))})) :action #(re-frame/dispatch [:navigate-to :contact-code])}]))}))
(defn recipient-selector [{:keys [name address disabled? contact-only?]}] (defn recipient-selector [{:keys [name address disabled? contact-only? request?]}]
[components/cartouche {:on-press #(on-choose-recipient contact-only?) :disabled? disabled? :icon :icons/dots-horizontal} [components/cartouche {:on-press #(on-choose-recipient contact-only?)
:disabled? disabled?
:icon :icons/dots-horizontal
:icon-opts {:accessibility-label :choose-contact-button}}
(i18n/label :t/wallet-choose-recipient) (i18n/label :t/wallet-choose-recipient)
[react/view {:accessibility-label :choose-recipient-button}
(if name (if name
[recipient-contact address name] [recipient-contact address name request?]
[recipient-address address])]) [recipient-address address])]])
(defn- amount-input [{:keys [input-options disabled?]}] (defn- amount-input [{:keys [input-options disabled?]}]
[react/view components.styles/flex [react/view {:style components.styles/flex
:accessibility-label :specify-amount-button}
[components/text-input [components/text-input
(merge (merge
(if disabled? (if disabled?
{:editable false} {:editable false}
{:keyboard-type :numeric {:keyboard-type :numeric
:placeholder (i18n/label :t/amount-placeholder) :placeholder (i18n/label :t/amount-placeholder)
:style components.styles/flex}) :style components.styles/flex
:accessibility-label :amount-input})
input-options)]]) input-options)]])
(defn amount-selector [{:keys [error disabled?] :as m}] (defn amount-selector [{:keys [error disabled?] :as m}]

View File

@ -37,7 +37,8 @@
[react/view styles/request-details-wrapper [react/view styles/request-details-wrapper
[components/recipient-selector {:contact-only? true [components/recipient-selector {:contact-only? true
:address to :address to
:name to-name}] :name to-name
:request? true}]
[components/asset-selector {:disabled? true [components/asset-selector {:disabled? true
:symbol :ETH}] :symbol :ETH}]
[components/amount-selector {:error amount-error [components/amount-selector {:error amount-error
@ -49,7 +50,8 @@
nil ;; Force a phantom button to ensure consistency with other transaction screens which define 2 buttons nil ;; Force a phantom button to ensure consistency with other transaction screens which define 2 buttons
[button/button {:disabled? (not (and to amount)) [button/button {:disabled? (not (and to amount))
:on-press #(re-frame/dispatch [:wallet-send-request whisper-identity amount]) :on-press #(re-frame/dispatch [:wallet-send-request whisper-identity amount])
:text-style {:padding-horizontal 0}} :text-style {:padding-horizontal 0}
:accessibility-label :sent-request-button}
(i18n/label :t/send-request) (i18n/label :t/send-request)
[vector-icons/icon :icons/forward {:color :white}]]]]])) [vector-icons/icon :icons/forward {:color :white}]]]]]))
@ -70,12 +72,14 @@
comp/default-action comp/default-action
(i18n/label :t/receive) (i18n/label :t/receive)
[toolbar/actions [{:icon :icons/share [toolbar/actions [{:icon :icons/share
:icon-opts {:color :white} :icon-opts {:color :white
:accessibility-label :share-button}
:handler #(list-selection/open-share {:message address})}]]] :handler #(list-selection/open-share {:message address})}]]]
[react/view {:flex 1} [react/view {:flex 1}
[common/network-info {:text-color :white}] [common/network-info {:text-color :white}]
[react/scroll-view styles/request-wrapper [react/scroll-view styles/request-wrapper
[qr-code address chain-id] [qr-code address chain-id]
[button/primary-button {:on-press #(re-frame/dispatch [:navigate-to :wallet-send-transaction-request]) [button/primary-button {:on-press #(re-frame/dispatch [:navigate-to :wallet-send-transaction-request])
:style styles/send-request} :style styles/send-request
:accessibility-label :sent-transaction-request-button}
(i18n/label :t/send-transaction-request)]]]])) (i18n/label :t/send-transaction-request)]]]]))

View File

@ -19,7 +19,8 @@
[react/view styles/ok-icon-container [react/view styles/ok-icon-container
[vi/icon :icons/ok {:color components.styles/color-blue4}]] [vi/icon :icons/ok {:color components.styles/color-blue4}]]
[react/text {:style styles/transaction-sent [react/text {:style styles/transaction-sent
:font (if platform/android? :medium :default)} :font (if platform/android? :medium :default)
:accessibility-label :transaction-sent-text}
(i18n/label :t/transaction-sent)] (i18n/label :t/transaction-sent)]
[react/view styles/gap] [react/view styles/gap]
[react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]] [react/text {:style styles/transaction-sent-description} (i18n/label :t/transaction-description)]]
@ -32,7 +33,8 @@
:uppercase? (get-in platform/platform-specific [:uppercase?])} :uppercase? (get-in platform/platform-specific [:uppercase?])}
(i18n/label :t/view-transaction-details)]]] (i18n/label :t/view-transaction-details)]]]
[components/separator] [components/separator]
[react/touchable-highlight {:on-press #(re-frame/dispatch close-transaction-screen-event)} [react/touchable-highlight {:on-press #(re-frame/dispatch close-transaction-screen-event)
:accessibility-label :got-it-button}
[react/view styles/got-it-container [react/view styles/got-it-container
[react/text {:style styles/got-it [react/text {:style styles/got-it
:font (if platform/android? :medium :default) :font (if platform/android? :medium :default)

View File

@ -41,7 +41,9 @@
[react/animated-view {:style (styles/animated-sign-panel bottom-value)} [react/animated-view {:style (styles/animated-sign-panel bottom-value)}
[react/animated-view {:style (styles/sign-panel opacity-value)} [react/animated-view {:style (styles/sign-panel opacity-value)}
[react/view styles/signing-phrase-container [react/view styles/signing-phrase-container
[react/text {:style styles/signing-phrase} signing-phrase]] [react/text {:style styles/signing-phrase
:accessibility-label :signing-phrase-text}
signing-phrase]]
[react/text {:style styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)] [react/text {:style styles/signing-phrase-description} (i18n/label :t/signing-phrase-description)]
[react/view styles/password-container [react/view styles/password-container
[react/text-input [react/text-input
@ -50,7 +52,8 @@
:placeholder (i18n/label :t/enter-password) :placeholder (i18n/label :t/enter-password)
:placeholder-text-color components.styles/color-gray4 :placeholder-text-color components.styles/color-gray4
:on-change-text #(re-frame/dispatch [:wallet.send/set-password %]) :on-change-text #(re-frame/dispatch [:wallet.send/set-password %])
:style styles/password}]]] :style styles/password
:accessibility-label :enter-password-input}]]]
(when wrong-password? (when wrong-password?
[tooltip/tooltip (i18n/label :t/wrong-password)])])) [tooltip/tooltip (i18n/label :t/wrong-password)])]))
@ -60,10 +63,12 @@
[bottom-buttons/bottom-buttons [bottom-buttons/bottom-buttons
styles/sign-buttons styles/sign-buttons
[button/button {:style components.styles/flex [button/button {:style components.styles/flex
:on-press cancel-handler} :on-press cancel-handler
:accessibility-label :cancel-button}
(i18n/label :t/cancel)] (i18n/label :t/cancel)]
[button/button {:style (wallet.styles/button-container sign-enabled?) [button/button {:style (wallet.styles/button-container sign-enabled?)
:on-press sign-handler} :on-press sign-handler
:accessibility-label :sign-transaction-button}
(i18n/label :t/transactions-sign-transaction) (i18n/label :t/transactions-sign-transaction)
[vector-icons/icon :icons/forward {:color :white}]]])) [vector-icons/icon :icons/forward {:color :white}]]]))
@ -81,12 +86,14 @@
styles/sign-buttons styles/sign-buttons
(when sign-enabled? (when sign-enabled?
[button/button {:style components.styles/flex [button/button {:style components.styles/flex
:on-press sign-later-handler} :on-press sign-later-handler
:accessibility-label :sign-later-button}
(i18n/label :t/transactions-sign-later)]) (i18n/label :t/transactions-sign-later)])
[button/button {:style components.styles/flex [button/button {:style components.styles/flex
:disabled? (not immediate-sign-enabled?) :disabled? (not immediate-sign-enabled?)
:on-press #(re-frame/dispatch [:wallet.send/set-signing? true]) :on-press #(re-frame/dispatch [:wallet.send/set-signing? true])
:text-style {:color :white}} :text-style {:color :white}
:accessibility-label :sign-transaction-button}
(i18n/label :t/transactions-sign-transaction) (i18n/label :t/transactions-sign-transaction)
[vector-icons/icon :icons/forward {:color (if immediate-sign-enabled? :white :gray)}]]])) [vector-icons/icon :icons/forward {:color (if immediate-sign-enabled? :white :gray)}]]]))
@ -118,13 +125,15 @@
(i18n/label :t/gas-limit) (i18n/label :t/gas-limit)
[react/text-input (merge styles/transaction-fee-input [react/text-input (merge styles/transaction-fee-input
{:on-change-text #(re-frame/dispatch [:wallet.send/edit-gas %]) {:on-change-text #(re-frame/dispatch [:wallet.send/edit-gas %])
:default-value (str (money/to-fixed gas))})]] :default-value (str (money/to-fixed gas))
:accessibility-label :gas-limit-input})]]
[wallet.components/cartouche {} [wallet.components/cartouche {}
(i18n/label :t/gas-price) (i18n/label :t/gas-price)
[react/view styles/advanced-options-wrapper [react/view styles/advanced-options-wrapper
[react/text-input (merge styles/transaction-fee-input [react/text-input (merge styles/transaction-fee-input
{:on-change-text #(re-frame/dispatch [:wallet.send/edit-gas-price (money/->wei :gwei %)]) {:on-change-text #(re-frame/dispatch [:wallet.send/edit-gas-price (money/->wei :gwei %)])
:default-value (str (money/to-fixed (money/wei-> :gwei gas-price)))})] :default-value (str (money/to-fixed (money/wei-> :gwei gas-price)))
:accessibility-label :gas-price-input})]
[wallet.components/cartouche-secondary-text [wallet.components/cartouche-secondary-text
(i18n/label :t/gwei)]]]] (i18n/label :t/gwei)]]]]
[react/view styles/transaction-fee-info [react/view styles/transaction-fee-info
@ -134,18 +143,22 @@
[react/view styles/transaction-fee-block-wrapper [react/view styles/transaction-fee-block-wrapper
[wallet.components/cartouche {:disabled? true} [wallet.components/cartouche {:disabled? true}
(i18n/label :t/amount) (i18n/label :t/amount)
[react/view {:accessibility-label :amount-input}
[wallet.components/cartouche-text-content [wallet.components/cartouche-text-content
(str (money/to-fixed (money/wei->ether amount))) (str (money/to-fixed (money/wei->ether amount)))
(name symbol)]] (name symbol)]]]
[wallet.components/cartouche {:disabled? true} [wallet.components/cartouche {:disabled? true}
(i18n/label :t/wallet-transaction-total-fee) (i18n/label :t/wallet-transaction-total-fee)
[react/view {:accessibility-label :total-fee-input}
[wallet.components/cartouche-text-content [wallet.components/cartouche-text-content
(str (money/to-fixed (max-fee gas gas-price))) (str (money/to-fixed (max-fee gas gas-price)))
(i18n/label :t/eth)]]] (i18n/label :t/eth)]]]]
[bottom-buttons/bottom-buttons styles/fee-buttons [bottom-buttons/bottom-buttons styles/fee-buttons
[button/button {:on-press #(re-frame/dispatch [:wallet.send/reset-gas-default])} [button/button {:on-press #(re-frame/dispatch [:wallet.send/reset-gas-default])
:accessibility-label :reset-to-default-button}
(i18n/label :t/reset-default)] (i18n/label :t/reset-default)]
[button/button {:on-press #(do (re-frame/dispatch [:wallet.send/set-gas-details gas gas-price]) (act/default-handler))} [button/button {:on-press #(do (re-frame/dispatch [:wallet.send/set-gas-details gas gas-price]) (act/default-handler))
:accessibility-label :done-button}
(i18n/label :t/done)]]]]))) (i18n/label :t/done)]]]])))
(defn- advanced-cartouche [{:keys [gas gas-price]} modal?] (defn- advanced-cartouche [{:keys [gas gas-price]} modal?]
@ -154,7 +167,8 @@
:on-press #(do (re-frame/dispatch [:wallet.send/clear-gas]) :on-press #(do (re-frame/dispatch [:wallet.send/clear-gas])
(re-frame/dispatch [:navigate-to-modal :wallet-transaction-fee]))} (re-frame/dispatch [:navigate-to-modal :wallet-transaction-fee]))}
(i18n/label :t/wallet-transaction-fee) (i18n/label :t/wallet-transaction-fee)
[react/view styles/advanced-options-text-wrapper [react/view {:style styles/advanced-options-text-wrapper
:accessibility-label :transaction-fee-button}
[react/text {:style styles/advanced-fees-text} [react/text {:style styles/advanced-fees-text}
(str (money/to-fixed (max-fee gas gas-price)) " " (i18n/label :t/eth))] (str (money/to-fixed (max-fee gas gas-price)) " " (i18n/label :t/eth))]
[react/text {:style styles/advanced-fees-details-text} [react/text {:style styles/advanced-fees-details-text}
@ -164,7 +178,8 @@
[react/view {:style styles/advanced-wrapper} [react/view {:style styles/advanced-wrapper}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet.send/toggle-advanced (not advanced?)])} [react/touchable-highlight {:on-press #(re-frame/dispatch [:wallet.send/toggle-advanced (not advanced?)])}
[react/view {:style styles/advanced-button-wrapper} [react/view {:style styles/advanced-button-wrapper}
[react/view {:style styles/advanced-button} [react/view {:style styles/advanced-button
:accessibility-label :advanced-button}
[react/text {:style (merge wallet.components.styles/label styles/advanced-label)} [react/text {:style (merge wallet.components.styles/label styles/advanced-label)}
(i18n/label :t/wallet-advanced)] (i18n/label :t/wallet-advanced)]
[vector-icons/icon (if advanced? :icons/up :icons/down) {:color :white}]]]] [vector-icons/icon (if advanced? :icons/up :icons/down) {:color :white}]]]]

View File

@ -27,7 +27,8 @@
[react/view (merge components.styles/flex {:background-color :white}) [react/view (merge components.styles/flex {:background-color :white})
[status-bar/status-bar {:type :modal-wallet}] [status-bar/status-bar {:type :modal-wallet}]
[toolbar/toolbar #_{} {:style wallet.styles/toolbar} [toolbar/toolbar #_{} {:style wallet.styles/toolbar}
[toolbar/nav-text {:style {:color :white}} [toolbar/nav-text {:style {:color :white}
:accessibility-label :done-button}
(i18n/label :t/done)] (i18n/label :t/done)]
[toolbar/content-title {:color :white} [toolbar/content-title {:color :white}
(i18n/label :t/wallet-assets)]] (i18n/label :t/wallet-assets)]]

View File

@ -18,10 +18,11 @@
(re-frame/dispatch [:wallet/discard-unsigned-transaction-with-confirmation id])) (re-frame/dispatch [:wallet/discard-unsigned-transaction-with-confirmation id]))
(defn history-action [filter?] (defn history-action [filter?]
(merge (cond->
{:icon :icons/filter {:icon :icons/filter
:icon-opts {:accessibility-label :filters-button}
:handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-filter])} :handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-filter])}
(when filter? {:icon-opts {:overlay-style styles/corner-dot}}))) filter? (assoc-in [:icon-opts :overlay-style] styles/corner-dot)))
(defn- all-checked? [filter-data] (defn- all-checked? [filter-data]
(and (every? :checked? (:type filter-data)) (and (every? :checked? (:type filter-data))
@ -40,9 +41,11 @@
(defn action-buttons [{:keys [id] :as transaction}] (defn action-buttons [{:keys [id] :as transaction}]
[react/view {:style styles/action-buttons} [react/view {:style styles/action-buttons}
[button/primary-button {:style {:margin-right 12} [button/primary-button {:style {:margin-right 12}
:on-press #(re-frame/dispatch [:wallet/show-sign-transaction id])} :on-press #(re-frame/dispatch [:wallet/show-sign-transaction id])
:accessibility-label :sign-button}
(i18n/label :t/transactions-sign)] (i18n/label :t/transactions-sign)]
[button/secondary-button {:on-press #(on-delete-transaction transaction)} [button/secondary-button {:on-press #(on-delete-transaction transaction)
:accessibility-label :delete-button}
(i18n/label :t/delete)]]) (i18n/label :t/delete)]])
(defn- inbound? [type] (= :inbound type)) (defn- inbound? [type] (= :inbound type))
@ -62,11 +65,14 @@
(throw (str "Unknown transaction type: " k)))) (throw (str "Unknown transaction type: " k))))
(defn render-transaction [{:keys [hash from-contact to-contact to from type value time-formatted] :as transaction}] (defn render-transaction [{:keys [hash from-contact to-contact to from type value time-formatted] :as transaction}]
(let [[label contact address] (if (inbound? type) (let [[label contact address
[(i18n/label :t/from) from-contact from] contact-accessibility-label
[(i18n/label :t/to) to-contact to])] address-accessibility-label] (if (inbound? type)
[(i18n/label :t/from) from-contact from :sender-text :sender-address-text]
[(i18n/label :t/to) to-contact to :recipient-name-text :recipient-address-text])
unsigned? (unsigned? type)]
[list/touchable-item #(re-frame/dispatch [:show-transaction-details hash]) [list/touchable-item #(re-frame/dispatch [:show-transaction-details hash])
[react/view [react/view {:accessibility-label (if unsigned? :unsigned-transaction-item :transaction-item)}
[list/item [list/item
[list/item-icon (transaction-type->icon (keyword type))] [list/item-icon (transaction-type->icon (keyword type))]
[list/item-content [list/item-content
@ -74,24 +80,31 @@
[react/text {:style styles/tx-amount [react/text {:style styles/tx-amount
:ellipsize-mode "tail" :ellipsize-mode "tail"
:number-of-lines 1} :number-of-lines 1}
(money/wei->str :eth value)] [react/text {:accessibility-label :amount-text}
(->> value (money/wei-> :eth) money/to-fixed str)]
" "
[react/text {:accessibility-label :currency-text}
(clojure.string/upper-case (name :eth))]]
[react/text {:style styles/tx-time} [react/text {:style styles/tx-time}
time-formatted]] time-formatted]]
[react/view {:style styles/address-row} [react/view {:style styles/address-row}
[react/text {:style styles/address-label} [react/text {:style styles/address-label}
label] label]
(when contact (when contact
[react/text {:style styles/address-contact} [react/text {:style styles/address-contact
:accessibility-label contact-accessibility-label}
contact]) contact])
[react/text {:style styles/address-hash [react/text {:style styles/address-hash
:ellipsize-mode "middle" :ellipsize-mode "middle"
:number-of-lines 1} :number-of-lines 1
:accessibility-label address-accessibility-label}
address]] address]]
(when (unsigned? type) (when unsigned?
[action-buttons transaction])] [action-buttons transaction])]
[list/item-icon {:icon :icons/forward [list/item-icon {:icon :icons/forward
:style {:margin-top 10} :style {:margin-top 10}
:icon-opts styles/forward}]]]])) :icon-opts (merge styles/forward
{:accessibility-label :show-transaction-button})}]]]]))
(defn filtered-transaction? [transaction filter-data] (defn filtered-transaction? [transaction filter-data]
(:checked? (some #(when (= (:type transaction) (:id %)) %) (:type filter-data)))) (:checked? (some #(when (= (:type transaction) (:id %)) %) (:type filter-data))))
@ -119,23 +132,26 @@
[react/view {:style components.styles/flex} [react/view {:style components.styles/flex}
[list/flat-list {:data transactions [list/flat-list {:data transactions
:render-fn render-transaction :render-fn render-transaction
:empty-component [react/text {:style styles/empty-text} :empty-component [react/text {:style styles/empty-text
:accessibility-label :no-unsigned-transactions-text}
(i18n/label :t/transactions-unsigned-empty)]}]])) (i18n/label :t/transactions-unsigned-empty)]}]]))
;; Filter history ;; Filter history
(defn- item-filter [{:keys [icon checked? path]} content] (defn- item-filter [{:keys [icon checked? path]} content]
[react/view {:accessibility-label :filter-item}
[list/list-item-with-checkbox [list/list-item-with-checkbox
{:checked? checked? {:checked? checked?
:on-value-change #(re-frame/dispatch [:wallet.transactions/filter path %])} :on-value-change #(re-frame/dispatch [:wallet.transactions/filter path %])}
[list/item [list/item
[list/item-icon icon] [list/item-icon icon]
content]]) content]]])
(defn- render-item-filter [{:keys [id label checked?]}] (defn- render-item-filter [{:keys [id label checked?]}]
[item-filter {:icon (transaction-type->icon id) :checked? checked? :path {:type id}} [item-filter {:icon (transaction-type->icon id) :checked? checked? :path {:type id}}
[list/item-content [list/item-content
[list/item-primary-only label]]]) [list/item-primary-only {:accessibility-label :filter-name-text}
label]]])
(defn- wrap-filter-data [m] (defn- wrap-filter-data [m]
[{:title (i18n/label :t/transactions-filter-type) [{:title (i18n/label :t/transactions-filter-type)
@ -148,27 +164,31 @@
[react/view styles/filter-container [react/view styles/filter-container
[status-bar/status-bar {:type :modal-white}] [status-bar/status-bar {:type :modal-white}]
[toolbar/toolbar {} [toolbar/toolbar {}
[toolbar/nav-clear-text (i18n/label :t/done)] [toolbar/nav-clear-text {:accessibility-label :done-button} (i18n/label :t/done)]
[toolbar/content-title (i18n/label :t/transactions-filter-title)] [toolbar/content-title (i18n/label :t/transactions-filter-title)]
[toolbar/text-action {:handler #(re-frame/dispatch [:wallet.transactions/filter-all]) [toolbar/text-action {:handler #(re-frame/dispatch [:wallet.transactions/filter-all])
:disabled? (all-checked? filter-data)} :disabled? (all-checked? filter-data)
:accessibility-label :select-all-button}
(i18n/label :t/transactions-filter-select-all)]] (i18n/label :t/transactions-filter-select-all)]]
[react/view {:style (merge {:background-color :white} components.styles/flex)} [react/view {:style (merge {:background-color :white} components.styles/flex)}
[list/section-list {:sections (wrap-filter-data filter-data)}]]])) [list/section-list {:sections (wrap-filter-data filter-data)}]]]))
(defn history-tab [active?] (defn history-tab [active?]
[react/text {:uppercase? true [react/text {:uppercase? true
:style (styles/tab-title active?)} :style (styles/tab-title active?)
:accessibility-label :history-button}
(i18n/label :t/transactions-history)]) (i18n/label :t/transactions-history)])
(defview unsigned-tab [active?] (defview unsigned-tab [active?]
(letsubs [unsigned-transactions-count [:wallet.transactions/unsigned-transactions-count]] (letsubs [unsigned-transactions-count [:wallet.transactions/unsigned-transactions-count]]
[react/view {:flex-direction :row} [react/view {:flex-direction :row}
[react/text {:style (styles/tab-title active?) [react/text {:style (styles/tab-title active?)
:uppercase? true} :uppercase? true
:accessibility-label :unsigned-transactions-button}
(i18n/label :t/transactions-unsigned)] (i18n/label :t/transactions-unsigned)]
(when (pos? unsigned-transactions-count) (when (pos? unsigned-transactions-count)
[react/text {:style styles/tab-unsigned-transactions-count} [react/text {:style styles/tab-unsigned-transactions-count
:accessibility-label :unsigned-transactions-counter-text}
(str " " unsigned-transactions-count)])])) (str " " unsigned-transactions-count)])]))
(def tabs-list (def tabs-list
@ -201,11 +221,16 @@
:unsigned-transactions unsigned-list :unsigned-transactions unsigned-list
react/view)]])) react/view)]]))
(defn- pretty-print-asset [symbol amount] (defn- pretty-print-asset [symbol amount & [with-currency?]]
(case symbol (let [token (case symbol
;; TODO (jeluard) Format tokens amount once tokens history is supported ;; TODO (jeluard) Format tokens amount once tokens history is supported
:ETH (if amount (money/wei->str :eth amount) "...") :ETH :eth
(throw (str "Unknown asset symbol: " symbol)))) (throw (str "Unknown asset symbol: " symbol)))]
(if amount
(if with-currency?
(money/wei->str token amount)
(->> amount (money/wei-> token) money/to-fixed str))
"...")))
(defn details-header [{:keys [value date type symbol]}] (defn details-header [{:keys [value date type symbol]}]
@ -213,7 +238,12 @@
[react/view {:style styles/details-header-icon} [react/view {:style styles/details-header-icon}
[list/item-icon (transaction-type->icon type)]] [list/item-icon (transaction-type->icon type)]]
[react/view {:style styles/details-header-infos} [react/view {:style styles/details-header-infos}
[react/text {:style styles/details-header-value} (pretty-print-asset symbol value)] [react/text {:style styles/details-header-value}
[react/text {:accessibility-label :amount-text}
(pretty-print-asset symbol value)]
" "
[react/text {:accessibility-label :currency-text}
(clojure.string/upper-case (name symbol))]]
[react/text {:style styles/details-header-date} date]]]) [react/text {:style styles/details-header-date} date]]])
(defn progress-bar [progress] (defn progress-bar [progress]
@ -230,14 +260,22 @@
(i18n/label :t/confirmations-helper-text)]]) (i18n/label :t/confirmations-helper-text)]])
(defn details-list-row (defn details-list-row
([label value] ([label props-value]
(details-list-row label value nil)) (details-list-row label props-value nil))
([label value extra-value] ([label props-value extra-props-value]
(let [[props value] (if (string? props-value)
[nil props-value]
props-value)
[extra-props extra-value] (if (string? extra-props-value)
[nil extra-props-value]
extra-props-value)]
[react/view {:style styles/details-row} [react/view {:style styles/details-row}
[react/text {:style styles/details-item-label} (i18n/label label)] [react/text {:style styles/details-item-label} (i18n/label label)]
[react/view {:style styles/details-item-value-wrapper} [react/view {:style styles/details-item-value-wrapper}
[react/text {:style styles/details-item-value} (str value)] [react/text (merge {:style styles/details-item-value} props)
[react/text {:style styles/details-item-extra-value} (str extra-value)]]])) (str value)]
[react/text (merge {:style styles/details-item-extra-value} extra-props)
(str extra-value)]]])))
(defn details-list [{:keys [block hash (defn details-list [{:keys [block hash
from from-wallet from-contact from from-wallet from-contact
@ -247,11 +285,17 @@
[details-list-row :t/block block] [details-list-row :t/block block]
[details-list-row :t/hash hash] [details-list-row :t/hash hash]
[details-list-row :t/from [details-list-row :t/from
(or from-wallet from-contact from) [{:accessibility-label (if from-wallet :sender-name-text :sender-address-text)}
(when (or from-wallet from-contact) from)] (or from-wallet from-contact from)]
(when (or from-wallet from-contact)
[{:accessibility-label :sender-address-text}
from])]
[details-list-row :t/to [details-list-row :t/to
(or to-wallet to-contact to) [{:accessibility-label (if to-wallet :recipient-name-text :recipient-address-text)}
(when (or to-wallet to-contact) to)] (or to-wallet to-contact to)]
(when (or to-wallet to-contact)
[{:accessibility-label :recipient-address-text}
to])]
[details-list-row :t/gas-limit gas-limit] [details-list-row :t/gas-limit gas-limit]
[details-list-row :t/gas-price gas-price-gwei gas-price-eth] [details-list-row :t/gas-price gas-price-gwei gas-price-eth]
[details-list-row :t/gas-used gas-used] [details-list-row :t/gas-used gas-used]

View File

@ -20,24 +20,32 @@
[toolbar/actions [toolbar/actions
[(assoc (act/opts [{:label (i18n/label :t/wallet-manage-assets) [(assoc (act/opts [{:label (i18n/label :t/wallet-manage-assets)
:action #(re-frame/dispatch [:navigate-to-modal :wallet-settings-assets])}]) :action #(re-frame/dispatch [:navigate-to-modal :wallet-settings-assets])}])
:icon-opts {:color :white})]]]) :icon-opts {:color :white
:accessibility-label :options-menu-button})]]])
(defn- total-section [usd-value] (defn- total-section [usd-value]
[react/view {:style styles/main-section} [react/view {:style styles/main-section}
[react/view {:style styles/total-balance-container} [react/view {:style styles/total-balance-container}
[react/view {:style styles/total-balance} [react/view {:style styles/total-balance}
[react/text {:style styles/total-balance-value} usd-value] [react/text {:style styles/total-balance-value
[react/text {:style styles/total-balance-currency} (i18n/label :t/usd-currency)]] :accessibility-label :total-amount-value-text}
usd-value]
[react/text {:style styles/total-balance-currency
:accessibility-label :total-amount-currency-text}
(i18n/label :t/usd-currency)]]
[react/text {:style styles/total-value} (i18n/label :t/wallet-total-value)]]]) [react/text {:style styles/total-value} (i18n/label :t/wallet-total-value)]]])
(def actions (def actions
[{:label (i18n/label :t/send-transaction) [{:label (i18n/label :t/send-transaction)
:accessibility-label :send-transaction-button
:icon :icons/arrow-right :icon :icons/arrow-right
:action #(re-frame/dispatch [:navigate-to :wallet-send-transaction])} :action #(re-frame/dispatch [:navigate-to :wallet-send-transaction])}
{:label (i18n/label :t/receive-transaction) {:label (i18n/label :t/receive-transaction)
:accessibility-label :receive-transaction-button
:icon :icons/arrow-left :icon :icons/arrow-left
:action #(re-frame/dispatch [:navigate-to :wallet-request-transaction])} :action #(re-frame/dispatch [:navigate-to :wallet-request-transaction])}
{:label (i18n/label :t/transaction-history) {:label (i18n/label :t/transaction-history)
:accessibility-label :transaction-history-button
:icon :icons/transaction-history :icon :icons/transaction-history
:action #(re-frame/dispatch [:navigate-to :transactions-history])}]) :action #(re-frame/dispatch [:navigate-to :transactions-history])}])
@ -48,7 +56,8 @@
[react/view {:style styles/asset-item-value-container} [react/view {:style styles/asset-item-value-container}
[react/text {:style styles/asset-item-value [react/text {:style styles/asset-item-value
:number-of-lines 1 :number-of-lines 1
:ellipsize-mode :tail} :ellipsize-mode :tail
:accessibility-label (str (-> symbol name clojure.string/lower-case) "-asset-value-text")}
(wallet.utils/format-amount amount decimals)] (wallet.utils/format-amount amount decimals)]
[react/text {:style styles/asset-item-currency [react/text {:style styles/asset-item-currency
:uppercase? true :uppercase? true

View File

@ -23,11 +23,14 @@
content content
;; Styles are only relevant on iOS. On Android first button is 'neutral' and second is 'positive' ;; Styles are only relevant on iOS. On Android first button is 'neutral' and second is 'positive'
(clj->js (clj->js
(vector (merge {:text (i18n/label :t/cancel) :style "cancel"} (vector (merge {:text (i18n/label :t/cancel)
:style "cancel"
:accessibility-label :cancel-button}
(when on-cancel {:onPress on-cancel})) (when on-cancel {:onPress on-cancel}))
{:text (or confirm-button-text "OK") {:text (or confirm-button-text "OK")
:onPress on-accept :onPress on-accept
:style "destructive"}))))) :style "destructive"
:accessibility-label :confirm-button})))))
(defn show-question (defn show-question
([title content on-accept] ([title content on-accept]
@ -37,9 +40,12 @@
title title
content content
(clj->js (clj->js
(vector (merge {:text (i18n/label :t/no)} (vector (merge {:text (i18n/label :t/no)
:accessibility-label :no-button}
(when on-cancel {:onPress on-cancel})) (when on-cancel {:onPress on-cancel}))
{:text (i18n/label :t/yes) :onPress on-accept}))))) {:text (i18n/label :t/yes)
:onPress on-accept
:accessibility-label :yes-button})))))
(defn http-post (defn http-post
"Performs an HTTP POST request" "Performs an HTTP POST request"