Implement onboarding slide animation (#15489)
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 2.4 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 2.4 MiB |
Before Width: | Height: | Size: 788 KiB |
Before Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.7 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 2.6 MiB |
After Width: | Height: | Size: 4.7 MiB |
After Width: | Height: | Size: 8.9 MiB |
|
@ -0,0 +1,47 @@
|
||||||
|
import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
|
||||||
|
|
||||||
|
const slideAnimationDuration = 300;
|
||||||
|
|
||||||
|
const easeOut = {
|
||||||
|
duration: slideAnimationDuration,
|
||||||
|
easing: Easing.bezier(0, 0, 0.58, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derived Values
|
||||||
|
export function dynamicProgressBarWidth(staticProgressBarWidth, progress) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
return staticProgressBarWidth * (progress.value || 0) / 100;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function carouselLeftPosition(windowWidth, progress) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
const progressValue = progress.value;
|
||||||
|
switch (true) {
|
||||||
|
case (progressValue < 25):
|
||||||
|
return 0;
|
||||||
|
case (progressValue === 25):
|
||||||
|
return withTiming(-windowWidth, easeOut);
|
||||||
|
case (progressValue < 50):
|
||||||
|
return -windowWidth;
|
||||||
|
case (progressValue === 50):
|
||||||
|
return withTiming(-2 * windowWidth, easeOut);
|
||||||
|
case (progressValue < 75):
|
||||||
|
return -2 * windowWidth;
|
||||||
|
case (progressValue === 75):
|
||||||
|
return withTiming(-3 * windowWidth, easeOut);
|
||||||
|
case (progressValue < 100):
|
||||||
|
return -3 * windowWidth;
|
||||||
|
case (progressValue === 100):
|
||||||
|
return withTiming(-4 * windowWidth, easeOut);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -293,7 +293,10 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||||
:createNativeWrapper identity
|
:createNativeWrapper identity
|
||||||
:default #js {}})
|
:default #js {}})
|
||||||
|
|
||||||
(def react-native-redash #js {:clamp nil})
|
(def react-native-redash
|
||||||
|
#js
|
||||||
|
{:clamp nil
|
||||||
|
:withPause (fn [])})
|
||||||
|
|
||||||
(def react-native-languages
|
(def react-native-languages
|
||||||
(clj->js {:default {:language "en"
|
(clj->js {:default {:language "en"
|
||||||
|
@ -370,6 +373,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||||
"react-native-screens" (clj->js {})
|
"react-native-screens" (clj->js {})
|
||||||
"react-native-reanimated" react-native-reanimated
|
"react-native-reanimated" react-native-reanimated
|
||||||
"react-native-redash/lib/module/v1" react-native-redash
|
"react-native-redash/lib/module/v1" react-native-redash
|
||||||
|
"react-native-redash" react-native-redash
|
||||||
"react-native-fetch-polyfill" fetch
|
"react-native-fetch-polyfill" fetch
|
||||||
"react-native-status-keycard" status-keycard
|
"react-native-status-keycard" status-keycard
|
||||||
"react-native-keychain" keychain
|
"react-native-keychain" keychain
|
||||||
|
@ -407,6 +411,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||||
"../src/js/worklets/bottom_sheet.js" #js {}
|
"../src/js/worklets/bottom_sheet.js" #js {}
|
||||||
"../src/js/worklets/record_audio.js" #js {}
|
"../src/js/worklets/record_audio.js" #js {}
|
||||||
"../src/js/worklets/scroll_view.js" #js {}
|
"../src/js/worklets/scroll_view.js" #js {}
|
||||||
|
"../src/js/worklets/onboarding_carousel.js" #js {}
|
||||||
"../src/js/worklets/lightbox.js" #js {}
|
"../src/js/worklets/lightbox.js" #js {}
|
||||||
"./fleets.js" default-fleets
|
"./fleets.js" default-fleets
|
||||||
"@walletconnect/client" wallet-connect-client
|
"@walletconnect/client" wallet-connect-client
|
||||||
|
|
|
@ -127,6 +127,7 @@
|
||||||
|
|
||||||
;;Solid
|
;;Solid
|
||||||
(def black "#000000")
|
(def black "#000000")
|
||||||
|
(def onboarding-header-black "#000716")
|
||||||
|
|
||||||
;;;;Primary
|
;;;;Primary
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
withDelay
|
withDelay
|
||||||
withSpring
|
withSpring
|
||||||
withRepeat
|
withRepeat
|
||||||
|
withSequence
|
||||||
withDecay
|
withDecay
|
||||||
Easing
|
Easing
|
||||||
Keyframe
|
Keyframe
|
||||||
|
@ -17,8 +18,8 @@
|
||||||
SlideOutUp
|
SlideOutUp
|
||||||
LinearTransition)]
|
LinearTransition)]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
|
["react-native-redash" :refer (withPause)]
|
||||||
[react-native.flat-list :as rn-flat-list]
|
[react-native.flat-list :as rn-flat-list]
|
||||||
[utils.collection]
|
|
||||||
[utils.worklets.core :as worklets.core]))
|
[utils.worklets.core :as worklets.core]))
|
||||||
|
|
||||||
(def ^:const default-duration 300)
|
(def ^:const default-duration 300)
|
||||||
|
@ -59,6 +60,8 @@
|
||||||
(def with-decay withDecay)
|
(def with-decay withDecay)
|
||||||
(def key-frame Keyframe)
|
(def key-frame Keyframe)
|
||||||
(def with-repeat withRepeat)
|
(def with-repeat withRepeat)
|
||||||
|
(def with-sequence withSequence)
|
||||||
|
(def with-pause withPause)
|
||||||
(def cancel-animation cancelAnimation)
|
(def cancel-animation cancelAnimation)
|
||||||
|
|
||||||
;; Easings
|
;; Easings
|
||||||
|
|
|
@ -2,19 +2,14 @@
|
||||||
|
|
||||||
(def ui
|
(def ui
|
||||||
{:add-new-contact (js/require "../resources/images/ui2/add-contact.png")
|
{:add-new-contact (js/require "../resources/images/ui2/add-contact.png")
|
||||||
:intro-1 (js/require "../resources/images/ui2/intro-1.png")
|
|
||||||
:intro-2 (js/require "../resources/images/ui2/intro-2.png")
|
|
||||||
:intro-3 (js/require "../resources/images/ui2/intro-3.png")
|
|
||||||
:intro-4 (js/require "../resources/images/ui2/intro-4.png")
|
|
||||||
:lifestyle (js/require "../resources/images/ui2/lifestyle.png")
|
:lifestyle (js/require "../resources/images/ui2/lifestyle.png")
|
||||||
:music (js/require "../resources/images/ui2/music.png")
|
:music (js/require "../resources/images/ui2/music.png")
|
||||||
:podcasts (js/require "../resources/images/ui2/podcasts.png")
|
:podcasts (js/require "../resources/images/ui2/podcasts.png")
|
||||||
:sync-device (js/require "../resources/images/ui2/sync-new-device-cover-background.png")
|
:sync-device (js/require "../resources/images/ui2/sync-new-device-cover-background.png")
|
||||||
:onboarding-bg-1 (js/require "../resources/images/ui2/onboarding-bg-1.png")
|
|
||||||
:onboarding-blur-bg (js/require "../resources/images/ui2/onboarding_blur_bg.png")
|
|
||||||
:generate-keys (js/require "../resources/images/ui2/generate_keys.png")
|
:generate-keys (js/require "../resources/images/ui2/generate_keys.png")
|
||||||
:ethereum-address (js/require "../resources/images/ui2/ethereum_address.png")
|
:ethereum-address (js/require "../resources/images/ui2/ethereum_address.png")
|
||||||
:use-keycard (js/require "../resources/images/ui2/keycard.png")})
|
:use-keycard (js/require "../resources/images/ui2/keycard.png")
|
||||||
|
:onboarding-illustration (js/require "../resources/images/ui2/onboarding_illustration.png")})
|
||||||
|
|
||||||
(def mock-images
|
(def mock-images
|
||||||
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
|
{:coinbase (js/require "../resources/images/mock2/coinbase.png")
|
||||||
|
|
|
@ -5,20 +5,12 @@
|
||||||
{:background-color colors/neutral-95
|
{:background-color colors/neutral-95
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:position :absolute
|
:position :absolute
|
||||||
|
:overflow :hidden
|
||||||
:top 0
|
:top 0
|
||||||
:bottom 0
|
:bottom 0
|
||||||
:left 0
|
:left 0
|
||||||
:right 0})
|
:right 0})
|
||||||
|
|
||||||
(defn background-gradient-overlay
|
|
||||||
[dark-overlay?]
|
|
||||||
{:position :absolute
|
|
||||||
:height (if dark-overlay? 240 136)
|
|
||||||
:top 0
|
|
||||||
:left 0
|
|
||||||
:right 0
|
|
||||||
:bottom 0})
|
|
||||||
|
|
||||||
(def background-blur-overlay
|
(def background-blur-overlay
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
:left 0
|
:left 0
|
||||||
|
|
|
@ -1,26 +1,22 @@
|
||||||
(ns status-im2.contexts.onboarding.common.background.view
|
(ns status-im2.contexts.onboarding.common.background.view
|
||||||
(:require [react-native.core :as rn]
|
(:require [react-native.core :as rn]
|
||||||
[quo2.foundations.colors :as colors]
|
[react-native.blur :as blur]
|
||||||
[status-im2.common.resources :as resources]
|
[status-im2.contexts.onboarding.common.carousel.view :as carousel]
|
||||||
[react-native.linear-gradient :as linear-gradient]
|
[status-im2.contexts.onboarding.common.background.style :as style]
|
||||||
[status-im2.contexts.onboarding.common.background.style :as style]))
|
[status-im2.contexts.onboarding.common.carousel.animation :as carousel.animation]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[dark-overlay?]
|
[dark-overlay?]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(carousel.animation/initialize-animation)
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style style/background-container}
|
{:style style/background-container}
|
||||||
[rn/image
|
[carousel/view dark-overlay?]
|
||||||
{:blur-radius (if dark-overlay? 13 0)
|
|
||||||
:style {:height "100%"
|
|
||||||
:width "100%"}
|
|
||||||
;; Todo - get background image from sub using carousel index on landing page
|
|
||||||
:source (resources/get-image :onboarding-bg-1)}]
|
|
||||||
[linear-gradient/linear-gradient
|
|
||||||
{:colors [(if dark-overlay? (colors/custom-color :yin 50) "#000716")
|
|
||||||
(if dark-overlay? (colors/custom-color :yin 50 0) "#000716")]
|
|
||||||
:start {:x 0 :y 0}
|
|
||||||
:end {:x 0 :y 1}
|
|
||||||
:style (style/background-gradient-overlay dark-overlay?)}]
|
|
||||||
(when dark-overlay?
|
(when dark-overlay?
|
||||||
[rn/view
|
[blur/view
|
||||||
{:style style/background-blur-overlay}])])
|
{:style style/background-blur-overlay
|
||||||
|
:blur-amount 30
|
||||||
|
:blur-radius 25
|
||||||
|
:blur-type :transparent
|
||||||
|
:overlay-color :transparent}])])])
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
(ns status-im2.contexts.onboarding.common.carousel.animation
|
||||||
|
(:require
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
|
[utils.worklets.onboarding-carousel :as worklets.onboarding-carousel]))
|
||||||
|
|
||||||
|
(def progress (atom nil))
|
||||||
|
(def paused (atom nil))
|
||||||
|
|
||||||
|
(def ^:const progress-bar-animation-delay 300)
|
||||||
|
(def ^:const progress-bar-animation-duration 4000)
|
||||||
|
|
||||||
|
(defn slide-animation
|
||||||
|
[progress-percentage & [delay duration]]
|
||||||
|
(reanimated/with-delay
|
||||||
|
(or delay progress-bar-animation-delay)
|
||||||
|
(reanimated/with-timing
|
||||||
|
progress-percentage
|
||||||
|
(js-obj "duration" (or duration progress-bar-animation-duration)
|
||||||
|
"easing" (:linear reanimated/easings)))))
|
||||||
|
|
||||||
|
(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)))
|
||||||
|
|
||||||
|
(defn initialize-animation
|
||||||
|
[]
|
||||||
|
(when-not @progress
|
||||||
|
(reset! progress (reanimated/use-shared-value 0))
|
||||||
|
(reset! paused (reanimated/use-shared-value false))
|
||||||
|
(animate-progress @progress @paused)))
|
||||||
|
|
||||||
|
;; Derived Values
|
||||||
|
(defn carousel-left-position
|
||||||
|
[window-width]
|
||||||
|
(worklets.onboarding-carousel/carousel-left-position window-width @progress))
|
||||||
|
|
||||||
|
(defn dynamic-progress-bar-width
|
||||||
|
[progress-bar-width]
|
||||||
|
(worklets.onboarding-carousel/dynamic-progress-bar-width progress-bar-width @progress))
|
|
@ -0,0 +1,73 @@
|
||||||
|
(ns status-im2.contexts.onboarding.common.carousel.style
|
||||||
|
(:require
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[react-native.reanimated :as reanimated]))
|
||||||
|
|
||||||
|
(defn header-container
|
||||||
|
[status-bar-height content-width index]
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:left (* content-width index)
|
||||||
|
:padding-top (+ 30 status-bar-height)
|
||||||
|
:width content-width
|
||||||
|
:height (+ 96 status-bar-height)
|
||||||
|
:flex-direction :row
|
||||||
|
:background-color colors/onboarding-header-black})
|
||||||
|
|
||||||
|
(defn header-text-view
|
||||||
|
[window-width]
|
||||||
|
{:flex-direction :column
|
||||||
|
:width window-width
|
||||||
|
:padding-left 20})
|
||||||
|
|
||||||
|
(def carousel-text
|
||||||
|
{:color colors/white})
|
||||||
|
|
||||||
|
(def carousel-sub-text
|
||||||
|
{:color colors/white
|
||||||
|
:margin-top 2})
|
||||||
|
|
||||||
|
(defn background-image
|
||||||
|
[content-width]
|
||||||
|
{:resize-mode :stretch
|
||||||
|
:width content-width})
|
||||||
|
|
||||||
|
(defn progress-bar-item
|
||||||
|
[static? end?]
|
||||||
|
{:height 2
|
||||||
|
:flex 1
|
||||||
|
:background-color (if static? colors/white-opa-10 colors/white)
|
||||||
|
:margin-right (if end? 0 8)
|
||||||
|
:border-radius 4})
|
||||||
|
|
||||||
|
(defn progress-bar
|
||||||
|
[width]
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:width width
|
||||||
|
:flex-direction :row})
|
||||||
|
|
||||||
|
(defn dynamic-progress-bar
|
||||||
|
[width]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:width width}
|
||||||
|
{:height 2
|
||||||
|
:border-radius 4
|
||||||
|
:overflow :hidden}))
|
||||||
|
|
||||||
|
(defn progress-bar-container
|
||||||
|
[progress-bar-width status-bar-height]
|
||||||
|
{:position :absolute
|
||||||
|
:width progress-bar-width
|
||||||
|
:margin-left 20
|
||||||
|
:top (+ 12 status-bar-height)})
|
||||||
|
|
||||||
|
(defn carousel-container
|
||||||
|
[left]
|
||||||
|
(reanimated/apply-animations-to-style
|
||||||
|
{:left left}
|
||||||
|
{:position :absolute
|
||||||
|
:right 0
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:flex-direction :row}))
|
|
@ -0,0 +1,95 @@
|
||||||
|
(ns status-im2.contexts.onboarding.common.carousel.view
|
||||||
|
(:require [quo2.core :as quo]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[react-native.navigation :as navigation]
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
|
[status-im2.common.resources :as resources]
|
||||||
|
[status-im2.contexts.onboarding.common.carousel.style :as style]
|
||||||
|
[status-im2.contexts.onboarding.common.carousel.animation :as animation]))
|
||||||
|
|
||||||
|
(def header-text
|
||||||
|
[{:text (i18n/label :t/join-decentralised-communities)
|
||||||
|
:sub-text (i18n/label :t/participate-in-the-metaverse)}
|
||||||
|
{:text (i18n/label :t/chat-with-friends)
|
||||||
|
:sub-text (i18n/label :t/with-full-encryption)}
|
||||||
|
{:text (i18n/label :t/own-your-crypto)
|
||||||
|
:sub-text (i18n/label :t/use-the-multichain-wallet)}
|
||||||
|
{:text (i18n/label :t/discover-web3)
|
||||||
|
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
|
||||||
|
|
||||||
|
(defn header-text-view
|
||||||
|
[index window-width]
|
||||||
|
[rn/view {:style (style/header-text-view window-width)}
|
||||||
|
[quo/text
|
||||||
|
{:style style/carousel-text
|
||||||
|
:weight :semi-bold
|
||||||
|
:size :heading-2}
|
||||||
|
(get-in header-text [index :text])]
|
||||||
|
[quo/text
|
||||||
|
{:style style/carousel-sub-text
|
||||||
|
:size :paragraph-1}
|
||||||
|
(get-in header-text [index :sub-text])]])
|
||||||
|
|
||||||
|
(defn content-view
|
||||||
|
[{:keys [window-width status-bar-height index]}]
|
||||||
|
(let [content-width (* 4 window-width)]
|
||||||
|
[:<>
|
||||||
|
[rn/image
|
||||||
|
{:style (style/background-image content-width)
|
||||||
|
:source (resources/get-image :onboarding-illustration)}]
|
||||||
|
[rn/view {:style (style/header-container status-bar-height content-width index)}
|
||||||
|
(for [index (range 4)]
|
||||||
|
^{:key index}
|
||||||
|
[header-text-view index window-width])]]))
|
||||||
|
|
||||||
|
(defn progress-bar
|
||||||
|
[{:keys [static? progress-bar-width]}]
|
||||||
|
[rn/view
|
||||||
|
{:style (style/progress-bar progress-bar-width)}
|
||||||
|
[rn/view {:style (style/progress-bar-item static? false)}]
|
||||||
|
[rn/view {:style (style/progress-bar-item static? false)}]
|
||||||
|
[rn/view {:style (style/progress-bar-item static? false)}]
|
||||||
|
[rn/view {:style (style/progress-bar-item static? true)}]])
|
||||||
|
|
||||||
|
(defn dynamic-progress-bar
|
||||||
|
[progress-bar-width]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [width (animation/dynamic-progress-bar-width progress-bar-width)]
|
||||||
|
[reanimated/view {:style (style/dynamic-progress-bar width)}
|
||||||
|
[progress-bar
|
||||||
|
{:static? false
|
||||||
|
:progress-bar-width progress-bar-width}]]))])
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [window-width (rf/sub [:dimensions/window-width])
|
||||||
|
view-id (rf/sub [:view-id])
|
||||||
|
status-bar-height (:status-bar-height @navigation/constants)
|
||||||
|
progress-bar-width (- window-width 40)
|
||||||
|
carousel-left (animation/carousel-left-position window-width)]
|
||||||
|
(rn/use-effect
|
||||||
|
(fn []
|
||||||
|
(reanimated/set-shared-value @animation/paused (not= view-id :intro)))
|
||||||
|
[view-id])
|
||||||
|
[:<>
|
||||||
|
[reanimated/view {:style (style/carousel-container carousel-left)}
|
||||||
|
(for [index (range 2)]
|
||||||
|
^{:key index}
|
||||||
|
[content-view
|
||||||
|
{:window-width window-width
|
||||||
|
:status-bar-height status-bar-height
|
||||||
|
:index index}])]
|
||||||
|
[rn/view
|
||||||
|
{:style (style/progress-bar-container
|
||||||
|
progress-bar-width
|
||||||
|
status-bar-height)}
|
||||||
|
[progress-bar
|
||||||
|
{:static? true
|
||||||
|
:progress-bar-width progress-bar-width}]
|
||||||
|
[dynamic-progress-bar progress-bar-width]]]))])
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
(ns status-im2.contexts.onboarding.common.intro.view
|
|
||||||
(:require [utils.i18n :as i18n]
|
|
||||||
[quo2.core :as quo]
|
|
||||||
[react-native.core :as rn]
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im2.contexts.onboarding.common.intro.style :as style]
|
|
||||||
[status-im2.common.resources :as resources]))
|
|
||||||
|
|
||||||
(def carousels
|
|
||||||
[{:image (resources/get-image :intro-1)
|
|
||||||
:text (i18n/label :t/join-decentralised-communities)
|
|
||||||
:sub-text (i18n/label :t/participate-in-the-metaverse)}
|
|
||||||
{:image (resources/get-image :intro-2)
|
|
||||||
:text (i18n/label :t/chat-with-friends)
|
|
||||||
:sub-text (i18n/label :t/with-full-encryption)}
|
|
||||||
{:image (resources/get-image :intro-3)
|
|
||||||
:text (i18n/label :t/own-your-crypto)
|
|
||||||
:sub-text (i18n/label :t/use-the-multichain-wallet)}
|
|
||||||
{:image (resources/get-image :intro-4)
|
|
||||||
:text (i18n/label :t/discover-web3)
|
|
||||||
:sub-text (i18n/label :t/explore-the-decentralized-web)}])
|
|
||||||
|
|
||||||
(defn progress-bar
|
|
||||||
[index]
|
|
||||||
[rn/view style/progress-bar-container
|
|
||||||
[rn/view {:style (style/progress-bar-item index 0 false)}]
|
|
||||||
[rn/view {:style (style/progress-bar-item index 1 false)}]
|
|
||||||
[rn/view {:style (style/progress-bar-item index 2 false)}]
|
|
||||||
[rn/view {:style (style/progress-bar-item index 3 true)}]])
|
|
||||||
|
|
||||||
;; TODO: carousel component is to be correctly implemented as quo2 component with animations etc in:
|
|
||||||
;; https://github.com/status-im/status-mobile/issues/15012
|
|
||||||
(defn carousel
|
|
||||||
[index]
|
|
||||||
[rn/view {:style style/carousel}
|
|
||||||
[progress-bar index]
|
|
||||||
[quo/text
|
|
||||||
{:style style/carousel-text
|
|
||||||
:weight :semi-bold
|
|
||||||
:size :heading-2}
|
|
||||||
(get-in carousels [index :text])]
|
|
||||||
[quo/text
|
|
||||||
{:style style/carousel-text
|
|
||||||
:size :paragraph-1}
|
|
||||||
(get-in carousels [index :sub-text])]])
|
|
||||||
|
|
||||||
(defn set-index
|
|
||||||
[old-index]
|
|
||||||
(mod (inc old-index) 4))
|
|
||||||
|
|
||||||
(defn view
|
|
||||||
[]
|
|
||||||
(reagent/with-let [carousel-index (reagent/atom 0)
|
|
||||||
interval-id (js/setInterval #(swap! carousel-index set-index)
|
|
||||||
1500)]
|
|
||||||
[rn/view {:style style/page-container}
|
|
||||||
[carousel @carousel-index]
|
|
||||||
[rn/image
|
|
||||||
{:style style/page-image
|
|
||||||
:source (get-in carousels [@carousel-index :image])}]
|
|
||||||
[quo/drawer-buttons
|
|
||||||
{:top-card {:on-press (fn []
|
|
||||||
(rf/dispatch [:navigate-to :sign-in])
|
|
||||||
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
|
||||||
:heading (i18n/label :t/sign-in)
|
|
||||||
:accessibility-label :already-use-status-button}
|
|
||||||
:bottom-card {:on-press (fn []
|
|
||||||
(rf/dispatch [:navigate-to :new-to-status])
|
|
||||||
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
|
||||||
:heading (i18n/label :t/new-to-status)
|
|
||||||
:accessibility-label :new-to-status-button}}
|
|
||||||
(i18n/label :t/you-already-use-status)
|
|
||||||
[quo/text
|
|
||||||
{:style style/text-container}
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-2
|
|
||||||
:style style/plain-text
|
|
||||||
:weight :semi-bold}
|
|
||||||
(i18n/label :t/by-continuing-you-accept)]
|
|
||||||
[quo/text
|
|
||||||
{:on-press #(rf/dispatch [:open-modal :privacy-policy])
|
|
||||||
:size :paragraph-2
|
|
||||||
:style style/highlighted-text
|
|
||||||
:weight :semi-bold}
|
|
||||||
(i18n/label :t/terms-of-service)]]]]
|
|
||||||
(finally
|
|
||||||
(js/clearInterval interval-id))))
|
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im2.contexts.onboarding.common.intro.style
|
(ns status-im2.contexts.onboarding.intro.style
|
||||||
(:require
|
(:require
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
[quo2.foundations.colors :as colors]))
|
[quo2.foundations.colors :as colors]))
|
|
@ -0,0 +1,37 @@
|
||||||
|
(ns status-im2.contexts.onboarding.intro.view
|
||||||
|
(:require [quo2.core :as quo]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[status-im2.contexts.onboarding.intro.style :as style]
|
||||||
|
[status-im2.contexts.onboarding.common.background.view :as background]))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
[rn/view {:style style/page-container}
|
||||||
|
[background/view false]
|
||||||
|
[quo/drawer-buttons
|
||||||
|
{:top-card {:on-press (fn []
|
||||||
|
(rf/dispatch [:navigate-to :sign-in])
|
||||||
|
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
||||||
|
:heading (i18n/label :t/sign-in)
|
||||||
|
:accessibility-label :already-use-status-button}
|
||||||
|
:bottom-card {:on-press (fn []
|
||||||
|
(rf/dispatch [:navigate-to :new-to-status])
|
||||||
|
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
||||||
|
:heading (i18n/label :t/new-to-status)
|
||||||
|
:accessibility-label :new-to-status-button}}
|
||||||
|
(i18n/label :t/you-already-use-status)
|
||||||
|
[quo/text
|
||||||
|
{:style style/text-container}
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style style/plain-text
|
||||||
|
:weight :semi-bold}
|
||||||
|
(i18n/label :t/by-continuing-you-accept)]
|
||||||
|
[quo/text
|
||||||
|
{:on-press #(rf/dispatch [:open-modal :privacy-policy])
|
||||||
|
:size :paragraph-2
|
||||||
|
:style style/highlighted-text
|
||||||
|
:weight :semi-bold}
|
||||||
|
(i18n/label :t/terms-of-service)]]]])
|
|
@ -4,20 +4,13 @@
|
||||||
|
|
||||||
(def full-screen {:flex 1})
|
(def full-screen {:flex 1})
|
||||||
|
|
||||||
(def image-background
|
(def content-container
|
||||||
{:height "100%"
|
|
||||||
:width "100%"})
|
|
||||||
|
|
||||||
(def layer-background
|
|
||||||
{:padding-top (if platform/ios? 44 0)
|
{:padding-top (if platform/ios? 44 0)
|
||||||
:position :absolute
|
:position :absolute
|
||||||
:top 0
|
:top 0
|
||||||
:bottom 0
|
:bottom 0
|
||||||
:left 0
|
:left 0
|
||||||
:right 0
|
:right 0})
|
||||||
:background-color colors/neutral-80-opa-80-blur})
|
|
||||||
|
|
||||||
(def navigation-bar {:height 56})
|
|
||||||
|
|
||||||
(def options-container
|
(def options-container
|
||||||
{:padding-top 12
|
{:padding-top 12
|
||||||
|
|
|
@ -7,16 +7,10 @@
|
||||||
[status-im2.common.resources :as resources]
|
[status-im2.common.resources :as resources]
|
||||||
[status-im2.contexts.onboarding.new-to-status.style :as style]
|
[status-im2.contexts.onboarding.new-to-status.style :as style]
|
||||||
[status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar]
|
[status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar]
|
||||||
|
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn background-image
|
|
||||||
[]
|
|
||||||
[rn/image
|
|
||||||
{:style style/image-background
|
|
||||||
:blur-radius 13
|
|
||||||
:source (resources/get-image :onboarding-blur-bg)}])
|
|
||||||
|
|
||||||
(defn sign-in-options
|
(defn sign-in-options
|
||||||
[]
|
[]
|
||||||
(let [window (rf/sub [:dimensions/window])]
|
(let [window (rf/sub [:dimensions/window])]
|
||||||
|
@ -78,7 +72,7 @@
|
||||||
(defn new-to-status
|
(defn new-to-status
|
||||||
[]
|
[]
|
||||||
[rn/view {:style style/full-screen}
|
[rn/view {:style style/full-screen}
|
||||||
[background-image]
|
[background/view true]
|
||||||
[rn/view {:style style/layer-background}
|
[rn/view {:style style/content-container}
|
||||||
[navigation-bar/navigation-bar {:on-press-info #(js/alert "Info pressed")}]
|
[navigation-bar/navigation-bar {:on-press-info #(js/alert "Info pressed")}]
|
||||||
[sign-in-options]]])
|
[sign-in-options]]])
|
||||||
|
|
|
@ -202,4 +202,4 @@
|
||||||
[background/view true]
|
[background/view true]
|
||||||
(if @show-profiles?
|
(if @show-profiles?
|
||||||
[profiles-section]
|
[profiles-section]
|
||||||
[login-section show-profiles?])]))
|
[login-section])]))
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im2.common.resources :as resources]
|
|
||||||
[status-im2.constants :as constants]
|
[status-im2.constants :as constants]
|
||||||
|
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||||
[status-im2.contexts.onboarding.sign-in.style :as style]
|
[status-im2.contexts.onboarding.sign-in.style :as style]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
@ -216,9 +216,7 @@
|
||||||
:camera-options {:zoomMode :off}
|
:camera-options {:zoomMode :off}
|
||||||
:scan-barcode true
|
:scan-barcode true
|
||||||
:on-read-code on-read-code}]
|
:on-read-code on-read-code}]
|
||||||
[rn/image
|
[background/view true])
|
||||||
{:style (merge style/absolute-fill {:height height :width width})
|
|
||||||
:source (resources/get-image :intro-4)}])
|
|
||||||
(conj hole-view-wrapper
|
(conj hole-view-wrapper
|
||||||
[blur/view
|
[blur/view
|
||||||
{:style style/absolute-fill
|
{:style style/absolute-fill
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
|
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
|
||||||
[status-im2.contexts.communities.discover.view :as communities.discover]
|
[status-im2.contexts.communities.discover.view :as communities.discover]
|
||||||
[status-im2.contexts.communities.overview.view :as communities.overview]
|
[status-im2.contexts.communities.overview.view :as communities.overview]
|
||||||
[status-im2.contexts.onboarding.common.intro.view :as intro]
|
[status-im2.contexts.onboarding.intro.view :as intro]
|
||||||
[status-im2.contexts.onboarding.create-password.view :as create-password]
|
[status-im2.contexts.onboarding.create-password.view :as create-password]
|
||||||
[status-im2.contexts.onboarding.create-profile.view :as create-profile]
|
[status-im2.contexts.onboarding.create-profile.view :as create-profile]
|
||||||
[status-im2.contexts.onboarding.enable-biometrics.view :as enable-biometrics]
|
[status-im2.contexts.onboarding.enable-biometrics.view :as enable-biometrics]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
(ns utils.worklets.onboarding-carousel)
|
||||||
|
|
||||||
|
(def worklets (js/require "../src/js/worklets/onboarding_carousel.js"))
|
||||||
|
|
||||||
|
(defn dynamic-progress-bar-width
|
||||||
|
[static-progress-bar-width progress]
|
||||||
|
(.dynamicProgressBarWidth ^js worklets static-progress-bar-width progress))
|
||||||
|
|
||||||
|
(defn carousel-left-position
|
||||||
|
[window-width progress]
|
||||||
|
(.carouselLeftPosition ^js worklets window-width progress))
|