Bottom tab animation on leaving/entering main tabs
This commit is contained in:
parent
de5c23d39f
commit
a30c379a87
|
@ -38,7 +38,7 @@
|
|||
"keyboardDidHide"
|
||||
(fn [_]
|
||||
(dispatch [:show-tab-bar])
|
||||
(when (zero? @keyboard-height)
|
||||
(when-not (zero? @keyboard-height)
|
||||
(dispatch [:set :keyboard-height 0]))))
|
||||
(.hide react/splash-screen)
|
||||
(.addEventListener react/app-state "change" app-state-change-handler)
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
[status-im.chat.db :as chat.db]
|
||||
[status-im.models.transactions :as transactions]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs-styles]))
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs-styles]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]))
|
||||
|
||||
(re-frame/reg-sub ::chats :chats)
|
||||
(re-frame/reg-sub ::access-scope->command-id :access-scope->command-id)
|
||||
|
@ -77,10 +78,13 @@
|
|||
(fn [kb-height]
|
||||
(cond
|
||||
(and platform/iphone-x? (> kb-height 0))
|
||||
(- kb-height 34 tabs-styles/tabs-height)
|
||||
platform/ios? (- kb-height (if (> kb-height 0)
|
||||
tabs-styles/tabs-height
|
||||
0))
|
||||
(- kb-height (* 2 tabs.styles/minimized-tabs-height))
|
||||
|
||||
platform/ios?
|
||||
(+ kb-height (- (if (> kb-height 0)
|
||||
tabs.styles/minimized-tabs-height
|
||||
0)))
|
||||
|
||||
:default 0)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
|
|
@ -57,3 +57,5 @@
|
|||
(js->clj (.getLayout value-xy)))
|
||||
|
||||
(defn easing [] js/ReactNative.Easing)
|
||||
|
||||
(defn cubic [] (.-cubic (easing)))
|
||||
|
|
|
@ -10,16 +10,22 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
(defonce visible? (animation/create-value 1))
|
||||
(defonce last-to-value (atom 1))
|
||||
|
||||
(defn animate
|
||||
([visible duration to]
|
||||
(animate visible duration to nil))
|
||||
([visible duration to callback]
|
||||
(when (not= to @last-to-value)
|
||||
(reset! last-to-value to)
|
||||
(animation/start
|
||||
(animation/timing visible
|
||||
{:toValue to
|
||||
:duration duration
|
||||
:easing (animation/cubic)
|
||||
:useNativeDriver true})
|
||||
callback)))
|
||||
callback))))
|
||||
|
||||
(def tabs-list-data
|
||||
[{:nav-stack :chat-stack
|
||||
|
@ -80,17 +86,64 @@
|
|||
:active? (= current-view-id nav-stack)
|
||||
:nav-stack nav-stack}])]])
|
||||
|
||||
(defn tabs-animation-wrapper [visible? keyboard-shown? tab]
|
||||
(defn main-tab? [view-id]
|
||||
(contains?
|
||||
#{:home :wallet :dapps :my-profile :wallet-onboarding-setup}
|
||||
view-id))
|
||||
|
||||
(defn minimize-bar [view-id]
|
||||
(if (main-tab? view-id)
|
||||
(animate visible? 150 1)
|
||||
(animate visible? 150 tabs.styles/minimized-tab-ratio)))
|
||||
|
||||
(defn tabs-animation-wrapper-ios
|
||||
[content]
|
||||
[react/view
|
||||
[react/view
|
||||
{:style tabs.styles/title-cover-wrapper}
|
||||
content
|
||||
(when platform/iphone-x?
|
||||
[react/view
|
||||
{:style tabs.styles/ios-titles-cover}])]
|
||||
[react/safe-area-view {:flex 1}]])
|
||||
|
||||
(defn tabs-animation-wrapper-android
|
||||
[keyboard-shown? view-id content]
|
||||
[react/view
|
||||
{:style (tabs.styles/animation-wrapper
|
||||
keyboard-shown?
|
||||
(main-tab? view-id))}
|
||||
[react/view
|
||||
{:style tabs.styles/title-cover-wrapper}
|
||||
content]])
|
||||
|
||||
(defn tabs-animation-wrapper [keyboard-shown? view-id tab]
|
||||
(reagent.core/create-class
|
||||
{:component-will-update
|
||||
(fn [this new-params]
|
||||
(let [old-view-id (get (.-argv (.-props this)) 2)
|
||||
new-view-id (get new-params 2)]
|
||||
(when (not= new-view-id old-view-id)
|
||||
(minimize-bar new-view-id))))
|
||||
:reagent-render
|
||||
(fn [keyboard-shown? view-id tab]
|
||||
(if platform/ios?
|
||||
[tabs-animation-wrapper-ios
|
||||
[react/animated-view
|
||||
{:style (tabs.styles/animated-container visible? keyboard-shown?)}
|
||||
[react/safe-area-view [tabs tab]]])
|
||||
[tabs tab]]]
|
||||
[tabs-animation-wrapper-android
|
||||
keyboard-shown?
|
||||
view-id
|
||||
[react/animated-view
|
||||
{:style (tabs.styles/animated-container visible? keyboard-shown?)}
|
||||
[tabs tab]]]))}))
|
||||
|
||||
(def disappearance-duration 150)
|
||||
(def appearance-duration 100)
|
||||
|
||||
(defn bottom-bar [_]
|
||||
(defn bottom-bar [_ view-id]
|
||||
(let [keyboard-shown? (reagent/atom false)
|
||||
visible? (animation/create-value 1)
|
||||
listeners (atom [])]
|
||||
(reagent/create-class
|
||||
{:component-will-mount
|
||||
|
@ -106,7 +159,10 @@
|
|||
(.addListener react/keyboard "keyboardDidHide"
|
||||
(fn []
|
||||
(reset! keyboard-shown? false)
|
||||
(animate visible? appearance-duration 1)))])))
|
||||
(animate visible? appearance-duration
|
||||
(if (main-tab? @view-id)
|
||||
1
|
||||
tabs.styles/minimized-tab-ratio))))])))
|
||||
:component-will-unmount
|
||||
(fn []
|
||||
(when (not-empty @listeners)
|
||||
|
@ -114,7 +170,7 @@
|
|||
(when listener
|
||||
(.remove listener)))))
|
||||
:reagent-render
|
||||
(fn [args]
|
||||
(fn [args view-id]
|
||||
(let [idx (.. (:navigation args)
|
||||
-state
|
||||
-index)
|
||||
|
@ -123,6 +179,4 @@
|
|||
1 :wallet-stack
|
||||
2 :profile-stack
|
||||
:chat-stack)]
|
||||
(if platform/ios?
|
||||
[react/safe-area-view [tabs tab]]
|
||||
[tabs-animation-wrapper visible? @keyboard-shown? tab])))})))
|
||||
[tabs-animation-wrapper @keyboard-shown? @view-id tab]))})))
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
platform/ios? 52
|
||||
platform/desktop? 68))
|
||||
|
||||
(def minimized-tabs-height 36)
|
||||
|
||||
(def tabs-diff (- tabs-height minimized-tabs-height))
|
||||
|
||||
(def minimized-tab-ratio
|
||||
(/ minimized-tabs-height tabs-height))
|
||||
|
||||
(def tab-height (dec tabs-height))
|
||||
|
||||
(def tabs-container
|
||||
|
@ -94,10 +101,34 @@
|
|||
:right 0
|
||||
:background-color :white
|
||||
:elevation 8
|
||||
:position (when keyboard-shown? :absolute)
|
||||
:position (when (or platform/ios?
|
||||
keyboard-shown?)
|
||||
:absolute)
|
||||
:transform [{:translateY
|
||||
(animation/interpolate
|
||||
visible?
|
||||
{:inputRange [0 1]
|
||||
:outputRange [tabs-height 0]})}]})
|
||||
|
||||
(def ios-titles-cover
|
||||
{:background-color :white
|
||||
:position :absolute
|
||||
:height (- tabs-height minimized-tabs-height)
|
||||
:align-self :stretch
|
||||
:top tabs-height
|
||||
:right 0
|
||||
:left 0})
|
||||
|
||||
(def title-cover-wrapper
|
||||
{:position :absolute
|
||||
:height tabs-height
|
||||
:bottom (if platform/iphone-x? 34 0)
|
||||
:right 0
|
||||
:left 0})
|
||||
|
||||
(defn animation-wrapper [keyboard-shown? main-tab?]
|
||||
{:height (cond
|
||||
keyboard-shown? 0
|
||||
main-tab? tabs-height
|
||||
:else minimized-tabs-height)
|
||||
:align-self :stretch})
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
[status-im.ui.screens.chat.stickers.views :as stickers]
|
||||
[status-im.ui.screens.chat.styles.main :as style]
|
||||
[status-im.ui.screens.chat.toolbar-content :as toolbar-content]
|
||||
[status-im.utils.platform :as platform])
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn add-contact-bar [public-key]
|
||||
|
@ -84,18 +85,18 @@
|
|||
:modal? modal?
|
||||
:current-public-key current-public-key)])
|
||||
|
||||
(def animation-duration 200)
|
||||
|
||||
(defview messages-view-animation [message-view]
|
||||
;; smooths out appearance of message-view
|
||||
(letsubs [opacity (animation/create-value 0)
|
||||
duration (if platform/android? 100 200)
|
||||
timeout (if platform/android? 50 0)]
|
||||
(letsubs [opacity (animation/create-value 0)]
|
||||
{:component-did-mount (fn [_]
|
||||
(animation/start
|
||||
(animation/anim-sequence
|
||||
[(animation/anim-delay timeout)
|
||||
(animation/spring opacity {:toValue 1
|
||||
:duration duration
|
||||
:useNativeDriver true})])))}
|
||||
(animation/timing
|
||||
opacity
|
||||
{:toValue 1
|
||||
:duration animation-duration
|
||||
:useNativeDriver true})))}
|
||||
[react/with-activity-indicator
|
||||
{:style style/message-view-preview
|
||||
:preview [react/view style/message-view-preview]}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
[status-im.ui.screens.home.styles :as styles]
|
||||
[status-im.ui.screens.home.views.inner-item :as inner-item]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils])
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(defn- toolbar [show-welcome? show-sync-state sync-state latest-block-number logged-in?]
|
||||
|
@ -59,6 +60,10 @@
|
|||
[icons/icon :main-icons/add {:color :white}])]]])
|
||||
|
||||
(defn home-list-item [[home-item-id home-item]]
|
||||
(if (= home-item-id :empty)
|
||||
[react/view
|
||||
{:style {:height tabs.styles/tabs-diff
|
||||
:align-self :stretch}}]
|
||||
(let [delete-action (if (:chat-id home-item)
|
||||
(if (and (:group-chat home-item)
|
||||
(not (:public? home-item)))
|
||||
|
@ -73,7 +78,7 @@
|
|||
:on-delete #(do
|
||||
(re-frame/dispatch [:set-swipe-position :chats home-item-id false])
|
||||
(re-frame/dispatch [delete-action home-item-id]))}
|
||||
[inner-item-view home-item]]))
|
||||
[inner-item-view home-item]])))
|
||||
|
||||
;;do not remove view-id and will-update or will-unmount handlers, this is how it works
|
||||
(views/defview welcome [view-id]
|
||||
|
@ -259,7 +264,8 @@
|
|||
previous-position)))
|
||||
(show-search!)))
|
||||
false)}))
|
||||
[list/flat-list {:data all-home-items
|
||||
[list/flat-list {:data (conj (vec all-home-items)
|
||||
[:empty {}])
|
||||
:key-fn first
|
||||
:end-fill-color colors/white
|
||||
:on-scroll-begin-drag
|
||||
|
|
|
@ -319,4 +319,7 @@
|
|||
[react/view styles/my-profile-info-container
|
||||
[my-profile-settings current-account shown-account currency (nil? login-data)]]
|
||||
(when (nil? login-data)
|
||||
[advanced shown-account on-show-advanced])]]])))
|
||||
[advanced shown-account on-show-advanced])
|
||||
[react/view
|
||||
{:align-self :stretch
|
||||
:height 16}]]]])))
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
(def chat-stack
|
||||
{:name :chat-stack
|
||||
:screens [{:name :chat-main-stack
|
||||
:screens (cond->
|
||||
[:home
|
||||
:screens (cond-> [:home
|
||||
:chat
|
||||
:profile
|
||||
:new
|
||||
|
@ -24,21 +22,4 @@
|
|||
:stickers-pack]
|
||||
config/hardwallet-enabled?
|
||||
(concat [:hardwallet-connect :enter-pin]))
|
||||
:config {:initialRouteName :home}}
|
||||
:chat-modal
|
||||
:show-extension-modal
|
||||
:stickers-pack-modal
|
||||
{:name :wallet-send-modal-stack
|
||||
:screens [:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-send-transaction-modal}}
|
||||
{:name :wallet-send-modal-stack-with-onboarding
|
||||
:screens [:wallet-onboarding-setup-modal
|
||||
:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-onboarding-setup-modal}}
|
||||
:wallet-sign-message-modal]
|
||||
:config {:mode :modal
|
||||
:initialRouteName :chat-main-stack}})
|
||||
:config {:initialRouteName :home}})
|
||||
|
|
|
@ -13,30 +13,62 @@
|
|||
[status-im.ui.screens.routing.chat-stack :as chat-stack]
|
||||
[status-im.ui.screens.routing.wallet-stack :as wallet-stack]
|
||||
[status-im.ui.screens.routing.profile-stack :as profile-stack]
|
||||
[status-im.ui.screens.routing.modals :as modals]
|
||||
[status-im.ui.components.bottom-bar.core :as bottom-bar]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]))
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]))
|
||||
|
||||
(defn navigation-events [view-id modal?]
|
||||
(defonce view-id (reagent.core/atom nil))
|
||||
|
||||
(defn navigation-events [current-view-id modal?]
|
||||
[:> navigation/navigation-events
|
||||
{:on-will-focus
|
||||
(fn []
|
||||
(log/debug :on-will-focus view-id)
|
||||
(when (not= @view-id current-view-id)
|
||||
(reset! view-id current-view-id))
|
||||
(log/debug :on-will-focus current-view-id)
|
||||
(when modal?
|
||||
(status-bar/set-status-bar view-id))
|
||||
(re-frame/dispatch [:screens/on-will-focus view-id]))
|
||||
(status-bar/set-status-bar current-view-id))
|
||||
(re-frame/dispatch [:screens/on-will-focus current-view-id]))
|
||||
:on-did-focus
|
||||
(fn []
|
||||
(log/debug :on-did-focus view-id)
|
||||
(when-not modal?
|
||||
(status-bar/set-status-bar view-id)))}])
|
||||
(status-bar/set-status-bar current-view-id)))}])
|
||||
|
||||
(defn wrap [view-id component]
|
||||
(defn wrap
|
||||
"Wraps screen with main view and adds navigation-events component"
|
||||
[view-id component]
|
||||
(fn []
|
||||
(let [main-view (react/create-main-screen-view view-id)]
|
||||
(if platform/ios?
|
||||
[main-view (assoc common-styles/flex
|
||||
:margin-bottom
|
||||
(cond
|
||||
;; there is no need to show bottom nav bar on
|
||||
;; `intro-login-stack` screens
|
||||
(contains?
|
||||
intro-login-stack/all-screens
|
||||
view-id)
|
||||
0
|
||||
|
||||
;; :wallet-onboarding-setup is the only screen
|
||||
;; except main tabs which requires maximised
|
||||
;; bottom nav bar, that's why it requires an extra
|
||||
;; bottom margin, otherwise bottom nav bar will
|
||||
;; partially cover the screen
|
||||
(contains?
|
||||
#{:wallet-onboarding-setup}
|
||||
view-id)
|
||||
tabs.styles/tabs-height
|
||||
|
||||
:else
|
||||
tabs.styles/minimized-tabs-height))
|
||||
[component]
|
||||
[navigation-events view-id false]]
|
||||
|
||||
[main-view common-styles/flex
|
||||
[component]
|
||||
[navigation-events view-id false]])))
|
||||
[navigation-events view-id false]]))))
|
||||
|
||||
(defn wrap-modal [modal-view component]
|
||||
"Wraps modal screen with necessary styling and adds :on-request-close handler
|
||||
|
@ -74,7 +106,20 @@
|
|||
routes
|
||||
(cond->
|
||||
(merge {:headerMode "none"
|
||||
:cardStyle {:backgroundColor (when platform/ios? :white)}}
|
||||
:cardStyle {:backgroundColor (when platform/ios? :white)}
|
||||
:onTransitionStart (fn [n]
|
||||
(let [idx (.. n
|
||||
-navigation
|
||||
-state
|
||||
-index)
|
||||
routes (.. n
|
||||
-navigation
|
||||
-state
|
||||
-routes)]
|
||||
(when (and (array? routes) (int? idx))
|
||||
(let [route (aget routes idx)
|
||||
route-name (keyword (.-routeName route))]
|
||||
(bottom-bar/minimize-bar route-name)))))}
|
||||
(prepare-config config)))))
|
||||
|
||||
(defn switch-navigator [routes config]
|
||||
|
@ -125,12 +170,20 @@
|
|||
(map build-screen)
|
||||
(into {})))
|
||||
|
||||
(defn wrap-bottom-bar
|
||||
[nav]
|
||||
[bottom-bar/bottom-bar nav view-id])
|
||||
|
||||
(defn get-main-component [view-id]
|
||||
(log/debug :component view-id)
|
||||
(switch-navigator
|
||||
(into {}
|
||||
[(build-screen (intro-login-stack/intro-login-stack view-id))
|
||||
[:tabs
|
||||
[:tabs-and-modals
|
||||
{:screen
|
||||
(stack-navigator
|
||||
(merge
|
||||
{:tabs
|
||||
{:screen (tab-navigator
|
||||
(->> [(build-screen chat-stack/chat-stack)
|
||||
(build-screen wallet-stack/wallet-stack)
|
||||
|
@ -138,5 +191,9 @@
|
|||
(into {}))
|
||||
{:initialRouteName :chat-stack
|
||||
:tabBarComponent (reagent.core/reactify-component
|
||||
bottom-bar/bottom-bar)})}]])
|
||||
wrap-bottom-bar)})}}
|
||||
(stack-screens modals/modal-screens))
|
||||
{:mode :modal
|
||||
:initialRouteName :tabs
|
||||
:onTransitionStart (fn [])})}]])
|
||||
{:initialRouteName :intro-login-stack}))
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
(ns status-im.ui.screens.routing.intro-login-stack
|
||||
(:require [status-im.utils.config :as config]))
|
||||
|
||||
(def all-screens
|
||||
#{:login
|
||||
:progress
|
||||
:create-account
|
||||
:recover
|
||||
:accounts
|
||||
:intro
|
||||
:hardwallet-authentication-method
|
||||
:hardwallet-connect
|
||||
:enter-pin
|
||||
:hardwallet-setup
|
||||
:hardwallet-success})
|
||||
|
||||
(defn intro-login-stack [view-id]
|
||||
{:name :intro-login-stack
|
||||
:screens (cond-> [:login
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
(ns status-im.ui.screens.routing.modals)
|
||||
|
||||
(def modal-screens
|
||||
[{:name :wallet-send-modal-stack
|
||||
:screens [:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-send-transaction-modal}}
|
||||
{:name :wallet-send-modal-stack-with-onboarding
|
||||
:screens [:wallet-onboarding-setup-modal
|
||||
:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-onboarding-setup-modal}}
|
||||
:chat-modal
|
||||
:show-extension-modal
|
||||
:stickers-pack-modal
|
||||
:wallet-sign-message-modal
|
||||
:selection-modal-screen
|
||||
:wallet-settings-assets
|
||||
:wallet-transaction-fee
|
||||
:wallet-transactions-filter
|
||||
:profile-qr-viewer])
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
(def profile-stack
|
||||
{:name :profile-stack
|
||||
:screens [{:name :main-profile-stack
|
||||
:screens (cond-> [:my-profile
|
||||
:contacts-list
|
||||
:blocked-users-list
|
||||
|
@ -39,7 +38,4 @@
|
|||
:keycard-settings
|
||||
:reset-card
|
||||
:enter-pin]))
|
||||
:config {:initialRouteName :my-profile}}
|
||||
:profile-qr-viewer]
|
||||
:config {:mode :modal
|
||||
:initialRouteName :main-profile-stack}})
|
||||
:config {:initialRouteName :my-profile}})
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
(def wallet-stack
|
||||
{:name :wallet-stack
|
||||
:screens [{:name :main-wallet-stack
|
||||
:screens [:wallet
|
||||
:collectibles-list
|
||||
:wallet-onboarding-setup
|
||||
|
@ -23,21 +22,4 @@
|
|||
:transactions-history
|
||||
:wallet-transaction-details
|
||||
:wallet-settings-hook]
|
||||
:config {:initialRouteName :wallet}}
|
||||
:selection-modal-screen
|
||||
{:name :wallet-send-modal-stack
|
||||
:screens [:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent-modal
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-send-transaction-modal}}
|
||||
{:name :wallet-send-modal-stack-with-onboarding
|
||||
:screens [:wallet-onboarding-setup-modal
|
||||
:wallet-send-transaction-modal
|
||||
:wallet-transaction-sent
|
||||
:wallet-transaction-fee]
|
||||
:config {:initialRouteName :wallet-send-modal-stack-with-onboarding}}
|
||||
:wallet-settings-assets
|
||||
:wallet-transaction-fee
|
||||
:wallet-transactions-filter]
|
||||
:config {:mode :modal
|
||||
:initialRouteName :main-wallet-stack}})
|
||||
:config {:initialRouteName :wallet}})
|
||||
|
|
Loading…
Reference in New Issue