Skip to content

Commit 646f01d

Browse files
committed
Use Reanimated V2 for Switcher Animations
1 parent 54718ca commit 646f01d

File tree

7 files changed

+157
-126
lines changed

7 files changed

+157
-126
lines changed

.clj-kondo/config.edn

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{:lint-as {status-im.utils.views/defview clojure.core/defn
22
status-im.utils.views/letsubs clojure.core/let
3-
reagent.core/with-let clojkure.core/let
3+
reagent.core/with-let clojure.core/let
44
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
55
quo.react/with-deps-check clojure.core/fn
66
quo.previews.preview/list-comp clojure.core/for

src/quo/react_native.cljs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,6 @@
7474
(def animated-view
7575
(reagent/adapt-react-class (.-View ^js animated)))
7676

77-
(def animated-image-view
78-
(reagent/adapt-react-class (.-Image ^js animated)))
79-
8077
(def ui-manager (.-UIManager ^js rn))
8178

8279
(def layout-animation (.-LayoutAnimation ^js rn))

src/status_im/switcher/animation.cljs

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,79 @@
11
(ns status-im.switcher.animation
2-
(:require [quo.react-native :as rn]
3-
[reagent.core :as reagent]
4-
[status-im.switcher.constants :as constants]
5-
[status-im.ui.components.animation :as anim]))
2+
(:require [quo2.reanimated :as reanimated]
3+
[status-im.switcher.constants :as constants]))
64

7-
(def bottom-tabs-opacity (anim/create-value 1))
8-
(def bottom-tabs-position (anim/create-value 0))
5+
;; Component Animations
6+
(defn switcher-touchable-on-press-in
7+
[touchable-scale]
8+
(reanimated/animate-shared-value-with-timing touchable-scale 0.9 300 :easing1))
99

10-
;; TODO(parvesh): Use 300, after using dispatch-later for opening card(otherwise pending animation issue)
11-
;; or OnAnimationEnd
12-
(def layout-animation #js {:duration 250
13-
:create #js {:type (:ease-in-ease-out rn/layout-animation-types)
14-
:property (:scale-xy rn/layout-animation-properties)}
15-
:update #js {:type (:ease-in-ease-out rn/layout-animation-types)
16-
:property (:scale-xy rn/layout-animation-properties)}
17-
:delete #js {:type (:ease-in-ease-out rn/layout-animation-types)
18-
:property (:scale-xy rn/layout-animation-properties)}})
10+
(defn switcher-touchable-on-press-out
11+
[switcher-opened? close-button-opacity switcher-button-opacity button-touchable-scale]
12+
(reanimated/animate-shared-value-with-timing button-touchable-scale 1 300 :easing2)
13+
(if @switcher-opened?
14+
(do
15+
(reanimated/animate-shared-value-with-timing close-button-opacity 0 300 :easing2)
16+
(reanimated/animate-shared-value-with-timing switcher-button-opacity 1 300 :easing1))
17+
(do
18+
(reanimated/animate-shared-value-with-timing close-button-opacity 1 300 :easing1)
19+
(reanimated/animate-shared-value-with-timing switcher-button-opacity 0 300 :easing2)))
20+
(swap! switcher-opened? not))
1921

20-
(defn animate-layout [show? anim-values]
21-
(let [{:keys [width height]} (constants/dimensions)
22-
target-radius (- (max width height)
23-
constants/switcher-button-radius)]
24-
(rn/configure-next layout-animation)
25-
(reset! (:switcher-screen-radius anim-values) (if show? target-radius 1))
26-
(reagent/flush)))
27-
28-
(defn timing-animation [property toValue]
29-
(anim/timing property {:toValue toValue
30-
:duration 300
31-
:useNativeDriver true}))
32-
33-
(defn animate-components [show? view-id anim-values]
34-
(anim/start
35-
(anim/parallel
36-
(into
37-
[(timing-animation (:switcher-button-opacity anim-values) (if show? 0 1))
38-
(timing-animation (:switcher-close-button-icon-opacity anim-values) (if show? 1 0))
39-
(timing-animation (:switcher-close-button-background-opacity anim-values) (if show? 0.2 0))]
40-
(when (= view-id :home-stack)
41-
[(timing-animation bottom-tabs-opacity (if show? 0 1))
42-
(timing-animation bottom-tabs-position (if show? (constants/bottom-tabs-height) 0))])))))
43-
44-
(defn animate [show? view-id anim-values]
45-
(reagent/flush)
46-
(animate-layout show? anim-values)
47-
(animate-components show? view-id anim-values))
22+
;; Layout Animations
23+
(defn switcher-layout-animations [view-id]
24+
(let [{:keys [width height]} (constants/dimensions)
25+
half-width (/ width 2)
26+
switcher-bottom-position (constants/switcher-bottom-position view-id)
27+
switcher-target-radius (Math/hypot
28+
half-width
29+
(- height constants/switcher-button-radius switcher-bottom-position))
30+
switcher-size (* 2 switcher-target-radius)
31+
switcher-from-x (- half-width constants/switcher-button-radius)
32+
switcher-from-y (- height switcher-bottom-position constants/switcher-button-size constants/switcher-height-offset)
33+
switcher-to-x (- half-width switcher-target-radius)
34+
switcher-to-y (- height constants/switcher-button-size switcher-bottom-position switcher-target-radius)
35+
switcher-entering-animation (.duration (new reanimated/key-frame
36+
(clj->js
37+
{:from {:width constants/switcher-button-size
38+
:height constants/switcher-button-size
39+
:originX switcher-from-x
40+
:originY switcher-from-y
41+
:borderRadius constants/switcher-button-radius}
42+
:to {:width switcher-size
43+
:height switcher-size
44+
:originX switcher-to-x
45+
:originY switcher-to-y
46+
:borderRadius switcher-target-radius}})) 300)
47+
switcher-exiting-animation (.duration (new reanimated/key-frame
48+
(clj->js {:from {:width switcher-size
49+
:height switcher-size
50+
:originX switcher-to-x
51+
:originY switcher-to-y
52+
:borderRadius switcher-target-radius}
53+
:to {:width constants/switcher-button-size
54+
:height constants/switcher-button-size
55+
:originX switcher-from-x
56+
:originY switcher-from-y
57+
:borderRadius constants/switcher-button-radius}})) 300)
58+
container-from-x (- switcher-from-x)
59+
container-from-y (- switcher-from-y)
60+
container-to-x (- switcher-to-x)
61+
container-to-y (- switcher-to-y)
62+
container-entering-animation (.duration (new reanimated/key-frame
63+
(clj->js {:from {:originX container-from-x
64+
:originY container-from-y
65+
:transform [{:scale 0.9}]}
66+
:to {:originX container-to-x
67+
:originY container-to-y
68+
:transform [{:scale 1}]}})) 300)
69+
container-exiting-animation (.duration (new reanimated/key-frame
70+
(clj->js {:from {:originX container-to-x
71+
:originY container-to-y
72+
:transform [{:scale 1}]}
73+
:to {:originX container-from-x
74+
:originY container-from-y
75+
:transform [{:scale 0.9}]}})) 300)]
76+
{:switcher-entering-animation switcher-entering-animation
77+
:switcher-exiting-animation switcher-exiting-animation
78+
:container-entering-animation container-entering-animation
79+
:container-exiting-animation container-exiting-animation}))

src/status_im/switcher/constants.cljs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
(:require [status-im.utils.handlers :refer [<sub]]
33
[status-im.utils.platform :as platform]))
44

5+
;; For translucent status bar, dimensions/window also includes status bar's height,
6+
;; this offset is used for correctly calculating switcher position
7+
(def switcher-height-offset 24)
8+
59
(def switcher-button-radius 24)
610

711
(def switcher-button-size
@@ -20,9 +24,6 @@
2024
switcher-bottom-positions
2125
[(keyword platform/os) view-id]))
2226

23-
(defn switcher-center-position [view-id]
24-
(+ (switcher-bottom-position view-id) (/ switcher-button-size 2)))
25-
2627
;; TODO(parvesh) - use different height for android and ios(Confirm from Design)
2728
(defn bottom-tabs-height []
2829
(if platform/android? 55 80))

src/status_im/switcher/styles.cljs

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
(ns status-im.switcher.styles
22
(:require [quo.theme :as theme]
33
[quo2.foundations.colors :as colors]
4-
[status-im.switcher.constants :as constants]
5-
[status-im.switcher.animation :as animation]))
4+
[status-im.switcher.constants :as constants]))
65

76
(def themes
87
{:light {:bottom-tabs-bg-color colors/neutral-80
98
:bottom-tabs-on-scroll-bg-color colors/neutral-80-opa-80
109
:bottom-tabs-non-selected-tab colors/neutral-50
11-
:bottom-tabs-selected-tab colors/white}
10+
:bottom-tabs-selected-tab colors/white
11+
:switcher-close-button-bg-color colors/white}
1212
:dark {:bottom-tabs-bg-color colors/neutral-80
1313
:bottom-tabs-on-scroll-bg-color colors/neutral-80-opa-60
1414
:bottom-tabs-non-selected-tab colors/neutral-40
15-
:bottom-tabs-selected-tab colors/white}})
15+
:bottom-tabs-selected-tab colors/white
16+
:switcher-close-button-bg-color colors/white}})
1617

1718
(defn get-color [key]
1819
(get-in themes [(theme/get-theme) key]))
@@ -33,63 +34,45 @@
3334
:position :absolute
3435
:bottom -1
3536
:right 0
36-
:left 0
37-
:opacity animation/bottom-tabs-opacity
38-
:transform [{:translateY animation/bottom-tabs-position}]})
37+
:left 0})
3938

4039
;; Switcher
41-
(defn switcher-button [opacity]
40+
41+
(defn switcher-button []
4242
{:width constants/switcher-button-size
4343
:height constants/switcher-button-size
44-
:opacity opacity})
44+
:z-index 2})
4545

4646
(defn merge-switcher-button-common-styles [style]
4747
(merge
4848
{:width constants/switcher-button-size
4949
:height constants/switcher-button-size
5050
:border-radius constants/switcher-button-radius
5151
:position :absolute
52-
:bottom 0
53-
:z-index 3
52+
:z-index 2
5453
:align-items :center
5554
:align-self :center
5655
:justify-content :center}
5756
style))
5857

5958
(defn switcher-button-touchable [view-id]
6059
(merge-switcher-button-common-styles
61-
{:align-self :center
62-
:bottom (constants/switcher-bottom-position view-id)}))
60+
{:bottom (constants/switcher-bottom-position view-id)}))
6361

64-
(defn switcher-close-button-background [opacity]
62+
(defn switcher-close-button []
6563
(merge-switcher-button-common-styles
66-
{:background-color colors/switcher-background
67-
:opacity opacity}))
64+
{:backgroundColor (get-color :switcher-close-button-bg-color)}))
6865

69-
(defn switcher-close-button-icon [opacity]
66+
(defn switcher-screen []
7067
(merge-switcher-button-common-styles
71-
{:opacity opacity}))
72-
73-
(defn switcher-screen [view-id radius]
74-
(let [bottom (- (constants/switcher-center-position view-id) radius)
75-
size (* 2 radius)]
76-
(merge-switcher-button-common-styles
77-
{:background-color colors/switcher-background-opa-80
78-
:bottom bottom
79-
:border-radius 1000
80-
:width size
81-
:overflow :hidden
82-
:height size})))
68+
{:background-color colors/switcher-background-opa-80
69+
:z-index 1
70+
:overflow :hidden}))
8371

84-
(defn switcher-screen-container [view-id radius]
85-
(let [radius radius
86-
bottom (- radius (constants/switcher-center-position view-id))
87-
{:keys [width height]} (constants/dimensions)]
88-
{:position :absolute
89-
:align-self :center
90-
:bottom bottom
91-
:width width
92-
:height (- height 25)
72+
(defn switcher-screen-container []
73+
(let [{:keys [width height]} (constants/dimensions)]
74+
{:width width
75+
:height (+ height 100) ;; Extra Height is required to show hidden cards when zoom animation is running
9376
:align-items :center}))
9477

9578
(defn switcher-switch-screen []

src/status_im/switcher/switcher.cljs

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,64 @@
11
(ns status-im.switcher.switcher
2-
(:require [quo.react-native :as rn]
3-
[reagent.core :as reagent]
2+
(:require [reagent.core :as reagent]
3+
[quo2.reanimated :as reanimated]
44
[status-im.switcher.styles :as styles]
5-
[status-im.ui.components.animation :as anim]
65
[status-im.switcher.animation :as animation]
76
[status-im.ui.components.icons.icons :as icons]
87
[status-im.react-native.resources :as resources]
98
[status-im.switcher.switcher-container :as switcher-container]))
109

11-
(defn toggle-switcher-screen [switcher-opened? view-id anim-values]
12-
(swap! switcher-opened? not)
13-
(animation/animate @switcher-opened? view-id anim-values))
10+
(defn switcher-button
11+
[view-id close-button-opacity switcher-button-opacity
12+
button-touchable-scale toggle-switcher-screen-fn]
13+
[:>
14+
(fn []
15+
(let [touchable-original-style (styles/switcher-button-touchable view-id)
16+
close-button-original-style (styles/switcher-close-button)
17+
switcher-button-original-style (styles/switcher-button)
18+
touchable-animated-style (reanimated/apply-animations-to-style
19+
{:transform [{:scale button-touchable-scale}]}
20+
touchable-original-style)
21+
close-button-animated-style (reanimated/apply-animations-to-style
22+
{:opacity close-button-opacity}
23+
close-button-original-style)
24+
switcher-button-animated-style (reanimated/apply-animations-to-style
25+
{:opacity switcher-button-opacity}
26+
switcher-button-original-style)]
27+
(reagent/as-element
28+
[reanimated/touchable-opacity {:active-opacity 1
29+
:on-press-in #(animation/switcher-touchable-on-press-in
30+
button-touchable-scale)
31+
:on-press-out toggle-switcher-screen-fn
32+
:style touchable-animated-style}
33+
[reanimated/view {:style close-button-animated-style}
34+
[icons/icon :main-icons/close {:color :black}]]
35+
[reanimated/image {:source (resources/get-image :status-logo)
36+
:style switcher-button-animated-style}]])))])
1437

15-
(defn switcher-button [switcher-opened? view-id anim-values]
16-
[rn/touchable-opacity {:active-opacity 1
17-
:on-press #(toggle-switcher-screen switcher-opened? view-id anim-values)
18-
:style (styles/switcher-button-touchable view-id)}
19-
[rn/animated-view {:style (styles/switcher-close-button-background
20-
(:switcher-close-button-background-opacity anim-values))}]
21-
[rn/animated-view {:style (styles/switcher-close-button-icon
22-
(:switcher-close-button-icon-opacity anim-values))}
23-
[icons/icon :main-icons/close {:color :white}]]
24-
[rn/animated-image-view {:source (resources/get-image :status-logo)
25-
:style (styles/switcher-button
26-
(:switcher-button-opacity anim-values))}]])
27-
28-
(defn switcher-screen [switcher-opened? view-id anim-values]
29-
[rn/view {:style (styles/switcher-screen
30-
view-id @(:switcher-screen-radius anim-values))
31-
:pointer-events (if switcher-opened? :auto :none)}
32-
[switcher-container/container
33-
view-id @(:switcher-screen-radius anim-values)
34-
#(toggle-switcher-screen switcher-opened? view-id anim-values)]])
38+
(defn switcher-screen [switcher-opened? view-id toggle-switcher-screen-fn]
39+
(let [{:keys [switcher-entering-animation switcher-exiting-animation
40+
container-entering-animation container-exiting-animation]}
41+
(animation/switcher-layout-animations view-id)]
42+
(when @switcher-opened?
43+
[reanimated/view {:entering switcher-entering-animation
44+
:exiting switcher-exiting-animation
45+
:style (styles/switcher-screen)}
46+
[reanimated/view {:entering container-entering-animation
47+
:exiting container-exiting-animation
48+
:style (styles/switcher-screen-container)}
49+
[switcher-container/tabs toggle-switcher-screen-fn]]])))
3550

3651
(defn switcher [view-id]
37-
(let [switcher-opened? (reagent/atom false)
38-
anim-values {:switcher-button-opacity (anim/create-value 1)
39-
:switcher-close-button-icon-opacity (anim/create-value 0)
40-
:switcher-close-button-background-opacity (anim/create-value 0)
41-
:switcher-screen-radius (reagent/atom 1)}]
42-
[:<>
43-
[switcher-screen switcher-opened? view-id anim-values]
44-
[switcher-button switcher-opened? view-id anim-values]]))
52+
[:>
53+
(fn []
54+
(let [switcher-opened? (reagent/atom false)
55+
close-button-opacity (reanimated/use-shared-value 0)
56+
switcher-button-opacity (reanimated/use-shared-value 1)
57+
button-touchable-scale (reanimated/use-shared-value 1)
58+
toggle-switcher-screen-fn #(animation/switcher-touchable-on-press-out
59+
switcher-opened? close-button-opacity switcher-button-opacity button-touchable-scale)]
60+
(reagent/as-element
61+
[:<>
62+
[switcher-screen switcher-opened? view-id toggle-switcher-screen-fn]
63+
[switcher-button view-id close-button-opacity switcher-button-opacity
64+
button-touchable-scale toggle-switcher-screen-fn]])))])

src/status_im/switcher/switcher_container.cljs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,5 @@
2828
:num-columns 2
2929
:key-fn str}]]))
3030

31-
(defn container [view-id switcher-screen-radius toggle-switcher-screen]
32-
[rn/view {:style (styles/switcher-screen-container
33-
view-id switcher-screen-radius)}
34-
[switch-screen toggle-switcher-screen]])
31+
(defn tabs [toggle-switcher-screen]
32+
[switch-screen toggle-switcher-screen])

0 commit comments

Comments
 (0)