Simplify tabbar animation
Fixes #11086 Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
parent
2934de9b8c
commit
8adc32a5c9
|
@ -62,6 +62,7 @@
|
||||||
:ease-in (bezier 0.42 0 1 1)
|
:ease-in (bezier 0.42 0 1 1)
|
||||||
:ease-out (bezier 0 0 0.58 1)
|
:ease-out (bezier 0 0 0.58 1)
|
||||||
:ease-in-out (bezier 0.42 0 0.58 1)
|
:ease-in-out (bezier 0.42 0 0.58 1)
|
||||||
|
:cubic (bezier 0.55 0.055 0.675 0.19)
|
||||||
:keyboard (bezier 0.17 0.59 0.4 0.77)})
|
:keyboard (bezier 0.17 0.59 0.4 0.77)})
|
||||||
|
|
||||||
(def springs {:lazy {:damping 50
|
(def springs {:lazy {:damping 50
|
||||||
|
|
|
@ -3,41 +3,24 @@
|
||||||
[quo.gesture-handler :as gesture-handler]
|
[quo.gesture-handler :as gesture-handler]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
|
[cljs-bean.core :refer [bean]]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.animation :as animation]
|
[quo.components.safe-area :as safe-area]
|
||||||
|
[status-im.ui.screens.routing.core :as navigation]
|
||||||
|
[quo.animated :as animated]
|
||||||
|
[quo.react-native :as rn]
|
||||||
[status-im.ui.components.badge :as badge]
|
[status-im.ui.components.badge :as badge]
|
||||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.tabbar.styles :as tabs.styles]
|
[status-im.ui.components.tabbar.styles :as tabs.styles]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(defonce visible-native (animation/create-value 0))
|
|
||||||
(defonce last-to-value (atom 1))
|
|
||||||
|
|
||||||
(defn animate
|
|
||||||
([visible-native duration to]
|
|
||||||
(animate visible-native duration to nil))
|
|
||||||
([visible-native duration to callback]
|
|
||||||
(when (not= to @last-to-value)
|
|
||||||
(reset! last-to-value to)
|
|
||||||
(animation/start
|
|
||||||
(animation/timing visible-native
|
|
||||||
{:toValue to
|
|
||||||
:duration duration
|
|
||||||
:easing (animation/cubic)
|
|
||||||
:useNativeDriver true})
|
|
||||||
callback))))
|
|
||||||
|
|
||||||
(defn main-tab? [view-id]
|
(defn main-tab? [view-id]
|
||||||
(contains?
|
(contains?
|
||||||
#{:home :wallet :open-dapp :my-profile :wallet-onboarding-setup}
|
#{:chat-stack :browser-stack :wallet-stack :profile-stack
|
||||||
|
:home :wallet :open-dapp :my-profile :wallet-onboarding-setup}
|
||||||
view-id))
|
view-id))
|
||||||
|
|
||||||
(defn minimize-bar [route-name]
|
|
||||||
(if (main-tab? route-name)
|
|
||||||
(animate visible-native 150 0)
|
|
||||||
(animate visible-native 150 1)))
|
|
||||||
|
|
||||||
(def tabs-list-data
|
(def tabs-list-data
|
||||||
(->>
|
(->>
|
||||||
[{:nav-stack :chat-stack
|
[{:nav-stack :chat-stack
|
||||||
|
@ -89,45 +72,25 @@
|
||||||
[react/text {:style (tabs.styles/tab-title active?)}
|
[react/text {:style (tabs.styles/tab-title active?)}
|
||||||
label]]]]])))
|
label]]]]])))
|
||||||
|
|
||||||
(defn tabs []
|
(def tabs
|
||||||
(let [listeners (atom [])
|
(reagent/adapt-react-class
|
||||||
keyboard-shown? (reagent/atom false)
|
(fn [props]
|
||||||
keyboard-visible (animation/create-value 0)]
|
(let [{:keys [navigate index route]} (bean props)
|
||||||
(reagent/create-class
|
{:keys [keyboard-shown]
|
||||||
{:component-did-mount
|
:or {keyboard-shown false}} (when platform/android? (rn/use-keyboard))
|
||||||
(fn []
|
{:keys [bottom]} (safe-area/use-safe-area)
|
||||||
(when platform/android?
|
animated-visible (animated/use-timing-transition
|
||||||
(reset!
|
(main-tab? (keyword route))
|
||||||
listeners
|
{:duration 150})
|
||||||
[(.addListener ^js react/keyboard "keyboardDidShow"
|
keyboard-visible (animated/use-timing-transition
|
||||||
(fn []
|
keyboard-shown
|
||||||
(reset! keyboard-shown? true)
|
{:duration 200})]
|
||||||
(reagent/flush)
|
(reagent/as-element
|
||||||
(animation/start
|
[animated/view {:style (tabs.styles/tabs-wrapper keyboard-shown keyboard-visible)
|
||||||
(animation/timing keyboard-visible
|
:pointer-events (if keyboard-shown "none" "auto")}
|
||||||
{:toValue 1
|
[animated/view {:style (tabs.styles/space-handler bottom)
|
||||||
:duration 200}))))
|
|
||||||
(.addListener ^js react/keyboard "keyboardDidHide"
|
|
||||||
(fn []
|
|
||||||
(animation/start
|
|
||||||
(animation/timing keyboard-visible
|
|
||||||
{:toValue 0
|
|
||||||
:duration 200})
|
|
||||||
#(do (reset! keyboard-shown? false)
|
|
||||||
(reagent/flush)))))])))
|
|
||||||
:component-will-unmount
|
|
||||||
(fn []
|
|
||||||
(when (not-empty @listeners)
|
|
||||||
(doseq [^js listener @listeners]
|
|
||||||
(when listener
|
|
||||||
(.remove listener)))))
|
|
||||||
:reagent-render
|
|
||||||
(fn [{:keys [navigate index inset]}]
|
|
||||||
[react/animated-view {:style (tabs.styles/tabs-wrapper @keyboard-shown? keyboard-visible)
|
|
||||||
:pointer-events (if @keyboard-shown? "none" "auto")}
|
|
||||||
[react/animated-view {:style (tabs.styles/space-handler inset)
|
|
||||||
:pointer-events "none"}]
|
:pointer-events "none"}]
|
||||||
[react/animated-view {:style (tabs.styles/animated-container visible-native inset)}
|
[animated/view {:style (tabs.styles/animated-container animated-visible bottom)}
|
||||||
(for [[route-index
|
(for [[route-index
|
||||||
{:keys [nav-stack accessibility-label count-subscription content]}]
|
{:keys [nav-stack accessibility-label count-subscription content]}]
|
||||||
tabs-list-data
|
tabs-list-data
|
||||||
|
@ -142,15 +105,13 @@
|
||||||
:active? (= (str index) (str route-index))
|
:active? (= (str index) (str route-index))
|
||||||
:nav-stack nav-stack}])]
|
:nav-stack nav-stack}])]
|
||||||
[react/view
|
[react/view
|
||||||
{:style (tabs.styles/ios-titles-cover inset)}]])})))
|
{:style (tabs.styles/ios-titles-cover bottom)}]])))))
|
||||||
|
|
||||||
(defn tabbar [props]
|
(defn tabbar [props]
|
||||||
(let [navigate (oget props "navigation" "navigate")
|
(let [navigate (oget props "navigation" "navigate")
|
||||||
index (oget props "state" "index")]
|
state (bean (oget props "state"))
|
||||||
(reagent/as-element
|
index (get state :index)]
|
||||||
[react/safe-area-consumer
|
|
||||||
(fn [insets]
|
|
||||||
(reagent/as-element
|
(reagent/as-element
|
||||||
[tabs {:navigate navigate
|
[tabs {:navigate navigate
|
||||||
:index index
|
:route (navigation/get-active-route-name state)
|
||||||
:inset (oget insets "bottom")}]))])))
|
:index index}])))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(ns status-im.ui.components.tabbar.styles
|
(ns status-im.ui.components.tabbar.styles
|
||||||
(:require [status-im.ui.components.animation :as animation]
|
(:require [quo.animated :as animated]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
|
@ -91,10 +91,7 @@
|
||||||
:right 0
|
:right 0
|
||||||
:height tabs-height
|
:height tabs-height
|
||||||
:bottom inset
|
:bottom inset
|
||||||
:transform [{:translateY
|
:transform [{:translateY (animated/mix visible? tabs-diff 0)}]})
|
||||||
(animation/interpolate visible?
|
|
||||||
{:inputRange [0 1]
|
|
||||||
:outputRange [0 tabs-diff]})}]})
|
|
||||||
|
|
||||||
(defn ios-titles-cover [inset]
|
(defn ios-titles-cover [inset]
|
||||||
{:background-color colors/white
|
{:background-color colors/white
|
||||||
|
@ -111,10 +108,7 @@
|
||||||
:left 0
|
:left 0
|
||||||
:right 0
|
:right 0
|
||||||
:bottom 0
|
:bottom 0
|
||||||
:transform [{:translateY
|
:transform [{:translateY (animated/mix visible 0 tabs-height)}]}
|
||||||
(animation/interpolate visible
|
|
||||||
{:inputRange [0 1]
|
|
||||||
:outputRange [0 tabs-height]})}]}
|
|
||||||
(when keyboard
|
(when keyboard
|
||||||
{:position :absolute})))
|
{:position :absolute})))
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
["@react-navigation/stack" :refer (createStackNavigator TransitionPresets)]
|
["@react-navigation/stack" :refer (createStackNavigator TransitionPresets)]
|
||||||
["@react-navigation/bottom-tabs" :refer (createBottomTabNavigator)]
|
["@react-navigation/bottom-tabs" :refer (createBottomTabNavigator)]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
|
[cljs-bean.core :refer [bean]]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
|
@ -28,6 +29,12 @@
|
||||||
[callback]
|
[callback]
|
||||||
(.removeEventListener BackHandler "hardwareBackPress" callback))
|
(.removeEventListener BackHandler "hardwareBackPress" callback))
|
||||||
|
|
||||||
|
(defn get-active-route-name [{:keys [index routes]}]
|
||||||
|
(let [route (bean (get routes index))]
|
||||||
|
(if-let [inner-state (get route :state)]
|
||||||
|
(get-active-route-name (bean inner-state))
|
||||||
|
(some-> (get route :name) keyword))))
|
||||||
|
|
||||||
(def transition-presets TransitionPresets)
|
(def transition-presets TransitionPresets)
|
||||||
|
|
||||||
(def modal-presentation-ios (merge (js->clj (.-ModalPresentationIOS ^js transition-presets))
|
(def modal-presentation-ios (merge (js->clj (.-ModalPresentationIOS ^js transition-presets))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
(ns status-im.ui.screens.views
|
(ns status-im.ui.screens.views
|
||||||
(:require [status-im.utils.universal-links.core :as utils.universal-links]
|
(:require [status-im.utils.universal-links.core :as utils.universal-links]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
|
[cljs-bean.core :refer [bean]]
|
||||||
[status-im.ui.screens.about-app.views :as about-app]
|
[status-im.ui.screens.about-app.views :as about-app]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.screens.routing.core :as navigation]
|
[status-im.ui.screens.routing.core :as navigation]
|
||||||
|
@ -13,7 +14,6 @@
|
||||||
[status-im.ui.screens.popover.views :as popover]
|
[status-im.ui.screens.popover.views :as popover]
|
||||||
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
|
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
|
||||||
[status-im.ui.screens.wallet.send.views :as wallet]
|
[status-im.ui.screens.wallet.send.views :as wallet]
|
||||||
[status-im.ui.components.tabbar.core :as tabbar]
|
|
||||||
[status-im.ui.components.status-bar.view :as statusbar]
|
[status-im.ui.components.status-bar.view :as statusbar]
|
||||||
status-im.ui.screens.wallet.collectibles.etheremon.views
|
status-im.ui.screens.wallet.collectibles.etheremon.views
|
||||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.views
|
status-im.ui.screens.wallet.collectibles.cryptostrikers.views
|
||||||
|
@ -71,17 +71,8 @@
|
||||||
(reset! state state-obj)
|
(reset! state state-obj)
|
||||||
(resolve true)))))
|
(resolve true)))))
|
||||||
|
|
||||||
(defn get-active-route-name [state]
|
|
||||||
(let [index (get state "index")
|
|
||||||
route (get-in state ["routes" index])]
|
|
||||||
(if-let [state' (get route "state")]
|
|
||||||
(get-active-route-name state')
|
|
||||||
(some-> (get route "name") keyword))))
|
|
||||||
|
|
||||||
(defn on-state-change [state]
|
(defn on-state-change [state]
|
||||||
(let [route-name (get-active-route-name (js->clj state))]
|
(let [route-name (navigation/get-active-route-name (bean state))]
|
||||||
(tabbar/minimize-bar route-name)
|
|
||||||
|
|
||||||
;; NOTE(Ferossgp): Keycard did-load events backward compatibility
|
;; NOTE(Ferossgp): Keycard did-load events backward compatibility
|
||||||
(re-frame/dispatch [:screens/on-will-focus route-name])
|
(re-frame/dispatch [:screens/on-will-focus route-name])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue