From 120b59940d94122499d0d49369123faa37366f70 Mon Sep 17 00:00:00 2001 From: Gheorghe Pinzaru Date: Fri, 21 Aug 2020 11:56:50 +0300 Subject: [PATCH] Simplify tabbar animation Fixes #11086 --- src/quo/animated.cljs | 1 + src/status_im/ui/components/tabbar/core.cljs | 103 ++++++------------ .../ui/components/tabbar/styles.cljs | 14 +-- src/status_im/ui/screens/routing/core.cljs | 7 ++ src/status_im/ui/screens/views.cljs | 13 +-- 5 files changed, 46 insertions(+), 92 deletions(-) diff --git a/src/quo/animated.cljs b/src/quo/animated.cljs index d8b2c3ede8e..4c17b130b82 100644 --- a/src/quo/animated.cljs +++ b/src/quo/animated.cljs @@ -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 diff --git a/src/status_im/ui/components/tabbar/core.cljs b/src/status_im/ui/components/tabbar/core.cljs index 60bfd534928..3ce68aac92a 100644 --- a/src/status_im/ui/components/tabbar/core.cljs +++ b/src/status_im/ui/components/tabbar/core.cljs @@ -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}]))) diff --git a/src/status_im/ui/components/tabbar/styles.cljs b/src/status_im/ui/components/tabbar/styles.cljs index ada66b9dfb2..196c71968ab 100644 --- a/src/status_im/ui/components/tabbar/styles.cljs +++ b/src/status_im/ui/components/tabbar/styles.cljs @@ -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}))) diff --git a/src/status_im/ui/screens/routing/core.cljs b/src/status_im/ui/screens/routing/core.cljs index c06c7ff1779..412dd869995 100644 --- a/src/status_im/ui/screens/routing/core.cljs +++ b/src/status_im/ui/screens/routing/core.cljs @@ -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)) diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index af768e1b771..95e8f1f90c4 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -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])