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

View File

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

View File

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

View File

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

View File

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