new bottom tab (react-navigation)
This commit is contained in:
parent
0fe4ac516f
commit
b8d4f2911b
|
@ -254,7 +254,7 @@
|
|||
{:db (assoc-in db [:accounts/login :password] password)}
|
||||
(navigation/navigate-to-cofx :progress nil)
|
||||
(user-login false))
|
||||
(navigation/navigate-to-clean cofx :login nil)))
|
||||
(navigation/navigate-to-cofx cofx :login nil)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:accounts.login/login
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.models.transactions :as transactions]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs-styles]))
|
||||
|
||||
(re-frame/reg-sub ::chats :chats)
|
||||
(re-frame/reg-sub ::access-scope->command-id :access-scope->command-id)
|
||||
|
@ -75,8 +76,11 @@
|
|||
:<- [:get :keyboard-height]
|
||||
(fn [kb-height]
|
||||
(cond
|
||||
(and platform/iphone-x? (> kb-height 0)) (- kb-height 34)
|
||||
platform/ios? kb-height
|
||||
(and platform/iphone-x? (> kb-height 0))
|
||||
(- kb-height 34 tabs-styles/tabs-height)
|
||||
platform/ios? (- kb-height (if (> kb-height 0)
|
||||
tabs-styles/tabs-height
|
||||
0))
|
||||
:default 0)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
(ns status-im.ui.components.bottom-bar.core
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.styles :as common.styles]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defn animate
|
||||
([visible duration to]
|
||||
(animate visible duration to nil))
|
||||
([visible duration to callback]
|
||||
(animation/start
|
||||
(animation/timing visible
|
||||
{:toValue to
|
||||
:duration duration
|
||||
:useNativeDriver true})
|
||||
callback)))
|
||||
|
||||
(def tabs-list-data
|
||||
[{:view-id :chat-stack
|
||||
:content {:title (i18n/label :t/home)
|
||||
:icon :main-icons/home}
|
||||
:count-subscription :chats/unread-messages-number
|
||||
:accessibility-label :home-tab-button}
|
||||
{:view-id :wallet-stack
|
||||
:content {:title (i18n/label :t/wallet)
|
||||
:icon :main-icons/wallet}
|
||||
:count-subscription :get-wallet-unread-messages-number
|
||||
:accessibility-label :wallet-tab-button}
|
||||
{:view-id :profile-stack
|
||||
:content {:title (i18n/label :t/profile)
|
||||
:icon :main-icons/profile}
|
||||
:count-subscription :get-profile-unread-messages-number
|
||||
:accessibility-label :profile-tab-button}])
|
||||
|
||||
(defn- tab-content [{:keys [title icon]}]
|
||||
(fn [active? count]
|
||||
[react/view {:style tabs.styles/tab-container}
|
||||
[react/view
|
||||
[vector-icons/icon icon (tabs.styles/tab-icon active?)]]
|
||||
[react/view
|
||||
[react/text {:style (tabs.styles/tab-title active?)}
|
||||
title]]
|
||||
(when (pos? count)
|
||||
[react/view tabs.styles/counter-container
|
||||
[react/view tabs.styles/counter
|
||||
[components.common/counter count]]])]))
|
||||
|
||||
(def tabs-list (map #(update % :content tab-content) tabs-list-data))
|
||||
|
||||
(views/defview tab [view-id content active? accessibility-label count-subscription]
|
||||
(views/letsubs [count [count-subscription]]
|
||||
[react/touchable-highlight
|
||||
(cond-> {:style common.styles/flex
|
||||
:disabled active?
|
||||
:on-press #(re-frame/dispatch [:navigate-to-tab view-id])}
|
||||
accessibility-label
|
||||
(assoc :accessibility-label accessibility-label))
|
||||
[react/view
|
||||
[content active? count]]]))
|
||||
|
||||
(defn tabs [current-view-id]
|
||||
[react/view {:style tabs.styles/tabs-container}
|
||||
(for [{:keys [content view-id accessibility-label count-subscription]} tabs-list]
|
||||
^{:key view-id} [tab view-id content (= view-id current-view-id) accessibility-label count-subscription])])
|
||||
|
||||
(defn tabs-animation-wrapper [visible? keyboard-shown? tab]
|
||||
[react/animated-view
|
||||
{:style {:height tabs.styles/tabs-height
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0
|
||||
:position (when keyboard-shown? :absolute)
|
||||
:transform [{:translateY
|
||||
(animation/interpolate
|
||||
visible?
|
||||
{:inputRange [0 1]
|
||||
:outputRange [tabs.styles/tabs-height
|
||||
0]})}]}}
|
||||
[react/safe-area-view [tabs tab]]])
|
||||
|
||||
(def disappearance-duration 150)
|
||||
(def appearance-duration 100)
|
||||
|
||||
(defn bottom-bar [_]
|
||||
(let [keyboard-shown? (reagent/atom false)
|
||||
visible? (animation/create-value 1)
|
||||
listeners (atom [])]
|
||||
(reagent/create-class
|
||||
{:component-will-mount
|
||||
(fn []
|
||||
(when platform/android?
|
||||
(reset!
|
||||
listeners
|
||||
[(.addListener react/keyboard "keyboardDidShow"
|
||||
(fn []
|
||||
(reset! keyboard-shown? true)
|
||||
(animate visible?
|
||||
disappearance-duration 0)))
|
||||
(.addListener react/keyboard "keyboardDidHide"
|
||||
(fn []
|
||||
(reset! keyboard-shown? false)
|
||||
(animate visible? appearance-duration 1)))])))
|
||||
:component-will-unmount
|
||||
(fn []
|
||||
(when (not-empty @listeners)
|
||||
(doseq [listener @listeners]
|
||||
(when listener
|
||||
(.remove listener)))))
|
||||
:reagent-render
|
||||
(fn [args]
|
||||
(let [idx (.. (:navigation args)
|
||||
-state
|
||||
-index)
|
||||
tab (case idx
|
||||
0 :chat-stack
|
||||
1 :wallet-stack
|
||||
2 :profile-stack
|
||||
:chat-stack)]
|
||||
(if platform/ios?
|
||||
[react/safe-area-view [tabs tab]]
|
||||
[tabs-animation-wrapper visible? @keyboard-shown? tab])))})))
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.ui.screens.main-tabs.styles
|
||||
(:require [status-im.ui.components.styles :as styles]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
(ns status-im.ui.components.bottom-bar.styles
|
||||
(:require [status-im.ui.components.colors :as colors]
|
||||
[status-im.utils.platform :as platform])
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle]]))
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
[taoensso.timbre :as log]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.main-tabs.styles :as tabs.styles])
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
;;TODO copy-pate with minimum modifications of status-react tabs
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.main-tabs.styles :as main-tabs.styles]
|
||||
[status-im.ui.components.bottom-bar.styles :as main-tabs.styles]
|
||||
[status-im.ui.components.styles :as components.styles]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.platform :as utils.platform]
|
||||
|
|
|
@ -1,84 +1,26 @@
|
|||
(ns status-im.ui.screens.main-tabs.views
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [status-im.i18n :as i18n]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.react :as react]
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.status-bar.view :as status-bar.view]
|
||||
[status-im.ui.components.styles :as common.styles]
|
||||
[status-im.ui.screens.home.views :as home]
|
||||
[status-im.ui.screens.wallet.main.views :as wallet.main]
|
||||
[status-im.ui.screens.main-tabs.styles :as styles]
|
||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||
[status-im.ui.components.common.common :as components.common]))
|
||||
|
||||
(def tabs-list-data
|
||||
[{:view-id :home
|
||||
:content {:title (i18n/label :t/home)
|
||||
:icon :main-icons/home}
|
||||
:count-subscription :chats/unread-messages-number
|
||||
:accessibility-label :home-tab-button}
|
||||
{:view-id :wallet
|
||||
:content {:title (i18n/label :t/wallet)
|
||||
:icon :main-icons/wallet}
|
||||
:count-subscription :get-wallet-unread-messages-number
|
||||
:accessibility-label :wallet-tab-button}
|
||||
{:view-id :my-profile
|
||||
:content {:title (i18n/label :t/profile)
|
||||
:icon :main-icons/profile}
|
||||
:count-subscription :get-profile-unread-messages-number
|
||||
:accessibility-label :profile-tab-button}])
|
||||
|
||||
(defn- tab-content [{:keys [title icon]}]
|
||||
(fn [active? count]
|
||||
[react/view {:style styles/tab-container}
|
||||
[react/view
|
||||
[vector-icons/icon icon (styles/tab-icon active?)]]
|
||||
[react/view
|
||||
[react/text {:style (styles/tab-title active?)}
|
||||
title]]
|
||||
(when (pos? count)
|
||||
[react/view styles/counter-container
|
||||
[react/view styles/counter
|
||||
[components.common/counter count]]])]))
|
||||
|
||||
(def tabs-list (map #(update % :content tab-content) tabs-list-data))
|
||||
|
||||
(views/defview tab [view-id content active? accessibility-label count-subscription]
|
||||
(views/letsubs [count [count-subscription]]
|
||||
[react/touchable-highlight
|
||||
(cond-> {:style common.styles/flex
|
||||
:disabled active?
|
||||
:on-press #(re-frame/dispatch [:navigate-to-tab view-id])}
|
||||
accessibility-label
|
||||
(assoc :accessibility-label accessibility-label))
|
||||
[react/view
|
||||
[content active? count]]]))
|
||||
|
||||
(defn tabs [current-view-id]
|
||||
[react/view {:style styles/tabs-container}
|
||||
(for [{:keys [content view-id accessibility-label count-subscription]} tabs-list]
|
||||
^{:key view-id} [tab view-id content (= view-id current-view-id) accessibility-label count-subscription])])
|
||||
[status-im.ui.screens.profile.user.views :as profile.user]))
|
||||
|
||||
(views/defview main-container [view-id]
|
||||
(views/letsubs
|
||||
[tab-bar-visible? [:tab-bar-visible?]]
|
||||
;; :should-component-update is called only when props are changed,
|
||||
;; that's why view-id is passed as a prop here. main-tabs component will be
|
||||
;; rendered while next screen from stack navigator is shown, so we have
|
||||
;; to prevent re-rendering to avoid no clause exception in case form
|
||||
{:should-component-update
|
||||
(fn [_ _ [_ new-view-id]]
|
||||
(contains? #{:home :wallet :my-profile} new-view-id))}
|
||||
[react/view common.styles/main-container
|
||||
(case view-id
|
||||
:home [home/home-wrapper]
|
||||
:wallet [wallet.main/wallet]
|
||||
:my-profile [profile.user/my-profile]
|
||||
nil)
|
||||
|
||||
(when tab-bar-visible?
|
||||
[tabs view-id])]))
|
||||
;; :should-component-update is called only when props are changed,
|
||||
;; that's why view-id is passed as a prop here. main-tabs component will be
|
||||
;; rendered while next screen from stack navigator is shown, so we have
|
||||
;; to prevent re-rendering to avoid no clause exception in case form
|
||||
{:should-component-update
|
||||
(fn [_ _ [_ new-view-id]]
|
||||
(contains? #{:home :wallet :my-profile} new-view-id))}
|
||||
[react/view common.styles/main-container
|
||||
(case view-id
|
||||
:home [home/home-wrapper]
|
||||
:wallet [wallet.main/wallet]
|
||||
:my-profile [profile.user/my-profile]
|
||||
nil)])
|
||||
|
||||
(defn main-tabs [view-id]
|
||||
[react/view common.styles/flex
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.ui.screens.main-tabs.styles :as main-tabs.styles]
|
||||
[status-im.ui.components.bottom-bar.styles :as main-tabs.styles]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
[status-im.ui.screens.home.styles :as home.styles]
|
||||
|
|
|
@ -2,46 +2,44 @@
|
|||
(:require [status-im.utils.config :as config]))
|
||||
|
||||
(def chat-stack
|
||||
{:name :chat-stack
|
||||
:screens [{:name :chat-main-stack
|
||||
:screens (cond->
|
||||
[:home
|
||||
:chat
|
||||
:profile
|
||||
:new
|
||||
:new-chat
|
||||
:qr-scanner
|
||||
:take-picture
|
||||
:new-group
|
||||
:add-participants-toggle-list
|
||||
:contact-toggle-list
|
||||
:group-chat-profile
|
||||
:new-public-chat
|
||||
:open-dapp
|
||||
:dapp-description
|
||||
:browser
|
||||
:stickers
|
||||
:stickers-pack
|
||||
:login]
|
||||
|
||||
config/hardwallet-enabled?
|
||||
(concat [:hardwallet-connect :enter-pin]))
|
||||
:config {:initialRouteName :home}}
|
||||
:wallet-modal
|
||||
:chat-modal
|
||||
:show-extension-modal
|
||||
:stickers-pack-modal
|
||||
{:name :wallet-send-modal-stack
|
||||
:screens [:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-send-transaction-modal}}
|
||||
{:name :wallet-send-modal-stack-with-onboarding
|
||||
:screens [:wallet-onboarding-setup-modal
|
||||
:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-onboarding-setup-modal}}
|
||||
:wallet-sign-message-modal]
|
||||
:config {:mode :modal
|
||||
:initialRouteName :chat-main-stack}})
|
||||
{:name :chat-stack
|
||||
:screens [{:name :chat-main-stack
|
||||
:screens (cond->
|
||||
[:home
|
||||
:chat
|
||||
:profile
|
||||
:new
|
||||
:new-chat
|
||||
:qr-scanner
|
||||
:take-picture
|
||||
:new-group
|
||||
:add-participants-toggle-list
|
||||
:contact-toggle-list
|
||||
:group-chat-profile
|
||||
:new-public-chat
|
||||
:open-dapp
|
||||
:dapp-description
|
||||
:browser
|
||||
:stickers
|
||||
:stickers-pack]
|
||||
config/hardwallet-enabled?
|
||||
(concat [:hardwallet-connect :enter-pin]))
|
||||
:config {:initialRouteName :home}}
|
||||
:wallet-modal
|
||||
:chat-modal
|
||||
:show-extension-modal
|
||||
:stickers-pack-modal
|
||||
{:name :wallet-send-modal-stack
|
||||
:screens [:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-send-transaction-modal}}
|
||||
{:name :wallet-send-modal-stack-with-onboarding
|
||||
:screens [:wallet-onboarding-setup-modal
|
||||
:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-onboarding-setup-modal}}
|
||||
:wallet-sign-message-modal]
|
||||
:config {:mode :modal
|
||||
:initialRouteName :chat-main-stack}})
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[status-im.ui.screens.routing.intro-login-stack :as intro-login-stack]
|
||||
[status-im.ui.screens.routing.chat-stack :as chat-stack]
|
||||
[status-im.ui.screens.routing.wallet-stack :as wallet-stack]
|
||||
[status-im.ui.screens.routing.profile-stack :as profile-stack]))
|
||||
[status-im.ui.screens.routing.profile-stack :as profile-stack]
|
||||
[status-im.ui.components.bottom-bar.core :as bottom-bar]))
|
||||
|
||||
(defn wrap [view-id component]
|
||||
"Wraps screen with main view and adds navigation-events component"
|
||||
|
@ -65,6 +66,11 @@
|
|||
routes
|
||||
(prepare-config config)))
|
||||
|
||||
(defn tab-navigator [routes config]
|
||||
(nav-reagent/tab-navigator
|
||||
routes
|
||||
(prepare-config config)))
|
||||
|
||||
(declare stack-screens)
|
||||
|
||||
(defn build-screen [screen]
|
||||
|
@ -93,7 +99,10 @@
|
|||
|
||||
:else
|
||||
(nav-reagent/stack-screen (wrap screen-name screen-config)))]
|
||||
[screen-name {:screen res}])))
|
||||
[screen-name (cond-> {:screen res}
|
||||
(:navigation screen-config)
|
||||
(assoc :navigationOptions
|
||||
(:navigation screen-config)))])))
|
||||
|
||||
(defn stack-screens [screens-map]
|
||||
(->> screens-map
|
||||
|
@ -103,10 +112,15 @@
|
|||
(defn get-main-component [view-id]
|
||||
(log/debug :component view-id)
|
||||
(switch-navigator
|
||||
(->> [(intro-login-stack/intro-login-stack view-id)
|
||||
chat-stack/chat-stack
|
||||
wallet-stack/wallet-stack
|
||||
profile-stack/profile-stack]
|
||||
(map build-screen)
|
||||
(into {}))
|
||||
(into {}
|
||||
[(build-screen (intro-login-stack/intro-login-stack view-id))
|
||||
[:tabs
|
||||
{:screen (tab-navigator
|
||||
(->> [(build-screen chat-stack/chat-stack)
|
||||
(build-screen wallet-stack/wallet-stack)
|
||||
(build-screen profile-stack/profile-stack)]
|
||||
(into {}))
|
||||
{:initialRouteName :chat-stack
|
||||
:tabBarComponent (reagent.core/reactify-component
|
||||
bottom-bar/bottom-bar)})}]])
|
||||
{:initialRouteName :intro-login-stack}))
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
:enter-pin
|
||||
:hardwallet-setup
|
||||
:hardwallet-success]))
|
||||
:config (when
|
||||
:config (if
|
||||
;; add view-id here if you'd like that view to be
|
||||
;; first view when app is started
|
||||
(#{:intro :login :progress :accounts} view-id)
|
||||
{:initialRouteName view-id})})
|
||||
{:initialRouteName view-id}
|
||||
{:initialRouteName :login})})
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
:fleet-settings
|
||||
:currency-settings
|
||||
:backup-seed
|
||||
:login
|
||||
:create-account
|
||||
:recover
|
||||
:accounts
|
||||
:qr-scanner]
|
||||
|
||||
config/hardwallet-enabled?
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
:unsigned-transactions
|
||||
:transactions-history
|
||||
:wallet-transaction-details
|
||||
:login
|
||||
:wallet-settings-hook]
|
||||
:config {:initialRouteName :wallet}}
|
||||
:selection-modal-screen
|
||||
|
|
|
@ -11,6 +11,13 @@
|
|||
(re-frame/dispatch [:update-wallet])
|
||||
(assoc-in db [:wallet :current-tab] 0))
|
||||
|
||||
(defmethod navigation/preload-data! :wallet-stack
|
||||
[db _]
|
||||
;;TODO(goranjovic) - get rid of this preload hook completely
|
||||
(re-frame/dispatch [:wallet.ui/pull-to-refresh])
|
||||
(re-frame/dispatch [:update-wallet])
|
||||
(assoc-in db [:wallet :current-tab] 0))
|
||||
|
||||
(defmethod navigation/preload-data! :wallet-modal
|
||||
[db _]
|
||||
;;TODO(goranjovic) - get rid of this preload hook completely
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.ui.screens.wallet.transactions.styles
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle defstyle]])
|
||||
(:require [status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.screens.main-tabs.styles :as tabs.styles]))
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]))
|
||||
|
||||
(defnstyle tab [active?]
|
||||
{:flex 1
|
||||
|
|
|
@ -174,11 +174,11 @@ class TestChatManagementMultipleDevice(MultipleDeviceTestCase):
|
|||
username = chat_element.username.text
|
||||
chat_element.member_photo.click()
|
||||
for element in [chat_1.contact_profile_picture,
|
||||
chat_1.element_by_text(username, 'text'),
|
||||
chat_1.add_to_contacts,
|
||||
chat_1.profile_send_message,
|
||||
chat_1.profile_send_transaction,
|
||||
chat_1.profile_address_text,
|
||||
chat_1.element_by_text(username, 'text')]:
|
||||
chat_1.profile_address_text]:
|
||||
if not element.scroll_to_element():
|
||||
self.errors.append('%s is not visible' % element.name)
|
||||
chat_1.add_to_contacts.click()
|
||||
|
|
|
@ -25,7 +25,7 @@ class TestCommandsMultipleDevices(MultipleDeviceTestCase):
|
|||
|
||||
device_1_wallet_view = device_1_home.wallet_button.click()
|
||||
device_1_wallet_view.set_up_wallet()
|
||||
device_1_wallet_view.get_back_to_home_view()
|
||||
device_1_wallet_view.home_button.click()
|
||||
|
||||
public_key = device_2_home.get_public_key()
|
||||
device_2_profile = device_2_home.get_profile_view()
|
||||
|
|
|
@ -472,7 +472,8 @@ class BaseView(object):
|
|||
|
||||
def get_back_to_home_view(self):
|
||||
counter = 0
|
||||
while not self.home_button.is_element_displayed(2):
|
||||
from views.home_view import PlusButton
|
||||
while not PlusButton(self.driver).is_element_displayed(2):
|
||||
try:
|
||||
if counter >= 5:
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue