Simplify tabbar animation

Fixes #11086

Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
Gheorghe Pinzaru 2020-08-21 11:56:50 +03:00
parent 2934de9b8c
commit 8adc32a5c9
No known key found for this signature in database
GPG Key ID: C9A094959935A952
5 changed files with 46 additions and 92 deletions

View File

@ -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

View File

@ -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)
:pointer-events "none"}]
[react/animated-view {:style (tabs.styles/animated-container visible-native 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"}]
[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")]
state (bean (oget props "state"))
index (get state :index)]
(reagent/as-element
[react/safe-area-consumer
(fn [insets]
(reagent/as-element
[tabs {:navigate navigate
:index index
:inset (oget insets "bottom")}]))])))
[tabs {:navigate navigate
:route (navigation/get-active-route-name state)
:index index}])))

View File

@ -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]))
@ -84,17 +84,14 @@
:shadow-color (if (colors/dark?)
"rgba(0, 0, 0, 0.75)"
"rgba(0, 9, 26, 0.12)")
:elevation 8
:elevation 8
:background-color colors/white
:position :absolute
:left 0
: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})))

View File

@ -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))

View File

@ -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])