diff --git a/src/status_im2/contexts/onboarding/common/background/view.cljs b/src/status_im2/contexts/onboarding/common/background/view.cljs index 0ddd2f5255..8bf1502e51 100644 --- a/src/status_im2/contexts/onboarding/common/background/view.cljs +++ b/src/status_im2/contexts/onboarding/common/background/view.cljs @@ -31,7 +31,7 @@ :source (resources/get-image :onboarding-illustration)}]) (defonce progress (atom nil)) -(defonce paused (atom nil)) +(defonce paused? (atom nil)) (defn store-screen-height [evt] @@ -60,14 +60,14 @@ animate? (not dark-overlay?) window-width (rf/sub [:dimensions/window-width])] (when animate? - (carousel.animation/use-initialize-animation progress paused animate?)) + (carousel.animation/use-initialize-animation progress paused? animate?)) (rn/use-effect (fn [] - (reanimated/set-shared-value @paused (not= view-id :intro)) + (reanimated/set-shared-value @paused? (not= view-id :intro)) (fn [] (when (= view-id :generating-keys) - (carousel.animation/cleanup-animation progress paused)))) + (carousel.animation/cleanup-animation progress paused?)))) [view-id]) [rn/view @@ -76,8 +76,10 @@ [carousel/view {:animate? animate? :progress progress + :paused? paused? :header-text header-text :header-background true + :swipeable? true :background [background-image (* 4 window-width)]}] (when dark-overlay? [blur/view diff --git a/src/status_im2/contexts/onboarding/common/carousel/animation.cljs b/src/status_im2/contexts/onboarding/common/carousel/animation.cljs index a2eb7a431a..b1da09396d 100644 --- a/src/status_im2/contexts/onboarding/common/carousel/animation.cljs +++ b/src/status_im2/contexts/onboarding/common/carousel/animation.cljs @@ -2,34 +2,76 @@ (:require [react-native.core :as rn] [react-native.reanimated :as reanimated] - [utils.worklets.onboarding-carousel :as worklets.onboarding-carousel])) + [utils.worklets.onboarding-carousel :as worklets.onboarding-carousel] + [react-native.gesture :as gesture] + [oops.core :as oops])) (def ^:const progress-bar-animation-delay 300) (def ^:const progress-bar-animation-duration 4000) +(def ^:const initial-division-quotient 5) +(def ^:const progress-threshold 25) +(def ^:const drag-limit 100) (defn slide-animation - [progress-percentage & [delay duration]] + [progress-percentage & [duration]] (reanimated/with-delay - (or delay progress-bar-animation-delay) + progress-bar-animation-delay (reanimated/with-timing progress-percentage (js-obj "duration" (or duration progress-bar-animation-duration) "easing" (:linear reanimated/easings))))) +(defn calculate-remainder + [dividend divisor] + (if (and (pos-int? dividend) (zero? (mod dividend divisor))) + divisor + (mod dividend divisor))) + +(defn animation-value + [q index] + (let [next-quotient (+ q index) + dividend (if (>= next-quotient initial-division-quotient) + (* (- next-quotient initial-division-quotient) progress-threshold) + (* next-quotient progress-threshold))] + (calculate-remainder dividend drag-limit))) + +(defn animate-progress-value + [value] + (if (zero? value) (slide-animation value 0) (slide-animation value))) + (defn animate-progress - [progress paused] - (reanimated/set-shared-value - progress - (reanimated/with-pause - (reanimated/with-repeat - (reanimated/with-sequence - (slide-animation 25) - (slide-animation 50) - (slide-animation 75) - (slide-animation 100) - (slide-animation 0 300 0)) - -1) - paused))) + [progress paused next-progress] + (let [q (quot next-progress 25)] + (reanimated/set-shared-value + progress + (reanimated/with-pause + (reanimated/with-repeat + (reanimated/with-sequence + (animate-progress-value (animation-value q 1)) + (animate-progress-value (animation-value q 2)) + (animate-progress-value (animation-value q 3)) + (animate-progress-value (animation-value q 4)) + (animate-progress-value (calculate-remainder next-progress drag-limit))) + -1) + paused)))) + +(defn get-next-progress + [progress] + (let [current-progress (reanimated/get-shared-value @progress)] + (if (>= current-progress drag-limit) + drag-limit + (-> (quot current-progress progress-threshold) + (+ 1) + (* progress-threshold))))) + +(defn get-previous-progress + [progress] + (let [current-progress (reanimated/get-shared-value @progress)] + (if (< current-progress progress-threshold) + 0 + (-> (quot current-progress progress-threshold) + (- 1) + (* progress-threshold))))) (defn use-initialize-animation [progress paused animate?] @@ -37,7 +79,7 @@ (reset! paused (reanimated/use-shared-value false)) (rn/use-effect (fn [] - (animate-progress @progress @paused)) + (animate-progress @progress @paused 0)) [animate?])) (defn cleanup-animation @@ -46,6 +88,26 @@ (reanimated/cancel-animation @progress) (reanimated/cancel-animation @paused))) +(defn update-progress + [progress paused new-progress] + (reanimated/set-shared-value @progress new-progress) + (animate-progress @progress @paused new-progress)) + +(defn drag-gesture + [progress paused] + (-> + (gesture/gesture-pan) + (gesture/enabled true) + (gesture/max-pointers 1) + (gesture/on-finalize + (fn [event] + (let [next? (< (oops/oget event "translationX") (- drag-limit)) + previous? (> (oops/oget event "translationX") drag-limit)] + (when next? + (update-progress progress paused (get-next-progress progress))) + (when previous? + (update-progress progress paused (get-previous-progress progress)))))))) + (defn carousel-left-position [window-width animate? progress] (if animate? diff --git a/src/status_im2/contexts/onboarding/common/carousel/view.cljs b/src/status_im2/contexts/onboarding/common/carousel/view.cljs index a1550df13b..19fb4a9779 100644 --- a/src/status_im2/contexts/onboarding/common/carousel/view.cljs +++ b/src/status_im2/contexts/onboarding/common/carousel/view.cljs @@ -5,7 +5,8 @@ [react-native.navigation :as navigation] [react-native.reanimated :as reanimated] [status-im2.contexts.onboarding.common.carousel.style :as style] - [status-im2.contexts.onboarding.common.carousel.animation :as animation])) + [status-im2.contexts.onboarding.common.carousel.animation :as animation] + [react-native.gesture :as gesture])) (defn header-text-view [index window-width header-text] @@ -49,23 +50,25 @@ :progress-bar-width progress-bar-width}]])) (defn f-view - [{:keys [animate? progress header-text background header-background]}] + [{:keys [animate? progress paused? header-text background header-background swipeable?]}] (let [window-width (rf/sub [:dimensions/window-width]) status-bar-height (:status-bar-height @navigation/constants) progress-bar-width (- window-width 40) carousel-left (animation/carousel-left-position window-width animate? progress) container-view (if animate? reanimated/view rn/view)] [:<> - [container-view {:style (style/carousel-container carousel-left animate?)} - (for [index (range 2)] - ^{:key index} - [content-view - {:window-width window-width - :status-bar-height status-bar-height - :index index - :header-text header-text - :header-background header-background} - (when background background)])] + [gesture/gesture-detector + {:gesture (when swipeable? (animation/drag-gesture progress paused?))} + [container-view {:style (style/carousel-container carousel-left animate?)} + (for [index (range 2)] + ^{:key index} + [content-view + {:window-width window-width + :status-bar-height status-bar-height + :index index + :header-text header-text + :header-background header-background} + (when background background)])]] [rn/view {:style (style/progress-bar-container progress-bar-width @@ -79,4 +82,3 @@ :progress progress}]]])) (defn view [props] [:f> f-view props]) - diff --git a/src/status_im2/contexts/onboarding/identifiers/view.cljs b/src/status_im2/contexts/onboarding/identifiers/view.cljs index da7a927540..a12c95c2b1 100644 --- a/src/status_im2/contexts/onboarding/identifiers/view.cljs +++ b/src/status_im2/contexts/onboarding/identifiers/view.cljs @@ -23,16 +23,16 @@ (defn f-view [] (let [progress (atom nil) - paused (atom nil) + paused? (atom nil) {:keys [emoji-hash display-name compressed-key public-key]} (rf/sub [:multiaccount]) {:keys [color]} (rf/sub [:onboarding-2/profile]) photo-path (rf/sub [:chats/photo-path public-key]) emoji-string (string/join emoji-hash)] - (carousel.animation/use-initialize-animation progress paused true) + (carousel.animation/use-initialize-animation progress paused? true) (rn/use-effect (fn [] - (carousel.animation/cleanup-animation progress paused)) + (carousel.animation/cleanup-animation progress paused?)) []) [:<> [background/view true] @@ -40,6 +40,8 @@ [carousel/view {:animate? true :progress progress + :paused? paused? + :swipeable? false :header-text header-text}] [rn/view {:style style/content-container} [quo/profile-card