mirror of
https://github.com/status-im/status-react.git
synced 2025-01-11 03:26:31 +00:00
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-out (bezier 0 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)})
|
||||
|
||||
(def springs {:lazy {:damping 50
|
||||
|
@ -3,41 +3,24 @@
|
||||
[quo.gesture-handler :as gesture-handler]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[cljs-bean.core :refer [bean]]
|
||||
[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.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.tabbar.styles :as tabs.styles]
|
||||
[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]
|
||||
(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))
|
||||
|
||||
(defn minimize-bar [route-name]
|
||||
(if (main-tab? route-name)
|
||||
(animate visible-native 150 0)
|
||||
(animate visible-native 150 1)))
|
||||
|
||||
(def tabs-list-data
|
||||
(->>
|
||||
[{:nav-stack :chat-stack
|
||||
@ -89,45 +72,25 @@
|
||||
[react/text {:style (tabs.styles/tab-title active?)}
|
||||
label]]]]])))
|
||||
|
||||
(defn tabs []
|
||||
(let [listeners (atom [])
|
||||
keyboard-shown? (reagent/atom false)
|
||||
keyboard-visible (animation/create-value 0)]
|
||||
(reagent/create-class
|
||||
{:component-did-mount
|
||||
(fn []
|
||||
(when platform/android?
|
||||
(reset!
|
||||
listeners
|
||||
[(.addListener ^js react/keyboard "keyboardDidShow"
|
||||
(fn []
|
||||
(reset! keyboard-shown? true)
|
||||
(reagent/flush)
|
||||
(animation/start
|
||||
(animation/timing keyboard-visible
|
||||
{:toValue 1
|
||||
: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)
|
||||
(def tabs
|
||||
(reagent/adapt-react-class
|
||||
(fn [props]
|
||||
(let [{:keys [navigate index route]} (bean props)
|
||||
{:keys [keyboard-shown]
|
||||
:or {keyboard-shown false}} (when platform/android? (rn/use-keyboard))
|
||||
{:keys [bottom]} (safe-area/use-safe-area)
|
||||
animated-visible (animated/use-timing-transition
|
||||
(main-tab? (keyword route))
|
||||
{:duration 150})
|
||||
keyboard-visible (animated/use-timing-transition
|
||||
keyboard-shown
|
||||
{:duration 200})]
|
||||
(reagent/as-element
|
||||
[animated/view {:style (tabs.styles/tabs-wrapper keyboard-shown keyboard-visible)
|
||||
:pointer-events (if keyboard-shown "none" "auto")}
|
||||
[animated/view {:style (tabs.styles/space-handler bottom)
|
||||
: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
|
||||
{:keys [nav-stack accessibility-label count-subscription content]}]
|
||||
tabs-list-data
|
||||
@ -142,15 +105,13 @@
|
||||
:active? (= (str index) (str route-index))
|
||||
:nav-stack nav-stack}])]
|
||||
[react/view
|
||||
{:style (tabs.styles/ios-titles-cover inset)}]])})))
|
||||
{:style (tabs.styles/ios-titles-cover bottom)}]])))))
|
||||
|
||||
(defn tabbar [props]
|
||||
(let [navigate (oget props "navigation" "navigate")
|
||||
index (oget props "state" "index")]
|
||||
(reagent/as-element
|
||||
[react/safe-area-consumer
|
||||
(fn [insets]
|
||||
state (bean (oget props "state"))
|
||||
index (get state :index)]
|
||||
(reagent/as-element
|
||||
[tabs {:navigate navigate
|
||||
:index index
|
||||
:inset (oget insets "bottom")}]))])))
|
||||
:route (navigation/get-active-route-name state)
|
||||
:index index}])))
|
||||
|
@ -1,5 +1,5 @@
|
||||
(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.utils.platform :as platform]))
|
||||
|
||||
@ -91,10 +91,7 @@
|
||||
:right 0
|
||||
:height tabs-height
|
||||
:bottom inset
|
||||
:transform [{:translateY
|
||||
(animation/interpolate visible?
|
||||
{:inputRange [0 1]
|
||||
:outputRange [0 tabs-diff]})}]})
|
||||
:transform [{:translateY (animated/mix visible? tabs-diff 0)}]})
|
||||
|
||||
(defn ios-titles-cover [inset]
|
||||
{:background-color colors/white
|
||||
@ -111,10 +108,7 @@
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:transform [{:translateY
|
||||
(animation/interpolate visible
|
||||
{:inputRange [0 1]
|
||||
:outputRange [0 tabs-height]})}]}
|
||||
:transform [{:translateY (animated/mix visible 0 tabs-height)}]}
|
||||
(when keyboard
|
||||
{:position :absolute})))
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
["@react-navigation/stack" :refer (createStackNavigator TransitionPresets)]
|
||||
["@react-navigation/bottom-tabs" :refer (createBottomTabNavigator)]
|
||||
[reagent.core :as reagent]
|
||||
[cljs-bean.core :refer [bean]]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
@ -28,6 +29,12 @@
|
||||
[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 modal-presentation-ios (merge (js->clj (.-ModalPresentationIOS ^js transition-presets))
|
||||
|
@ -1,6 +1,7 @@
|
||||
(ns status-im.ui.screens.views
|
||||
(:require [status-im.utils.universal-links.core :as utils.universal-links]
|
||||
[re-frame.core :as re-frame]
|
||||
[cljs-bean.core :refer [bean]]
|
||||
[status-im.ui.screens.about-app.views :as about-app]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.routing.core :as navigation]
|
||||
@ -13,7 +14,6 @@
|
||||
[status-im.ui.screens.popover.views :as popover]
|
||||
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
|
||||
[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.screens.wallet.collectibles.etheremon.views
|
||||
status-im.ui.screens.wallet.collectibles.cryptostrikers.views
|
||||
@ -71,17 +71,8 @@
|
||||
(reset! state state-obj)
|
||||
(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]
|
||||
(let [route-name (get-active-route-name (js->clj state))]
|
||||
(tabbar/minimize-bar route-name)
|
||||
|
||||
(let [route-name (navigation/get-active-route-name (bean state))]
|
||||
;; NOTE(Ferossgp): Keycard did-load events backward compatibility
|
||||
(re-frame/dispatch [:screens/on-will-focus route-name])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user