diff --git a/.env.jenkins b/.env.jenkins index f175c7fe5a..99707fc0cb 100644 --- a/.env.jenkins +++ b/.env.jenkins @@ -1,2 +1,2 @@ TESTFAIRY_ENABLED=1 -WALLET_WIP_ENABLED=0 \ No newline at end of file +WALLET_WIP_ENABLED=1 \ No newline at end of file diff --git a/src/status_im/components/button/styles.cljs b/src/status_im/components/button/styles.cljs index ba2a207122..8dc15bf855 100644 --- a/src/status_im/components/button/styles.cljs +++ b/src/status_im/components/button/styles.cljs @@ -16,9 +16,9 @@ {:flex-direction :row})) (def action-button - {:flex-basis 0 - :flex 1 - :align-items :center}) + {:flex-direction :row + :justify-content :center + :align-items :center}) (def action-button-center (merge action-button @@ -27,7 +27,7 @@ :border-right-width 1})) (def action-button-text - {:font-size 18 + {:font-size 15 :font-weight "normal" :color st/color-white :padding-horizontal 16 diff --git a/src/status_im/components/list/styles.cljs b/src/status_im/components/list/styles.cljs index 5304f4447c..6271a7ae81 100644 --- a/src/status_im/components/list/styles.cljs +++ b/src/status_im/components/list/styles.cljs @@ -10,15 +10,22 @@ {:flex 1 :flex-direction :column}) +(def primary-text-base + {:font-size 17 + :color st/color-black}) + (def primary-text - {:font-size 20 - :color st/color-black - :padding-top 13}) + (merge primary-text-base + {:padding-top 12})) + +(def primary-text-only + (merge primary-text-base + {:padding-vertical 22})) (def secondary-text {:font-size 16 :color st/color-gray4 - :padding-top 6}) + :padding-top 4}) (def item-icon {:width 40 @@ -29,11 +36,6 @@ (def secondary-action item-icon) -(def action-buttons - {:flex 1 - :flex-direction :row - :padding-vertical 12}) - (def base-separator {:height 1 :background-color st/color-gray5 @@ -49,7 +51,7 @@ (def section-separator base-separator) (def section-header - {:margin-vertical 2 - :margin-bottom 12 - :margin-top 16 - :margin-left 16}) \ No newline at end of file + {:font-size 14 + :margin-vertical 2 + :margin-top 16 + :margin-left 16}) \ No newline at end of file diff --git a/src/status_im/components/list/views.cljs b/src/status_im/components/list/views.cljs index 0aeabb6039..50b464e49d 100644 --- a/src/status_im/components/list/views.cljs +++ b/src/status_im/components/list/views.cljs @@ -1,4 +1,21 @@ (ns status-im.components.list.views + " + Wrapper for react-native list components. + + (defn render [{:keys [title subtitle]}] + [item + [item-icon :dots_vertical_white] + [item-content title subtitle] + [item-icon :arrow_right_gray]]) + + [flat-list {:data [{:title \"\" :subtitle \"\"}] :render-fn render}] + + [section-list {:sections [{:title :key :unik :data {:title \"\" :subtitle \"\"}}] :render-fn render}] + + or with a per-section `render-fn` + + [section-list {:sections [{:title \"\" :key :unik :render-fn render :data {:title \"\" :subtitle \"\"}}]}] + " (:require [reagent.core :as r] [status-im.components.list.styles :as lst] [status-im.components.react :as rn] @@ -7,12 +24,34 @@ (def flat-list-class (rn/get-class "FlatList")) (def section-list-class (rn/get-class "SectionList")) +(defn item + ([content] (item nil content)) + ([left-action content] (item left-action content nil)) + ([left-action content right-action] + [rn/view {:style lst/item} + left-action + content + right-action])) + +(defn item-icon [k] + [rn/icon k lst/item-icon]) + +(defn item-content + ([primary] (item-content primary nil)) + ([primary secondary] (item-content primary secondary nil)) + ([primary secondary extra] + [rn/view {:style lst/item-text-view} + [rn/text {:style (if secondary lst/primary-text lst/primary-text-only)} primary] + (when secondary + [rn/text {:style lst/secondary-text :ellipsize-mode "middle" :number-of-lines 1} secondary]) + extra])) + (defn- wrap-render-fn [f] (fn [data] ;; For details on passed data - ;; https://facebook.github.io/react-native/docs/sectionlist.html#rendersectionheader + ;; https://facebook.github.io/react-native/docs/sectionlist.html#renderitem (let [{:keys [item index separators]} (js->clj data :keywordize-keys true)] - (r/as-element (f item index separators))))) + (r/as-element (f (js->clj item) index separators))))) (defn- separator [] [rn/view lst/separator]) @@ -21,8 +60,8 @@ [rn/view lst/section-separator]) (defn base-list-props [render-fn empty-component] - (merge {:renderItem (wrap-render-fn render-fn) - :keyExtractor (fn [_ i] i)} + (merge {:keyExtractor (fn [_ i] i)} + (when render-fn {:renderItem (wrap-render-fn render-fn)}) (when p/ios? {:ItemSeparatorComponent (fn [] (r/as-element [separator]))}) ; TODO(jeluard) Does not work with our current ReactNative version (when empty-component {:ListEmptyComponent (r/as-element [empty-component])}))) @@ -30,33 +69,34 @@ (defn flat-list "A wrapper for FlatList. See https://facebook.github.io/react-native/docs/flatlist.html" - ([data render-fn] (flat-list data render-fn {})) - ([data render-fn {:keys [empty-component] :as props}] - (if (and (empty? data) empty-component) - ;; TODO(jeluard) remove when native :ListEmptyComponent is supported - empty-component - [flat-list-class - (merge (base-list-props render-fn empty-component) - {:data (clj->js data)} - props)]))) + [{:keys [data render-fn empty-component] :as props}] + (if (and (empty? data) empty-component) + ;; TODO(jeluard) remove when native :ListEmptyComponent is supported + empty-component + [flat-list-class + (merge (base-list-props render-fn empty-component) + {:data (clj->js data)} + props)])) (defn- wrap-render-section-header-fn [f] (fn [data] ;; For details on passed data ;; https://facebook.github.io/react-native/docs/sectionlist.html#rendersectionheader - (let [{:keys [isection]} (js->clj data :keywordize-keys true)] + (let [{:keys [section]} (js->clj data :keywordize-keys true)] (r/as-element (f section))))) +(defn- default-render-section-header [m] + [rn/text {:style lst/section-header} (:title m)]) + (defn section-list "A wrapper for SectionList. See https://facebook.github.io/react-native/docs/sectionlist.html" - ([data render-fn render-section-header-fn] (section-list data render-fn render-section-header-fn {})) - ([data render-fn render-section-header-fn {:keys [empty-component] :as props}] - (if (and (empty? data) empty-component) - empty-component - [section-list-class - (merge (base-list-props render-fn empty-component) - {:sections (clj->js data) - :renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)} - (when p/ios? {:SectionSeparatorComponent (fn [] (r/as-element [section-separator]))}) - props)]))) \ No newline at end of file + [{:keys [sections render-fn empty-component render-section-header-fn] :or {render-section-header-fn default-render-section-header} :as props}] + (if (and (empty? sections) empty-component) + empty-component + [section-list-class + (merge (base-list-props render-fn empty-component) + {:sections (clj->js (map #(if-let [f (:render-fn %)] (assoc % :renderItem (wrap-render-fn f)) %) sections)) + :renderSectionHeader (wrap-render-section-header-fn render-section-header-fn)} + (when p/ios? {:SectionSeparatorComponent (fn [] (r/as-element [section-separator]))}) + props)])) \ No newline at end of file diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index 7e62ff31f4..c665c60e2f 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -77,8 +77,7 @@ (defn text ([t] (r/as-element [text-class t])) - ([{:keys [uppercase?] :as opts - :or {font :default}} t & ts] + ([{:keys [uppercase?] :as opts} t & ts] (r/as-element (let [ts (cond->> (conj ts t) uppercase? (map clojure.string/upper-case))] diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs index c536072896..2bc1a493e9 100644 --- a/src/status_im/components/styles.cljs +++ b/src/status_im/components/styles.cljs @@ -10,6 +10,7 @@ (def color-blue-transparent "#7099e632") (def color-black "#000000") (def color-purple "#a187d5") +(def color-gray-transparent "rgba(0, 0, 0, 0.4)") (def color-gray "#838c93de") (def color-gray2 "#8f838c93") (def color-gray3 "#00000040") diff --git a/src/status_im/components/toolbar_new/styles.cljs b/src/status_im/components/toolbar_new/styles.cljs index f226851339..a1e8a1878d 100644 --- a/src/status_im/components/toolbar_new/styles.cljs +++ b/src/status_im/components/toolbar_new/styles.cljs @@ -1,15 +1,9 @@ (ns status-im.components.toolbar-new.styles (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]]) - (:require [status-im.components.styles :refer [text1-color - color-white - color-light-gray - color-gray5 - color-gray4 - color-blue - color-black]] + (:require [status-im.components.styles :as st] [status-im.utils.platform :as p])) -(def toolbar-background1 color-white) +(def toolbar-background1 st/color-white) (def toolbar-icon-width 24) (def toolbar-icon-height 24) @@ -42,7 +36,7 @@ :ios {:align-items :center}}) (defstyle toolbar-title-text - {:color text1-color + {:color st/text1-color :letter-spacing -0.2 :font-size 17 :ios {:text-align "center"}}) @@ -81,7 +75,7 @@ :padding-left 0 :padding-bottom 0 :text-align-vertical :center - :color color-black + :color st/color-black :ios {:padding-left 8 :padding-top 2 :letter-spacing -0.2}}) @@ -93,3 +87,9 @@ (def toolbar-button {:paddingVertical 16 :paddingHorizontal 12}) + +(def toolbar-right-action + {:color st/color-blue4 + :font-size 17 + :margin-right 12}) + diff --git a/src/status_im/components/toolbar_new/view.cljs b/src/status_im/components/toolbar_new/view.cljs index b03b67ccee..6497191651 100644 --- a/src/status_im/components/toolbar_new/view.cljs +++ b/src/status_im/components/toolbar_new/view.cljs @@ -18,6 +18,10 @@ [rn/view [rn/image image]]]) +(defn text-action [handler title] + [rn/text {:style tst/toolbar-right-action :onPress handler} + title]) + (defn toolbar [{:keys [title nav-action hide-nav? diff --git a/src/status_im/transactions/screens/unsigned_transactions.cljs b/src/status_im/transactions/screens/unsigned_transactions.cljs index a3bbced629..0c8d618645 100644 --- a/src/status_im/transactions/screens/unsigned_transactions.cljs +++ b/src/status_im/transactions/screens/unsigned_transactions.cljs @@ -50,7 +50,7 @@ {:component-did-update #(when-not (seq transactions) (rf/dispatch [:navigate-back])) :component-will-unmount #(rf/dispatch [:set-in [:transactions-list-ui-props :confirmed?] false])} (let [offline? (or (= network-status :offline) (= sync-state :offline))] - [(if platform/ios? rn/keyboard-avoiding-view rn/view) (merge {:behavior :padding} st/transactions-screen) + [rn/keyboard-avoiding-view st/transactions-screen [status-bar/status-bar {:type :transaction}] [toolbar-view transactions] [rn/view {:style st/transactions-screen-content-container} diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index d8d050fe21..9dc87467bc 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -334,8 +334,15 @@ :transactions-to "To" :transactions-sign "Sign" :transactions-sign-all "Sign all" + :transactions-sign-all-text "Sign the transaction by entering your password.\nMake sure that the words above match your secret signing phrase" + :transactions-sign-input-placeholder "Enter your passphrase" + :transactions-sign-all-done "Done" :transactions-delete "Delete" :transactions-history "History" :transactions-unsigned "Unsigned" :transactions-history-empty "You don't have a history transactions" - :transactions-unsigned-empty "You don't have unsigned transactions"}) + :transactions-unsigned-empty "You don't have unsigned transactions" + :transactions-filter-title "Filter History" + :transactions-filter-tokens "Tokens" + :transactions-filter-type "Type" + :transactions-filter-select-all "Select all"}) diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 460be6c2d3..c6ffd3523b 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -42,7 +42,7 @@ [status-im.ui.screens.profile.photo-capture.views :refer [profile-photo-capture]] [status-im.ui.screens.profile.qr-code.views :refer [qr-code-view]] [status-im.ui.screens.wallet.send.views :refer [send-transaction]] - [status-im.ui.screens.wallet.history.views :refer [wallet-transactions]])) + [status-im.ui.screens.wallet.history.views :as wallet-history])) (defn validate-current-view [current-view signed-up?] @@ -58,8 +58,6 @@ (when view-id (let [current-view (validate-current-view view-id signed-up?)] (let [component (case current-view - :wallet-transactions-unsigned wallet-transactions - :wallet-transactions-history wallet-transactions :wallet main-tabs :wallet-send-transaction send-transaction :discover main-tabs @@ -105,6 +103,8 @@ :transaction-details transaction-details :confirmation-success confirmation-success :contact-list-modal contact-list-modal - :wallet-transactions wallet-transactions + :wallet-transactions wallet-history/transactions + :wallet-transactions-filter wallet-history/filter-history + :wallet-transactions-sign-all wallet-history/sign-all (throw (str "Unknown modal view: " modal-view)))] [component])]])]]))))) diff --git a/src/status_im/ui/screens/wallet/history/styles.cljs b/src/status_im/ui/screens/wallet/history/styles.cljs index 903ba530b9..6f148e8396 100644 --- a/src/status_im/ui/screens/wallet/history/styles.cljs +++ b/src/status_im/ui/screens/wallet/history/styles.cljs @@ -5,11 +5,6 @@ {:flex 1 :background-color st/color-white}) -(def toolbar-right-action - {:color st/color-blue4 - :font-size 17 - :margin-right 12}) - (def main-section {:flex 1 :position :relative @@ -18,4 +13,51 @@ (def empty-text {:text-align :center :margin-top 22 - :margin-horizontal 92}) \ No newline at end of file + :margin-horizontal 92}) + +(def action-buttons + {:flex 1 + :flex-direction :row + :padding-vertical 12}) + +(def sign-all-view + {:flex 1 + :flex-direction :column + :justify-content :center + :background-color st/color-gray-transparent}) + +(def sign-all-popup + {:align-self :flex-start + :background-color st/color-white + :margin-horizontal 12 + :border-radius 8}) + +(def sign-all-popup-sign-phrase + {:border-radius 8 + :margin-top 12 + :margin-horizontal 12 + :text-align :center + :padding-vertical 9 + :background-color st/color-light-gray}) + +(def sign-all-popup-text + {:margin-top 8 + :margin-horizontal 12}) + +(def sign-all-actions + {:flex-direction :row + :justify-content :space-between + :margin-horizontal 12 + :margin-vertical 20}) + +(def sign-all-input + {:width 150 + :height 38}) + +(def sign-all-done + {:position :absolute + :right 0 + :top 0}) + +(def sign-all-done-button + {:background-color :transparent}) \ No newline at end of file diff --git a/src/status_im/ui/screens/wallet/history/views.cljs b/src/status_im/ui/screens/wallet/history/views.cljs index 72d3d46b46..f30751c51e 100644 --- a/src/status_im/ui/screens/wallet/history/views.cljs +++ b/src/status_im/ui/screens/wallet/history/views.cljs @@ -1,12 +1,13 @@ (ns status-im.ui.screens.wallet.history.views (:require-macros [status-im.utils.views :refer [defview letsubs]]) (:require [reagent.core :as r] + [re-frame.core :as rf] [status-im.components.button.view :as btn] [status-im.components.react :as rn] - [status-im.components.list.styles :as list-st] [status-im.components.list.views :as list] [status-im.components.tabs.styles :as tst] [status-im.components.tabs.views :as tabs] + [status-im.components.toolbar-new.actions :as act] [status-im.components.toolbar-new.view :as toolbar] [status-im.ui.screens.wallet.history.styles :as st] [status-im.utils.utils :as utils] @@ -17,24 +18,19 @@ ;; TODO(yenda) implement (utils/show-popup "TODO" "Sign Transaction")) -(defn on-sign-all-transactions - [m] - ;; TODO(yenda) implement - (utils/show-popup "TODO" "Sign All Transactions")) - (defn on-delete-transaction [m] ;; TODO(yenda) implement (utils/show-popup "TODO" "Delete Transaction")) (defn unsigned-action [] - [rn/text {:style st/toolbar-right-action :onPress on-sign-all-transactions} + [toolbar/text-action #(rf/dispatch [:navigate-to-modal :wallet-transactions-sign-all]) (i18n/label :t/transactions-sign-all)]) (defn history-action [] - ;; TODO(jeluard) - [rn/text {:style st/toolbar-right-action} - "AAAAA"]) + ;; TODO(jeluard) replace with proper icon + [toolbar/text-action #(rf/dispatch [:navigate-to-modal :wallet-transactions-filter]) + "History"]) (defn toolbar-view [view-id] [toolbar/toolbar @@ -48,28 +44,20 @@ :dropdown_white)) (defn action-buttons [m ] - [rn/view {:style list-st/action-buttons} + [rn/view {:style st/action-buttons} [btn/primary-button {:text (i18n/label :t/transactions-sign) :on-press #(on-sign-transaction m)}] [btn/secondary-button {:text (i18n/label :t/transactions-delete) :on-press #(on-delete-transaction m)}]]) (defn- unsigned? [state] (= "unsigned" state)) -(defn transaction-details [{:keys [to state] {:keys [value symbol]} :content :as m}] - [rn/view {:style list-st/item-text-view} - [rn/text {:style list-st/primary-text} (str value " " symbol)] - [rn/text {:style list-st/secondary-text :ellipsize-mode "middle" :number-of-lines 1} (str (i18n/label :t/transactions-to) " " to)] - (if (unsigned? state) - [action-buttons m])]) - -(defn render-transaction [m] - [rn/view {:style list-st/item} - [rn/image {:source {:uri :console} - :style list-st/item-icon}] - [transaction-details m] - [rn/icon :forward_gray list-st/secondary-action]]) - -(defn render-section-header [m] - [rn/text {:style list-st/section-header} (:title m)]) +(defn render-transaction [{:keys [to state] {:keys [value symbol]} :content :as m}] + [list/item + [list/item-icon :ok_blue] + [list/item-content + (str value " " symbol) (str (i18n/label :t/transactions-to) " " to) + (if (unsigned? state) + [action-buttons m])] + [list/item-icon :forward_gray]]) (def dummy-transaction-data [{:to "0x829bd824b016326a401d083b33d092293333a830" :content {:value "0,4909" :symbol "ETH"} :state :unsigned} @@ -94,26 +82,104 @@ [rn/text {:style st/empty-text} s]) (defview history-list [] - [list/section-list dummy-transaction-data-sorted render-transaction render-section-header - {:empty-component (empty-text (i18n/label :t/transactions-history-empty))}]) + [list/section-list {:sections dummy-transaction-data-sorted + :render-fn render-transaction + :empty-component (empty-text (i18n/label :t/transactions-history-empty))}]) (defview unsigned-list [] - [list/flat-list dummy-transaction-data render-transaction - {:empty-component (empty-text (i18n/label :t/transactions-unsigned-empty))}]) + [list/flat-list {:data dummy-transaction-data + :render-fn render-transaction + :empty-component (empty-text (i18n/label :t/transactions-unsigned-empty))}]) (def tab-list [{:view-id :wallet-transactions-unsigned - :title (i18n/label :t/transactions-unsigned) - :screen unsigned-list} + :title (i18n/label :t/transactions-unsigned) + :screen unsigned-list} {:view-id :wallet-transactions-history - :title (i18n/label :t/transactions-history) - :screen history-list}]) + :title (i18n/label :t/transactions-history) + :screen history-list}]) (def tab->index (reduce #(assoc %1 (:view-id %2) (count %1)) {} tab-list)) (defn get-tab-index [view-id] (get tab->index view-id 0)) +;; Sign all + +(defview sign-all [] + [] + [rn/keyboard-avoiding-view {:style st/sign-all-view} + [rn/view {:style st/sign-all-done} + [btn/primary-button {:style st/sign-all-done-button + :text (i18n/label :t/transactions-sign-all-done) + :on-press #(rf/dispatch [:navigate-back])}]] + [rn/view {:style st/sign-all-popup} + [rn/text {:style st/sign-all-popup-sign-phrase} "one two three"] ;; TODO hook + [rn/text {:style st/sign-all-popup-text} (i18n/label :t/transactions-sign-all-text)] + [rn/view {:style st/sign-all-actions} + [rn/text-input {:style st/sign-all-input + :secure-text-entry true + :placeholder (i18n/label :t/transactions-sign-input-placeholder)}] + [btn/primary-button {:text (i18n/label :t/transactions-sign-all) :on-press #(on-sign-transaction %)}]]]]) + +;; Filter history + +(defn- token->icon [s] + (case s + "GNO" :dollar_green + :ok_blue)) + +(defn item-tokens [{:keys [symbol label]}] + [list/item + [list/item-icon (token->icon symbol)] + [list/item-content label symbol] + ;; TODO checkbox + ]) + +(defn- type->icon [k] + (case k + "incoming" :dollar_green + "outgoing" :ok_blue + "pending" :dollar_green + "postponed" :ok_blue + :ok_blue)) + +(defn item-type [{:keys [id label]}] + [list/item + [list/item-icon (type->icon id)] + [list/item-content label] + ;; TODO checkbox + ]) + +(def filter-data + [{:title (i18n/label :t/transactions-filter-tokens) + :key :tokens + :render-fn item-tokens + :data [{:symbol "GNO" :label "Gnosis"} + {:symbol "SNT" :label "Status Network Token"} + {:symbol "SGT" :label "Status Genesis Token"} + {:symbol "GOL" :label "Golem"}]} + {:title (i18n/label :t/transactions-filter-type) + :key :type + :render-fn item-type + :data [{:id :incoming :label "Incoming"} + {:id :outgoing :label "Outgoing"} + {:id :pending :label "Pending"} + {:id :postponed :label "Postponed"}]}]) + +(defview filter-history [] + [] + [rn/view + [toolbar/toolbar + ;; TODO(jeluard) replace with icon when available and toolbar has been refactored + {:title (i18n/label :t/transactions-filter-title) + :nav-action (act/back #(rf/dispatch [:navigate-back]));; TODO close modal + :custom-action + [toolbar/text-action #(rf/dispatch [:navigate-to-modal :wallet-transactions-filter]) + (i18n/label :t/transactions-filter-select-all)]}] + [rn/scroll-view + [list/section-list {:sections filter-data}]]]) + ;; TODO(jeluard) whole swipe logic ;; extract navigate-tab action (on tap) @@ -135,7 +201,7 @@ (def initial-tab (-> tab-list first :view-id)) -(defview wallet-transactions [] +(defview transactions [] [] (let [view-id (r/atom initial-tab)] [rn/view {:style st/wallet-transactions-container}