From c7893ebd1710808f69c14537e704cce620e6eca1 Mon Sep 17 00:00:00 2001 From: Eric Dvorsak Date: Fri, 6 Oct 2017 15:08:16 +0200 Subject: [PATCH] [feature] update react-native-swiper rework current use of swiper to make it reusable --- package.json | 2 +- src/status_im/components/styles.cljs | 4 + src/status_im/components/tabs/styles.cljs | 69 +++----- src/status_im/components/tabs/views.cljs | 82 +++++----- src/status_im/ui/screens/main_tabs/views.cljs | 151 ++++++------------ src/status_im/ui/screens/views.cljs | 2 +- src/status_im/ui/screens/wallet/events.cljs | 5 - .../ui/screens/wallet/main/views.cljs | 2 +- .../ui/screens/wallet/navigation.cljs | 2 +- .../screens/wallet/transactions/styles.cljs | 15 +- .../ui/screens/wallet/transactions/views.cljs | 49 +++--- .../status_im/test/components/main_tabs.cljs | 5 - 12 files changed, 144 insertions(+), 244 deletions(-) diff --git a/package.json b/package.json index 0fd2a112a0..35210190a8 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "react-native-sortable-listview": "^0.1.1", "react-native-splash-screen": "1.0.9", "react-native-svg": "^4.6.1", - "react-native-swiper": "1.5.10", + "react-native-swiper": "1.5.13", "react-native-tcp": "^3.2.1", "react-native-udp": "^2.0.0", "react-native-vector-icons": "^4.0.1", diff --git a/src/status_im/components/styles.cljs b/src/status_im/components/styles.cljs index f4395eb31a..17f80bfcd8 100644 --- a/src/status_im/components/styles.cljs +++ b/src/status_im/components/styles.cljs @@ -143,3 +143,7 @@ :top 0 :right 0 :bottom 0}) + +(def main-container + {:background-color color-white + :flex 1}) diff --git a/src/status_im/components/tabs/styles.cljs b/src/status_im/components/tabs/styles.cljs index 667f9eff2b..7f832fc26b 100644 --- a/src/status_im/components/tabs/styles.cljs +++ b/src/status_im/components/tabs/styles.cljs @@ -1,66 +1,37 @@ (ns status-im.components.tabs.styles - (:require-macros [status-im.utils.styles :refer [defnstyle defstyle]]) (:require [status-im.components.styles :as styles] - [status-im.utils.platform :as platform])) - + [status-im.utils.platform :as platform]) + (:require-macros [status-im.utils.styles :refer [defnstyle]])) (def tabs-height (if platform/ios? 52 56)) (def tab-height (dec tabs-height)) -(defn tabs-container [hidden?] - {:position :absolute - :bottom (if hidden? (- tabs-height) 0) - :left 0 - :right 0 +(def tabs-container + {:flex-direction :row :height tabs-height :background-color styles/color-white - :transform [{:translateY 1}]}) - -(def tabs-container-line - {:border-top-width 1 + :border-top-width 1 :border-top-color styles/color-light-gray3}) -(def tabs-inner-container - {:flexDirection :row +(def tab-container + {:flex 1 :height tab-height - :opacity 1 - :justifyContent :center - :alignItems :center}) + :justify-content :center + :align-items :center}) -(def tab - {:flex 1 - :height tab-height - :justify-content :center - :align-items :center - :border-bottom-width 2 - :border-bottom-color styles/color-white}) +(defnstyle tab [active?] + {:flex 1 + :height tab-height + :justify-content :center + :align-items :center}) -(defnstyle tab-title [active? text-only?] - {:ios {:font-size (if text-only? 15 11)} - :android {:font-size (if text-only? 14 12)} +(defnstyle tab-title [active?] + {:ios {:font-size 11} + :android {:font-size 12} :text-align :center - :color (cond - active? styles/color-blue4 - text-only? styles/color-black - :else styles/color-gray4)}) + :color (if active? + styles/color-blue4 + styles/color-gray4)}) (defn tab-icon [active?] {:color (if active? styles/color-blue4 styles/color-gray4)}) - -(def tab-container - {:flex 1 - :height tab-height - :justify-content :center - :align-items :center}) - -(def swiper - {:shows-pagination false}) - -(defn main-swiper [tabs-hidden?] - (merge - swiper - {:position :absolute - :top 0 - :left 0 - :right 0 - :bottom (if tabs-hidden? 0 tabs-height)})) diff --git a/src/status_im/components/tabs/views.cljs b/src/status_im/components/tabs/views.cljs index f62a291fb3..03a28daf1e 100644 --- a/src/status_im/components/tabs/views.cljs +++ b/src/status_im/components/tabs/views.cljs @@ -1,42 +1,52 @@ (ns status-im.components.tabs.views - (:require [re-frame.core :refer [dispatch]] - [status-im.components.icons.vector-icons :as vi] + (:require [re-frame.core :as re-frame] [status-im.components.react :as react] - [status-im.components.tabs.styles :as tabs.styles] - [status-im.utils.platform :as platform]) + [status-im.components.styles :as styles] + [status-im.components.tabs.styles :as tabs.styles]) (:require-macros [status-im.utils.views :refer [defview]])) -(defn- tab [{:keys [view-id title icon-active icon-inactive style-active selected-view-id on-press]}] - (let [active? (= view-id selected-view-id) - text-only? (nil? icon-active)] - [react/touchable-highlight {:style (merge tabs.styles/tab (if (and active? style-active) style-active)) - :disabled active? - :on-press #(if on-press (on-press view-id) (dispatch [:navigate-to-tab view-id]))} - [react/view {:style tabs.styles/tab-container} - (when-let [icon (if active? icon-active icon-inactive)] - [react/view - [vi/icon icon (tabs.styles/tab-icon active?)]]) - [react/view - [react/text (merge (if text-only? {:uppercase? (get-in platform/platform-specific [:uppercase?])}) - {:style (tabs.styles/tab-title active? text-only?)}) - title]]]])) +(defview tab [index content tab-style on-press active?] + [react/touchable-highlight {:style (when tab-style + (tab-style active?)) + :disabled active? + :on-press #(on-press index)} + [react/view + [content active?]]]) -(defn- create-tab [index data selected-view-id on-press style-active] - (let [data (merge data {:key index - :index index - :style-active style-active - :selected-view-id selected-view-id - :on-press on-press})] - [tab data])) +(defn tabs [tabs-container-style indexed-tabs tab-style on-press is-current-tab?] + [react/view {:style tabs-container-style} + (for [[index {:keys [content view-id]}] indexed-tabs] + ^{:key index} [tab index content tab-style on-press (is-current-tab? view-id)])]) -(defview tabs-container [style children] - (letsubs [tabs-hidden? [:tabs-hidden?]] - [react/animated-view {:style style - :pointer-events (if tabs-hidden? :none :auto)} - children])) - -(defn tabs [{:keys [style style-tab-active tab-list selected-view-id on-press]}] - [tabs-container style - (into - [react/view tabs.styles/tabs-inner-container] - (map-indexed #(create-tab %1 %2 selected-view-id on-press style-tab-active) tab-list))]) +(defn swipable-tabs [tabs-list current-tab + {:keys [bottom-tabs? navigation-event main-container-style tabs-container-style tab-style] + :or {bottom-tabs false + navigation-event :navigate-to + tabs-container-style tabs.styles/tabs-container + tab-style tabs.styles/tab}}] + (let [swiper (atom nil) + indexed-tabs (map-indexed vector tabs-list) + tab->index (reduce (fn [acc [index tab]] + (assoc acc (:view-id tab) index)) + {} + indexed-tabs) + index->tab (clojure.set/map-invert tab->index) + get-tab-index #(get tab->index % 0)] + (fn [tabs-list current-tab] + (let [current-tab-index (get-tab-index current-tab) + on-press (fn [index] + (.scrollBy @swiper (- index current-tab-index))) + is-current-tab? (fn [view-id] + (= (get-tab-index view-id) current-tab-index))] + [react/view styles/main-container + (when-not bottom-tabs? + [tabs tabs-container-style indexed-tabs tab-style on-press is-current-tab?]) + [react/swiper {:loop false + :shows-pagination false + :index (get-tab-index current-tab) + :ref #(reset! swiper %) + :on-index-changed #(re-frame/dispatch [navigation-event (index->tab %)])} + (for [[index {:keys [screen view-id]}] indexed-tabs] + ^{:key index} [screen (is-current-tab? view-id)])] + (when bottom-tabs? + [tabs tabs-container-style indexed-tabs tab-style on-press is-current-tab?])])))) diff --git a/src/status_im/ui/screens/main_tabs/views.cljs b/src/status_im/ui/screens/main_tabs/views.cljs index 89ac3167b5..10da40c007 100644 --- a/src/status_im/ui/screens/main_tabs/views.cljs +++ b/src/status_im/ui/screens/main_tabs/views.cljs @@ -1,114 +1,57 @@ (ns status-im.ui.screens.main-tabs.views - (:require-macros [status-im.utils.views :as views] - [cljs.core.async.macros :as async-macros]) - (:require [re-frame.core :as re-frame] + (:require [status-im.components.drawer.view :refer [drawer-view]] + [status-im.components.icons.vector-icons :as vector-icons] [status-im.components.react :as react] - [status-im.components.tabs.styles :as styles] - [status-im.components.styles :as common-styles] - [status-im.i18n :as i18n] - [cljs.core.async :as async] [status-im.components.status-bar :refer [status-bar]] - [status-im.components.drawer.view :refer [drawer-view]] + [status-im.components.styles :as styles] + [status-im.components.tabs.styles :as tabs.styles] + [status-im.components.tabs.views :as tabs] + [status-im.i18n :as i18n] [status-im.ui.screens.chats-list.views :refer [chats-list]] - [status-im.ui.screens.discover.views :refer [discover]] [status-im.ui.screens.contacts.views :refer [contact-groups-list]] - [status-im.ui.screens.wallet.main.views :refer [wallet]] - [status-im.components.tabs.views :refer [tabs]])) + [status-im.ui.screens.discover.views :refer [discover]] + [status-im.ui.screens.wallet.main.views :refer [wallet]]) + (:require-macros [status-im.utils.views :as views])) -(def tab-list - [{:view-id :wallet - :title (i18n/label :t/wallet) - :screen wallet - :icon-inactive :icons/wallet - :icon-active :icons/wallet-active} - {:view-id :chat-list - :title (i18n/label :t/chats) - :screen chats-list - :icon-inactive :icons/chats - :icon-active :icons/chats-active} - {:view-id :discover - :title (i18n/label :t/discover) - :screen discover - :icon-inactive :icons/discover - :icon-active :icons/discover-active} - {:view-id :contact-list - :title (i18n/label :t/contacts) - :screen contact-groups-list - :icon-inactive :icons/contacts - :icon-active :icons/contacts-active}]) +(defn- tab-content [{:keys [title icon-active icon-inactive]}] + (fn [active?] + [react/view {:style tabs.styles/tab-container} + (let [icon (if active? icon-active icon-inactive)] + [react/view + [vector-icons/icon icon (tabs.styles/tab-icon active?)]]) + [react/view + [react/text {:style (tabs.styles/tab-title active?)} + title]]])) -(def tab->index (reduce #(assoc %1 (:view-id %2) (count %1)) {} tab-list)) +(def tabs-list* + [{:view-id :wallet + :content {:title (i18n/label :t/wallet) + :icon-inactive :icons/wallet + :icon-active :icons/wallet-active} + :screen wallet} + {:view-id :chat-list + :content {:title (i18n/label :t/chats) + :icon-inactive :icons/chats + :icon-active :icons/chats-active} + :screen chats-list} + {:view-id :discover + :content {:title (i18n/label :t/discover) + :icon-inactive :icons/discover + :icon-active :icons/discover-active} + :screen discover} + {:view-id :contact-list + :content {:title (i18n/label :t/contacts) + :icon-inactive :icons/contacts + :icon-active :icons/contacts-active} + :screen contact-groups-list}]) -(def index->tab (clojure.set/map-invert tab->index)) - -(defn get-tab-index [view-id] - (get tab->index view-id 0)) - -(defn scroll-to [prev-view-id view-id] - (let [p (get-tab-index prev-view-id) - n (get-tab-index view-id)] - (- n p))) - -(defonce scrolling? (atom false)) - -(defn on-scroll-end [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 index)] - (when-not (= view-id new-view-id) - (reset! swiped? true) - (re-frame/dispatch [:navigate-to-tab new-view-id]))))) - -(defn start-scrolling-loop - "Loop that synchronizes tabs scrolling to avoid an inconsistent state." - [scroll-start scroll-ended] - (async-macros/go-loop [[swiper to] (async/index - (is (contains? tabs/tab->index :chat-list)) - (is (= 2 (:discover tabs/tab->index)))) -