Fixed tabs component

This commit is contained in:
Julien Eluard 2017-09-07 22:47:27 +02:00 committed by Roman Volosovskyi
parent aaa13b922b
commit ad7c6b8542
11 changed files with 173 additions and 89 deletions

View File

@ -114,10 +114,11 @@
creating? [:get :accounts/creating-account?]]
[view
[status-bar]
[toolbar/toolbar2 {:hide-nav? (or (empty? accounts) show-actions? creating?)}
toolbar/default-nav-back
[toolbar-content-view]
[toolbar-action]]
(let [hide-nav? (or (empty? accounts) show-actions? creating?)]
[toolbar/toolbar2 {}
(when-not hide-nav? toolbar/default-nav-back)
[toolbar-content-view]
[toolbar-action]])
[add-contact-bar]])
(defn get-intro-status-message [all-messages]

View File

@ -114,7 +114,7 @@
"A wrapper for SectionList.
See https://facebook.github.io/react-native/docs/sectionlist.html"
[{: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)
(if (and (every? #(empty? (:data %)) sections) empty-component)
empty-component
[section-list-class
(merge (base-list-props render-fn empty-component)

View File

@ -46,6 +46,7 @@
(def color-light-red2 "#f47979")
(def color-green-1 "#a8f4d4")
(def color-green-2 "#448469")
(def color-cyan "#7adcfb")
(def color-separator "#D6D6D6")

View File

@ -1,27 +1,33 @@
(ns status-im.components.tabs.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :refer [dispatch]]
(:require-macros [status-im.utils.views :refer [defview]]
[cljs.core.async.macros :as am])
(:require [cljs.core.async :as async]
[reagent.core :as r]
[re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :as react]
[status-im.components.icons.vector-icons :as vi]
[status-im.components.tabs.styles :as styles]))
[status-im.components.tabs.styles :as styles]
[status-im.utils.platform :as p]))
(defn- tab [{:keys [view-id title icon-active icon-inactive selected-view-id]}]
(defn- tab [{:keys [view-id title icon-active icon-inactive selected-view-id on-press]}]
(let [active? (= view-id selected-view-id)]
[react/touchable-highlight {:style styles/tab
:disabled active?
:on-press #(dispatch [:navigate-to-tab view-id])}
:on-press #(if on-press (on-press view-id) (dispatch [:navigate-to-tab view-id]))}
[react/view {:style styles/tab-container}
(when-let [icon (if active? icon-active icon-inactive)]
[react/view
[vi/icon icon (styles/tab-icon active?)]])
[react/view
[react/text {:style (styles/tab-title active?)}
[react/text (merge (if-not icon-active {:uppercase? (get-in p/platform-specific [:uppercase?])})
{:style (styles/tab-title active?)})
title]]]]))
(defn- create-tab [index data selected-view-id]
(defn- create-tab [index data selected-view-id on-press]
(let [data (merge data {:key index
:index index
:selected-view-id selected-view-id})]
:selected-view-id selected-view-id
:on-press on-press})]
[tab data]))
(defview tabs-container [style children]
@ -31,8 +37,78 @@
:pointer-events (if tabs-hidden? :none :auto)}
children]))
(defn tabs [{:keys [style tab-list selected-view-id]}]
(defn tabs [{:keys [style tab-list selected-view-id on-press]}]
[tabs-container style
(into
[react/view styles/tabs-inner-container]
(map-indexed #(create-tab %1 %2 selected-view-id) tab-list))])
(map-indexed #(create-tab %1 %2 selected-view-id on-press) tab-list))])
;; Swipable tabs
(defn- tab->index [tabs] (reduce #(assoc %1 (:view-id %2) (count %1)) {} tabs))
(defn get-tab-index [tabs view-id]
(get (tab->index tabs) view-id 0))
(defn index->tab [tabs] (clojure.set/map-invert (tab->index tabs)))
(defn scroll-to [tab-list prev-view-id view-id]
(let [p (get-tab-index tab-list prev-view-id)
n (get-tab-index tab-list view-id)]
(- n p)))
(defonce scrolling? (atom false))
(defn on-scroll-end [on-view-change tabs swiped? scroll-ended view-id]
(fn [_ state]
(when @scrolling?
(async/put! scroll-ended true))
(let [{:strs [index]} (js->clj state)
new-view-id ((index->tab tabs) index)]
(if new-view-id
(when-not (= @view-id new-view-id)
(reset! swiped? true)
(on-view-change new-view-id))))))
(defn start-scrolling-loop
"Loop that synchronizes tabs scrolling to avoid an inconsistent state."
[scroll-start scroll-ended]
(am/go-loop [[swiper to] (async/<! scroll-start)]
;; start scrolling
(reset! scrolling? true)
(.scrollBy swiper to)
;; lock loop until scroll ends
(async/alts! [scroll-ended (async/timeout 2000)])
(reset! scrolling? false)
(recur (async/<! scroll-start))))
(defn swipable-tabs [{:keys [style on-view-change]} tab-list prev-view-id view-id]
(let [swiped? (r/atom false)
main-swiper (r/atom nil)
scroll-start (async/chan 10)
scroll-ended (async/chan 10)]
(r/create-class
{:component-did-mount
#(start-scrolling-loop scroll-start scroll-ended)
:component-will-update
(fn []
(if @swiped?
(reset! swiped? false)
(when @main-swiper
(let [to (scroll-to tab-list @prev-view-id @view-id)]
(async/put! scroll-start [@main-swiper to])))))
:display-name "swipable-tabs"
:reagent-render
(fn []
[react/view {:style style}
[tabs {:selected-view-id @view-id
:tab-list tab-list
:on-press on-view-change}]
[react/swiper (merge styles/swiper
{:index (get-tab-index tab-list @view-id)
:ref #(reset! main-swiper %)
:loop false
:on-momentum-scroll-end (on-scroll-end on-view-change tab-list swiped? scroll-ended view-id)})
(doall
(map-indexed (fn [index {screen :screen}]
(with-meta screen {:key index})) tab-list))]])})))

View File

@ -98,5 +98,7 @@
{:color st/color-blue4
:font-size 17})
(def toolbar-text-action-disabled {:color st/color-gray7})
(def item-text-white-background {:color st/color-blue4})

View File

@ -51,8 +51,10 @@
;; Actions
(defn text-action [handler title]
[rn/text {:style (merge tst/item tst/item-text) :on-press handler}
(defn text-action [{:keys [style handler disabled?]} title]
[rn/text {:style (merge tst/item tst/item-text style
(when disabled? tst/toolbar-text-action-disabled))
:on-press (when-not disabled? handler)}
title])
(def blank-action [rn/view {:style (merge tst/item tst/toolbar-action)}])
@ -88,7 +90,7 @@
(defn toolbar2
([title] (toolbar2 nil title))
([props title] (toolbar2 props default-nav-back [content-title title]))
([props nav-item content-item] (toolbar2 props nav-item content-item nil))
([props nav-item content-item] (toolbar2 props nav-item content-item [actions [{:image :blank}]]))
([{:keys [background-color
hide-border?
style

View File

@ -49,8 +49,7 @@
(defn toolbar-edit []
[toolbar/toolbar2 {}
[toolbar/nav-button (act/back #(re-frame/dispatch [:set-in [:chat-list-ui-props :edit?] false]))]
[toolbar/content-title (i18n/label :t/edit-chats)]
[toolbar/actions [{:image :blank}]]])
[toolbar/content-title (i18n/label :t/edit-chats)]])
(defview toolbar-search []
(letsubs [search-text [:get-in [:toolbar-search :text]]]

View File

@ -40,8 +40,7 @@
(defn toolbar-edit []
[toolbar/toolbar2 {}
[toolbar/nav-button (act/back #(dispatch [:set-in [:contacts/ui-props :edit?] false]))]
[toolbar/content-title (label :t/edit-contacts)]
[toolbar/actions [{:image :blank}]]])
[toolbar/content-title (label :t/edit-contacts)]])
(defn contact-options [{:keys [unremovable?] :as contact} group]
(let [delete-contact-opt {:value #(u/show-confirmation

View File

@ -5,7 +5,6 @@
[status-im.components.checkbox.view :as checkbox]
[status-im.components.list.views :as list]
[status-im.components.react :as react]
[status-im.components.tabs.styles :as tabs.styles]
[status-im.components.tabs.views :as tabs]
[status-im.components.toolbar-new.view :as toolbar]
[status-im.i18n :as i18n]
@ -24,21 +23,23 @@
;; TODO(yenda) implement
(utils/show-popup "TODO" "Delete Transaction"))
(defn unsigned-action []
[toolbar/text-action #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])
(defn unsigned-action [unsigned-transactions]
[toolbar/text-action {:disabled? (zero? (count unsigned-transactions)) :handler #(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])}
(i18n/label :t/transactions-sign-all)])
(def history-action
{:icon :icons/filter
:icon-opts {}
:handler #(utils/show-popup "TODO" "Not implemented") #_(re-frame/dispatch [:navigate-to-modal :wallet-transactions-sign-all])})
(defn toolbar-view [view-id]
(defn toolbar-view [view-id unsigned-transactions]
[toolbar/toolbar2 {}
toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/transactions)]
(if (= @view-id :wallet-transactions-unsigned)
[unsigned-action]
(case @view-id
:wallet-transactions-unsigned
[unsigned-action unsigned-transactions]
:wallet-transactions-history
[toolbar/actions
[history-action]])])
@ -74,8 +75,7 @@
[list/item-icon {:icon :icons/forward}]])
;; TODO(yenda) hook with re-frame
(defn empty-text [s]
[react/text {:style history.styles/empty-text} s])
(defn- empty-text [s] [react/text {:style history.styles/empty-text} s])
(defview history-list []
(letsubs [transactions-history-list [:wallet/transactions-history-list]
@ -109,11 +109,6 @@
:title (i18n/label :t/transactions-history)
:screen [history-list]}])
(defn- tab->index [tabs] (reduce #(assoc %1 (:view-id %2) (count %1)) {} tabs))
(defn get-tab-index [tabs view-id]
(get (tab->index tabs) view-id 0))
;; Sign all
(defview sign-all []
@ -136,7 +131,7 @@
(defn- item-tokens [{:keys [symbol label checked?]}]
[list/item
[list/item-icon (transaction-type->icon "pending")] ;; TODO add proper token data
[list/item-icon (transaction-type->icon "pending")] ;; TODO(jeluard) add proper token data
[list/item-content label symbol]
[checkbox/checkbox {:checked? true #_checked?}]])
@ -168,34 +163,26 @@
[toolbar/toolbar2 {}
[toolbar/nav-clear-text (i18n/label :t/done)]
[toolbar/content-title (i18n/label :t/transactions-filter-title)]
[toolbar/text-action #(utils/show-popup "TODO" "Select All")
[toolbar/text-action {:handler #(utils/show-popup "TODO" "Select All")}
(i18n/label :t/transactions-filter-select-all)]]
[react/scroll-view
[list/section-list {:sections filter-data}]]])
;; TODO(jeluard) whole swipe logic
;; extract navigate-tab action (on tap)
(defn- main-section [view-id tabs ]
(let [prev-view-id (reagent/atom @view-id)]
[tabs/swipable-tabs {:style history.styles/main-section
:on-view-change #(do (reset! prev-view-id @view-id)
(reset! view-id %))}
(defn- main-section [view-id unsigned-transactions]
(let [tabs (tab-list unsigned-transactions)]
[react/view {:style history.styles/main-section}
[tabs/tabs {:selected-view-id @view-id
:tab-list tabs}]
[react/swiper (merge tabs.styles/swiper
{:index (get-tab-index tabs @view-id)
:loop false})
;:ref #(reset! swiper %)
;:on-momentum-scroll-end (on-scroll-end swiped? scroll-ended @view-id)
(doall
(map-indexed (fn [index {screen :screen}]
(with-meta screen {:key index} )) tabs))]]))
tabs prev-view-id view-id]))
;; TODO(yenda) must reflect selected wallet
(defview transactions []
(letsubs [unsigned-transactions [:wallet/unsigned-transactions]]
(let [view-id (reagent/atom :wallet-transactions-history)]
[react/view {:style history.styles/wallet-transactions-container}
[toolbar-view view-id]
[main-section view-id unsigned-transactions]])))
[unsigned-transactions [:wallet/unsigned-transactions]]
(let [tabs (tab-list unsigned-transactions)
default-view (get-in tabs [0 :view-id])
view-id (reagent/atom default-view)]
[react/view {:style history.styles/wallet-transactions-container}
[toolbar-view view-id unsigned-transactions]
[main-section view-id tabs]]))

View File

@ -48,7 +48,7 @@
:flex-shrink 1
:justify-content :space-between
:width 68
:margin-right 12})
:padding 12})
;;;;;;;;;;;;;;;;;;
;; Main section ;;
@ -150,3 +150,12 @@
(defn asset-border [color]
{:border-color color :border-width 1 :border-radius 32})
(def corner-dot
{:position :absolute
:top 12
:right 6
:width 4
:height 4
:border-radius 2
:background-color styles/color-cyan})

View File

@ -6,7 +6,7 @@
[status-im.components.button.view :as btn]
[status-im.components.drawer.view :as drawer]
[status-im.components.list.views :as list]
[status-im.components.react :as rn]
[status-im.components.react :as react]
[status-im.components.styles :as st]
[status-im.components.icons.vector-icons :as vi]
[status-im.components.toolbar-new.view :as toolbar]
@ -24,10 +24,10 @@
(utils/show-popup "TODO" "Not implemented yet!"))
(defn toolbar-title []
[rn/touchable-highlight {:on-press #(rf/dispatch [:navigate-to :wallet-list])
[react/touchable-highlight {:on-press #(rf/dispatch [:navigate-to :wallet-list])
:style wallet-styles/toolbar-title-container}
[rn/view {:style wallet-styles/toolbar-title-inner-container}
[rn/text {:style wallet-styles/toolbar-title-text
[react/view {:style wallet-styles/toolbar-title-inner-container}
[react/text {:style wallet-styles/toolbar-title-text
:font :toolbar-title}
(i18n/label :t/main-wallet)]
[vi/icon
@ -48,19 +48,27 @@
[(assoc (act/opts [{:text (i18n/label :t/wallet-settings) :value show-not-implemented!}]) :icon-opts {:color :white})
transaction-history-action]]])
(defn- change-display [change]
(let [pos-change? (pos? change)]
[react/view {:style (if pos-change?
wallet-styles/today-variation-container-positive
wallet-styles/today-variation-container-negative)}
[react/text {:style (if pos-change?
wallet-styles/today-variation-positive
wallet-styles/today-variation-negative)}
(str (if pos-change? "+" "-") change)]]))
(defn main-section [usd-value change error-message]
[rn/view {:style wallet-styles/main-section}
[react/view {:style wallet-styles/main-section}
(when error-message [wallet.views/error-message-view wallet-styles/error-container wallet-styles/error-message])
[rn/view {:style wallet-styles/total-balance-container}
[rn/view {:style wallet-styles/total-balance}
[rn/text {:style wallet-styles/total-balance-value} usd-value]
[rn/text {:style wallet-styles/total-balance-currency} "USD"]]
[rn/view {:style wallet-styles/value-variation}
[rn/text {:style wallet-styles/value-variation-title}
[react/view {:style wallet-styles/total-balance-container}
[react/view {:style wallet-styles/total-balance}
[react/text {:style wallet-styles/total-balance-value} usd-value]
[react/text {:style wallet-styles/total-balance-currency} "USD"]]
[react/view {:style wallet-styles/value-variation}
[react/text {:style wallet-styles/value-variation-title}
(i18n/label :t/wallet-total-value)]
[rn/view {:style (if (pos? change) wallet-styles/today-variation-container-positive wallet-styles/today-variation-container-negative)}
[rn/text {:style (if (pos? change) wallet-styles/today-variation-positive wallet-styles/today-variation-negative)}
change]]]
[change-display change]]
[btn/buttons wallet-styles/buttons
[{:text (i18n/label :t/wallet-send)
:on-press show-not-implemented! ;; #(rf/dispatch [:navigate-to :wallet-send-transaction])
@ -79,38 +87,38 @@
;; TODO(jeluard) Navigate to asset details screen
#_
[list/touchable-item show-not-implemented!
[rn/view
[react/view
[list/item
[list/item-image {:uri :launch_logo}]
[rn/view {:style wallet-styles/asset-item-value-container}
[rn/text {:style wallet-styles/asset-item-value} (str amount)]
[rn/text {:style wallet-styles/asset-item-currency
[react/view {:style wallet-styles/asset-item-value-container}
[react/text {:style wallet-styles/asset-item-value} (str amount)]
[react/text {:style wallet-styles/asset-item-currency
:uppercase? true}
id]]
[list/item-icon {:style :icons/forward}]]]]
[rn/view
[react/view
[list/item
(let [{:keys [source style]} (token->image id)]
[list/item-image source style])
[rn/view {:style wallet-styles/asset-item-value-container}
[rn/text {:style wallet-styles/asset-item-value} (str amount)]
[rn/text {:style wallet-styles/asset-item-currency
[react/view {:style wallet-styles/asset-item-value-container}
[react/text {:style wallet-styles/asset-item-value} (str amount)]
[react/text {:style wallet-styles/asset-item-currency
:uppercase? true}
id]]]])
(defn render-add-asset-fn [{:keys [id currency amount]}]
[list/touchable-item show-not-implemented!
[rn/view
[react/view
[list/item
[list/item-icon {:icon :icons/add :style wallet-styles/add-asset-icon :icon-opts {:color :blue}}]
[rn/view {:style wallet-styles/asset-item-value-container}
[rn/text {:style wallet-styles/add-asset-text}
[react/view {:style wallet-styles/asset-item-value-container}
[react/text {:style wallet-styles/add-asset-text}
(i18n/label :t/wallet-add-asset)]]]]])
(defn asset-section [eth prices-loading? balance-loading?]
(let [assets [{:id "eth" :currency :eth :amount eth}]]
[rn/view {:style wallet-styles/asset-section}
[rn/text {:style wallet-styles/asset-section-title} (i18n/label :t/wallet-assets)]
[react/view {:style wallet-styles/asset-section}
[react/text {:style wallet-styles/asset-section-title} (i18n/label :t/wallet-assets)]
[list/section-list
{:sections [{:key :assets
:data assets
@ -129,8 +137,8 @@
prices-loading? [:prices-loading?]
balance-loading? [:wallet/balance-loading?]
error-message [:wallet/error-message?]]
[rn/view {:style wallet-styles/wallet-container}
[react/view {:style wallet-styles/wallet-container}
[toolbar-view]
[rn/scroll-view
[react/scroll-view
[main-section portfolio-value portfolio-change error-message]
[asset-section eth-balance prices-loading? balance-loading?]]]))