feat: implement onboarding modal transition for sign in screen (#16167)
This commit is contained in:
parent
affd2a5e76
commit
c2c79cc1ac
|
@ -1,9 +1,19 @@
|
||||||
(ns quo2.components.drawers.drawer-buttons.component-spec
|
(ns quo2.components.drawers.drawer-buttons.component-spec
|
||||||
(:require [quo2.components.drawers.drawer-buttons.view :as drawer-buttons]
|
(:require [quo2.components.drawers.drawer-buttons.view :as drawer-buttons]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[test-helpers.component :as h]))
|
[test-helpers.component :as h]
|
||||||
|
[react-native.safe-area :as safe-area]))
|
||||||
|
|
||||||
(h/describe "drawer-buttons"
|
(h/describe "drawer-buttons"
|
||||||
|
(h/before-each
|
||||||
|
(fn []
|
||||||
|
(h/use-fake-timers)))
|
||||||
|
|
||||||
|
(h/after-each
|
||||||
|
(fn []
|
||||||
|
(h/clear-all-timers)
|
||||||
|
(h/use-real-timers)))
|
||||||
|
|
||||||
(h/test "the top heading and subheading render"
|
(h/test "the top heading and subheading render"
|
||||||
(h/render [drawer-buttons/view
|
(h/render [drawer-buttons/view
|
||||||
{:top-card {:heading :top-heading}
|
{:top-card {:heading :top-heading}
|
||||||
|
@ -29,15 +39,16 @@
|
||||||
|
|
||||||
(h/test "it clicks the top card"
|
(h/test "it clicks the top card"
|
||||||
(let [event (h/mock-fn)]
|
(let [event (h/mock-fn)]
|
||||||
(h/render [drawer-buttons/view
|
(with-redefs [safe-area/get-top (fn [] 10)]
|
||||||
{:top-card {:on-press event
|
(h/render [drawer-buttons/view
|
||||||
:heading :top-heading}
|
{:top-card {:on-press event
|
||||||
:bottom-card {:heading :bottom-heading}}
|
:heading :top-heading}
|
||||||
:top-sub-heading
|
:bottom-card {:heading :bottom-heading}}
|
||||||
:bottom-sub-heading])
|
:top-sub-heading
|
||||||
(h/fire-event :press (h/get-by-text "top-heading"))
|
:bottom-sub-heading])
|
||||||
(-> (js/expect event)
|
(h/fire-event :press (h/get-by-text "top-heading"))
|
||||||
(.toHaveBeenCalled))))
|
(-> (js/expect event)
|
||||||
|
(.toHaveBeenCalled)))))
|
||||||
|
|
||||||
(h/test "it clicks the bottom card"
|
(h/test "it clicks the bottom card"
|
||||||
(let [event (h/mock-fn)]
|
(let [event (h/mock-fn)]
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
(ns quo2.components.drawers.drawer-buttons.style
|
(ns quo2.components.drawers.drawer-buttons.style
|
||||||
(:require [quo2.foundations.colors :as colors]))
|
(:require [quo2.foundations.colors :as colors]
|
||||||
|
[react-native.reanimated :as reanimated]))
|
||||||
|
|
||||||
(def outer-container
|
(defn outer-container
|
||||||
{:height 216
|
[height border-radius container-style]
|
||||||
:border-top-left-radius 20
|
(reanimated/apply-animations-to-style
|
||||||
:border-top-right-radius 20
|
{:height height
|
||||||
:overflow :hidden})
|
:border-top-left-radius border-radius
|
||||||
|
:border-top-right-radius border-radius}
|
||||||
|
(assoc
|
||||||
|
container-style
|
||||||
|
:position :absolute
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom 0
|
||||||
|
:overflow :hidden)))
|
||||||
|
|
||||||
(def top-card
|
(def top-card
|
||||||
{:flex 1
|
{:flex 1
|
||||||
|
@ -17,7 +26,6 @@
|
||||||
|
|
||||||
(def bottom-card
|
(def bottom-card
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
:top 80
|
|
||||||
:left 0
|
:left 0
|
||||||
:right 0
|
:right 0
|
||||||
:bottom 0
|
:bottom 0
|
||||||
|
@ -41,6 +49,20 @@
|
||||||
:align-items :center
|
:align-items :center
|
||||||
:border-color colors/white-opa-5})
|
:border-color colors/white-opa-5})
|
||||||
|
|
||||||
|
(def blur-view-style
|
||||||
|
{:flex 1
|
||||||
|
:border-top-left-radius 20
|
||||||
|
:border-top-right-radius 20})
|
||||||
|
|
||||||
|
(def blur-content-style
|
||||||
|
{:flex 1
|
||||||
|
:background-color :transparent
|
||||||
|
:position :absolute
|
||||||
|
:top 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom 0})
|
||||||
|
|
||||||
(def bottom-text
|
(def bottom-text
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:color colors/white-70-blur})
|
:color colors/white-70-blur})
|
||||||
|
@ -51,4 +73,4 @@
|
||||||
(defn heading-text
|
(defn heading-text
|
||||||
[gap]
|
[gap]
|
||||||
{:color colors/white
|
{:color colors/white
|
||||||
:margin-bottom gap})
|
:margin-bottom gap})
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
[quo2.components.markdown.text :as text]
|
[quo2.components.markdown.text :as text]
|
||||||
[quo2.foundations.colors :as colors]
|
[quo2.foundations.colors :as colors]
|
||||||
[react-native.blur :as blur]
|
[react-native.blur :as blur]
|
||||||
[quo2.components.drawers.drawer-buttons.style :as style]))
|
[quo2.components.drawers.drawer-buttons.style :as style]
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
|
[react-native.platform :as platform]
|
||||||
|
[react-native.safe-area :as safe-area]))
|
||||||
|
|
||||||
|
(def default-height 216)
|
||||||
|
|
||||||
(defn render-bottom
|
(defn render-bottom
|
||||||
[children]
|
[children]
|
||||||
|
@ -29,35 +34,74 @@
|
||||||
children]]
|
children]]
|
||||||
[render-bottom children]))
|
[render-bottom children]))
|
||||||
|
|
||||||
(defn render-children-top
|
(defn- f-render-children-top
|
||||||
[children]
|
[children top-children-opacity]
|
||||||
(if (label? children)
|
(let [scale (reanimated/interpolate top-children-opacity [1 0] [1 1.1])
|
||||||
[text/text
|
padding-left (reanimated/interpolate scale [1 1.1] [0 14])]
|
||||||
{:size :paragraph-2
|
[reanimated/view
|
||||||
:style style/top-text
|
{:style (reanimated/apply-animations-to-style
|
||||||
:weight :semi-bold}
|
{:opacity top-children-opacity
|
||||||
children]
|
:transform [{:scale scale}
|
||||||
children))
|
{:translate-x padding-left}]}
|
||||||
|
{})}
|
||||||
|
(if (label? children)
|
||||||
|
[text/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:style style/top-text
|
||||||
|
:weight :semi-bold}
|
||||||
|
children]
|
||||||
|
children)]))
|
||||||
|
|
||||||
(defn card
|
(defn- f-card
|
||||||
[{:keys [on-press style heading gap accessibility-label top?]} children]
|
[{:keys [on-press default-on-press style heading gap accessibility-label top? top-title-opacity
|
||||||
|
top-children-opacity
|
||||||
|
animated-heading]
|
||||||
|
:or {top-title-opacity (reanimated/use-shared-value 1)}}
|
||||||
|
children]
|
||||||
[rn/touchable-highlight
|
[rn/touchable-highlight
|
||||||
{:accessibility-label accessibility-label
|
{:accessibility-label accessibility-label
|
||||||
:on-press on-press
|
:on-press (fn []
|
||||||
|
(when on-press
|
||||||
|
(on-press))
|
||||||
|
(when default-on-press
|
||||||
|
(default-on-press)))
|
||||||
:border-radius 20
|
:border-radius 20
|
||||||
:style style
|
:style style
|
||||||
:underlay-color (:background-color style)}
|
:underlay-color (:background-color style)}
|
||||||
[rn/view
|
[rn/view
|
||||||
[text/text
|
[reanimated/view
|
||||||
{:size :heading-1
|
{:style (reanimated/apply-animations-to-style
|
||||||
:style (style/heading-text gap)
|
{:opacity top-title-opacity}
|
||||||
:weight :semi-bold}
|
{})}
|
||||||
heading]
|
[text/text
|
||||||
|
{:size :heading-1
|
||||||
|
:style (style/heading-text gap)
|
||||||
|
:weight :semi-bold}
|
||||||
|
heading]]
|
||||||
|
(when animated-heading
|
||||||
|
(let [animated-heading-opacity (reanimated/interpolate top-children-opacity [1 0] [0 1])]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity top-title-opacity}
|
||||||
|
{:position :absolute})}
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity animated-heading-opacity}
|
||||||
|
{})}
|
||||||
|
[text/text
|
||||||
|
{:size :heading-1
|
||||||
|
:style (style/heading-text gap)
|
||||||
|
:weight :semi-bold}
|
||||||
|
animated-heading]]]))
|
||||||
(if top?
|
(if top?
|
||||||
[render-children-top children]
|
[:f> f-render-children-top children top-children-opacity]
|
||||||
[render-children-bottom children])]])
|
[render-children-bottom children])]])
|
||||||
|
|
||||||
(defn view
|
(defn card
|
||||||
|
[props children]
|
||||||
|
[:f> f-card props children])
|
||||||
|
|
||||||
|
(defn f-view
|
||||||
"[view opts]
|
"[view opts]
|
||||||
opts
|
opts
|
||||||
{:container-style style-object
|
{:container-style style-object
|
||||||
|
@ -70,29 +114,101 @@
|
||||||
child-1 string, keyword or hiccup
|
child-1 string, keyword or hiccup
|
||||||
child-2 string, keyword or hiccup
|
child-2 string, keyword or hiccup
|
||||||
"
|
"
|
||||||
[{:keys [container-style top-card bottom-card]} child-1 child-2]
|
[{:keys [container-style top-card bottom-card on-init animations-duration animations-delay]}
|
||||||
[rn/view
|
child-1
|
||||||
{:style (merge container-style style/outer-container)}
|
child-2]
|
||||||
[blur/view
|
(let [max-height (+ (:height (rn/get-window)) (if platform/android? (safe-area/get-top) 0))
|
||||||
{:blur-type :dark
|
height (reanimated/use-shared-value default-height)
|
||||||
:blur-amount 10
|
top-padding (reanimated/use-shared-value 12)
|
||||||
:style {:flex 1
|
border-radius (reanimated/use-shared-value 20)
|
||||||
:border-top-left-radius 20
|
bottom-view-top (reanimated/use-shared-value 80)
|
||||||
:border-top-right-radius 20}}]
|
top-title-opacity (reanimated/use-shared-value 1)
|
||||||
[rn/view
|
top-children-opacity (reanimated/use-shared-value 1)
|
||||||
{:style {:flex 1
|
animations-delay (/ animations-delay 1.4)
|
||||||
:background-color :transparent
|
start-top-animation (fn []
|
||||||
:position :absolute
|
(reanimated/animate-shared-value-with-delay bottom-view-top
|
||||||
:top 0
|
(:height (rn/get-screen))
|
||||||
:left 0
|
animations-duration
|
||||||
:right 0
|
:easing4
|
||||||
:bottom 0}}
|
animations-delay)
|
||||||
[card
|
(reanimated/animate-shared-value-with-delay
|
||||||
(merge {:gap 4
|
height
|
||||||
:top? true
|
max-height
|
||||||
:style style/top-card}
|
animations-duration
|
||||||
top-card) child-1]
|
:easing4
|
||||||
[card
|
animations-delay)
|
||||||
(merge {:style style/bottom-card
|
(reanimated/animate-shared-value-with-delay
|
||||||
:gap 20}
|
top-padding
|
||||||
bottom-card) child-2]]])
|
(+ 68 (safe-area/get-top))
|
||||||
|
animations-duration
|
||||||
|
:easing4
|
||||||
|
animations-delay)
|
||||||
|
(reanimated/animate-shared-value-with-delay
|
||||||
|
top-children-opacity
|
||||||
|
0
|
||||||
|
animations-duration
|
||||||
|
:easing4 animations-delay)
|
||||||
|
(reanimated/animate-shared-value-with-delay
|
||||||
|
top-title-opacity
|
||||||
|
0
|
||||||
|
0
|
||||||
|
:linear
|
||||||
|
(+ animations-delay animations-duration 500)))
|
||||||
|
reset-top-animation (fn []
|
||||||
|
(reanimated/set-shared-value top-title-opacity 1)
|
||||||
|
(reanimated/animate-shared-value-with-delay bottom-view-top
|
||||||
|
80
|
||||||
|
animations-duration
|
||||||
|
:easing4
|
||||||
|
50)
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
height
|
||||||
|
default-height
|
||||||
|
animations-duration
|
||||||
|
:easing4)
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
top-padding
|
||||||
|
12
|
||||||
|
animations-duration
|
||||||
|
:easing4)
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
top-children-opacity
|
||||||
|
1
|
||||||
|
animations-duration
|
||||||
|
:easing4))]
|
||||||
|
(rn/use-effect (fn []
|
||||||
|
(when on-init
|
||||||
|
(on-init reset-top-animation))))
|
||||||
|
[reanimated/view {:style (style/outer-container height border-radius container-style)}
|
||||||
|
[blur/view
|
||||||
|
{:blur-type :dark
|
||||||
|
:blur-amount 10
|
||||||
|
:style style/blur-view-style}
|
||||||
|
[rn/view
|
||||||
|
{:style style/blur-content-style}
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:padding-top top-padding}
|
||||||
|
style/top-card)}
|
||||||
|
[card
|
||||||
|
(merge {:gap 4
|
||||||
|
:top? true
|
||||||
|
:style {:flex 1}
|
||||||
|
:top-children-opacity top-children-opacity
|
||||||
|
:top-title-opacity top-title-opacity
|
||||||
|
:default-on-press start-top-animation}
|
||||||
|
top-card)
|
||||||
|
child-1]]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:top bottom-view-top}
|
||||||
|
style/bottom-card)}
|
||||||
|
[card
|
||||||
|
(merge {:style {:flex 1}
|
||||||
|
:gap 10}
|
||||||
|
bottom-card)
|
||||||
|
child-2]]]]]))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[props child-1 child-2]
|
||||||
|
[:f> f-view props child-1 child-2])
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
{:linear (bezier 0 0 1 1)
|
{:linear (bezier 0 0 1 1)
|
||||||
:easing1 (bezier 0.25 0.1 0.25 1)
|
:easing1 (bezier 0.25 0.1 0.25 1)
|
||||||
:easing2 (bezier 0 0.3 0.6 0.9)
|
:easing2 (bezier 0 0.3 0.6 0.9)
|
||||||
:easing3 (bezier 0.3 0.3 0.3 0.9)})
|
:easing3 (bezier 0.3 0.3 0.3 0.9)
|
||||||
|
:easing4 (bezier 0.3 0.3 1 1)})
|
||||||
|
|
||||||
;; Helper functions
|
;; Helper functions
|
||||||
(defn get-shared-value
|
(defn get-shared-value
|
||||||
|
|
|
@ -80,7 +80,9 @@
|
||||||
multiaccount-data (when received-account?
|
multiaccount-data (when received-account?
|
||||||
(merge account {:password password}))
|
(merge account {:password password}))
|
||||||
navigate-to-syncing-devices? (and (or connection-success? error-on-pairing?) receiver?)
|
navigate-to-syncing-devices? (and (or connection-success? error-on-pairing?) receiver?)
|
||||||
user-in-syncing-devices-screen? (= (:view-id db) :syncing-progress)]
|
user-in-syncing-devices-screen? (or (= (:view-id db) :syncing-progress)
|
||||||
|
(= (:view-id db) :syncing-progress-intro))
|
||||||
|
user-in-sign-in-intro-screen? (= (:view-id db) :sign-in-intro)]
|
||||||
(merge {:db (cond-> db
|
(merge {:db (cond-> db
|
||||||
connection-success?
|
connection-success?
|
||||||
(assoc-in [:syncing :pairing-status] :connected)
|
(assoc-in [:syncing :pairing-status] :connected)
|
||||||
|
@ -95,7 +97,9 @@
|
||||||
(assoc-in [:syncing :pairing-status] :completed))}
|
(assoc-in [:syncing :pairing-status] :completed))}
|
||||||
(cond
|
(cond
|
||||||
(and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
(and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
||||||
{:dispatch [:navigate-to :syncing-progress]}
|
{:dispatch (if user-in-sign-in-intro-screen?
|
||||||
|
[:navigate-to-within-stack [:syncing-progress-intro :sign-in-intro]]
|
||||||
|
[:navigate-to :syncing-progress])}
|
||||||
|
|
||||||
(and completed-pairing? sender?)
|
(and completed-pairing? sender?)
|
||||||
{:dispatch [:syncing/clear-states]}
|
{:dispatch [:syncing/clear-states]}
|
||||||
|
|
|
@ -336,3 +336,6 @@
|
||||||
(def ^:const image-description-in-lightbox? false)
|
(def ^:const image-description-in-lightbox? false)
|
||||||
|
|
||||||
(def ^:const audio-max-duration-ms 120000)
|
(def ^:const audio-max-duration-ms 120000)
|
||||||
|
|
||||||
|
(def ^:const onboarding-modal-animation-duration 300)
|
||||||
|
(def ^:const onboarding-modal-animation-delay 400)
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
{: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
|
||||||
|
|
|
@ -4,23 +4,34 @@
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im2.contexts.onboarding.intro.style :as style]
|
[status-im2.contexts.onboarding.intro.style :as style]
|
||||||
[status-im2.contexts.onboarding.common.background.view :as background]))
|
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||||
|
[status-im2.constants :as constants]
|
||||||
|
[status-im2.contexts.syncing.scan-sync-code.view :as scan-sync-code]
|
||||||
|
[utils.debounce :as debounce]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
[rn/view {:style style/page-container}
|
[rn/view {:style style/page-container}
|
||||||
[background/view false]
|
[background/view false]
|
||||||
[quo/drawer-buttons
|
[quo/drawer-buttons
|
||||||
{:top-card {:on-press (fn []
|
{:on-init (fn [reset-top-animation-fn]
|
||||||
(rf/dispatch [:navigate-to :sign-in])
|
(reset! scan-sync-code/dismiss-animations reset-top-animation-fn))
|
||||||
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
:animations-duration constants/onboarding-modal-animation-duration
|
||||||
:heading (i18n/label :t/sign-in)
|
:animations-delay constants/onboarding-modal-animation-delay
|
||||||
:accessibility-label :already-use-status-button}
|
:top-card {:on-press (fn []
|
||||||
:bottom-card {:on-press (fn []
|
(debounce/dispatch-and-chill [:open-modal
|
||||||
(rf/dispatch [:navigate-to :new-to-status])
|
:sign-in-intro]
|
||||||
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
2000)
|
||||||
:heading (i18n/label :t/new-to-status)
|
(rf/dispatch [:hide-terms-of-services-opt-in-screen]))
|
||||||
:accessibility-label :new-to-status-button}}
|
:heading (i18n/label :t/sign-in)
|
||||||
|
:animated-heading (i18n/label :t/sign-in-by-syncing)
|
||||||
|
: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}}
|
||||||
[quo/text
|
[quo/text
|
||||||
{:style style/plain-text}
|
{:style style/plain-text}
|
||||||
(i18n/label :t/you-already-use-status)]
|
(i18n/label :t/you-already-use-status)]
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
:accessibility-label :create-new-profile}
|
:accessibility-label :create-new-profile}
|
||||||
{:icon :i/multi-profile
|
{:icon :i/multi-profile
|
||||||
:label (i18n/label :t/add-existing-status-profile)
|
:label (i18n/label :t/add-existing-status-profile)
|
||||||
:on-press #(rf/dispatch [:navigate-to :sign-in])
|
:on-press #(rf/dispatch [:open-modal :sign-in])
|
||||||
:accessibility-label :multi-profile}]]])
|
:accessibility-label :multi-profile}]]])
|
||||||
|
|
||||||
(defn show-new-account-options
|
(defn show-new-account-options
|
||||||
|
|
|
@ -3,9 +3,22 @@
|
||||||
[status-im2.contexts.onboarding.common.background.view :as background]
|
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||||
[status-im2.contexts.syncing.scan-sync-code.view :as scan-sync-code]))
|
[status-im2.contexts.syncing.scan-sync-code.view :as scan-sync-code]))
|
||||||
|
|
||||||
|
(defn navigate-back
|
||||||
|
[]
|
||||||
|
(when @scan-sync-code/navigate-back-fn
|
||||||
|
(@scan-sync-code/navigate-back-fn)))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
[scan-sync-code/view
|
[scan-sync-code/view
|
||||||
{:title (i18n/label :t/sign-in-by-syncing)
|
{:title (i18n/label :t/sign-in-by-syncing)
|
||||||
:show-bottom-view? true
|
:show-bottom-view? true
|
||||||
:background [background/view true]}])
|
:background [background/view true]
|
||||||
|
:animated? false}])
|
||||||
|
|
||||||
|
(defn animated-view
|
||||||
|
[]
|
||||||
|
[scan-sync-code/view
|
||||||
|
{:title (i18n/label :t/sign-in-by-syncing)
|
||||||
|
:show-bottom-view? true
|
||||||
|
:animated? true}])
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
(ns status-im2.contexts.onboarding.syncing.progress.style
|
(ns status-im2.contexts.onboarding.syncing.progress.style
|
||||||
(:require [quo2.foundations.colors :as colors]))
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def page-container
|
(defn page-container
|
||||||
|
[in-onboarding?]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:position :absolute
|
:position :absolute
|
||||||
:top 0
|
:top 0
|
||||||
|
@ -9,7 +10,7 @@
|
||||||
:left 0
|
:left 0
|
||||||
:right 0
|
:right 0
|
||||||
:padding-bottom 20
|
:padding-bottom 20
|
||||||
:background-color colors/neutral-80-opa-80-blur})
|
:background-color (when-not in-onboarding? colors/neutral-80-opa-80-blur)})
|
||||||
|
|
||||||
(def page-illustration
|
(def page-illustration
|
||||||
{:flex 1
|
{:flex 1
|
||||||
|
|
|
@ -30,22 +30,23 @@
|
||||||
:subtitle-accessibility-label :progress-screen-sub-title}])
|
:subtitle-accessibility-label :progress-screen-sub-title}])
|
||||||
|
|
||||||
(defn try-again-button
|
(defn try-again-button
|
||||||
[profile-color]
|
[profile-color in-onboarding?]
|
||||||
[quo/button
|
[quo/button
|
||||||
{:on-press (fn []
|
{:on-press (fn []
|
||||||
(rf/dispatch [:syncing/clear-states])
|
(rf/dispatch [:syncing/clear-states])
|
||||||
(rf/dispatch [:navigate-back]))
|
(rf/dispatch [:navigate-back-to
|
||||||
|
(if in-onboarding? :sign-in-intro :sign-in)]))
|
||||||
:accessibility-label :try-again-later-button
|
:accessibility-label :try-again-later-button
|
||||||
:override-background-color (colors/custom-color profile-color 60)
|
:override-background-color (colors/custom-color profile-color 60)
|
||||||
:style style/try-again-button}
|
:style style/try-again-button}
|
||||||
(i18n/label :t/try-again)])
|
(i18n/label :t/try-again)])
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[in-onboarding?]
|
||||||
(let [pairing-status (rf/sub [:pairing/pairing-status])
|
(let [pairing-status (rf/sub [:pairing/pairing-status])
|
||||||
profile-color (:color (rf/sub [:onboarding-2/profile]))]
|
profile-color (:color (rf/sub [:onboarding-2/profile]))]
|
||||||
[rn/view {:style style/page-container}
|
[rn/view {:style (style/page-container in-onboarding?)}
|
||||||
[background/view true]
|
(when-not in-onboarding? [background/view true])
|
||||||
[quo/page-nav]
|
[quo/page-nav]
|
||||||
[page-title (pairing-progress pairing-status)]
|
[page-title (pairing-progress pairing-status)]
|
||||||
(if (pairing-progress pairing-status)
|
(if (pairing-progress pairing-status)
|
||||||
|
@ -54,4 +55,8 @@
|
||||||
[rn/view {:style style/page-illustration}
|
[rn/view {:style style/page-illustration}
|
||||||
[quo/text "[Error here]"]])
|
[quo/text "[Error here]"]])
|
||||||
(when-not (pairing-progress pairing-status)
|
(when-not (pairing-progress pairing-status)
|
||||||
[try-again-button profile-color])]))
|
[try-again-button profile-color in-onboarding?])]))
|
||||||
|
|
||||||
|
(defn view-onboarding
|
||||||
|
[]
|
||||||
|
[view true])
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im2.contexts.syncing.scan-sync-code.style
|
(ns status-im2.contexts.syncing.scan-sync-code.style
|
||||||
(:require [quo2.foundations.colors :as colors]))
|
(:require [quo2.foundations.colors :as colors]
|
||||||
|
[react-native.reanimated :as reanimated]))
|
||||||
|
|
||||||
(def screen-padding 20)
|
(def screen-padding 20)
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@
|
||||||
[viewfinder]
|
[viewfinder]
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
:left (:x viewfinder)
|
:left (:x viewfinder)
|
||||||
:top (:y viewfinder)})
|
:top 19})
|
||||||
|
|
||||||
(def view-finder-border-container
|
(def view-finder-border-container
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
|
@ -104,6 +105,7 @@
|
||||||
|
|
||||||
(def camera-permission-container
|
(def camera-permission-container
|
||||||
{:height 335
|
{:height 335
|
||||||
|
:margin-top 19
|
||||||
:margin-horizontal screen-padding
|
:margin-horizontal screen-padding
|
||||||
:background-color colors/white-opa-5
|
:background-color colors/white-opa-5
|
||||||
:border-color colors/white-opa-10
|
:border-color colors/white-opa-10
|
||||||
|
@ -126,15 +128,17 @@
|
||||||
:align-items :center})
|
:align-items :center})
|
||||||
|
|
||||||
(defn bottom-container
|
(defn bottom-container
|
||||||
[padding-bottom]
|
[translate-y padding-bottom]
|
||||||
{:z-index 6
|
(reanimated/apply-animations-to-style
|
||||||
:padding-top 12
|
{:transform [{:translate-y translate-y}]}
|
||||||
:padding-bottom padding-bottom
|
{:z-index 6
|
||||||
:background-color colors/white-opa-5
|
:padding-top 12
|
||||||
:border-top-left-radius 20
|
:padding-bottom padding-bottom
|
||||||
:border-top-right-radius 20
|
:background-color colors/white-opa-5
|
||||||
:align-items :center
|
:border-top-left-radius 20
|
||||||
:justify-content :center})
|
:border-top-right-radius 20
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center}))
|
||||||
|
|
||||||
(def bottom-text
|
(def bottom-text
|
||||||
{:color colors/white
|
{:color colors/white
|
||||||
|
|
|
@ -14,12 +14,17 @@
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[status-im2.contexts.syncing.utils :as sync-utils]
|
[status-im2.contexts.syncing.utils :as sync-utils]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
|
[status-im2.constants :as constants]
|
||||||
|
[utils.debounce :as debounce]))
|
||||||
|
|
||||||
;; Android allow local network access by default. So, we need this check on iOS only.
|
;; Android allow local network access by default. So, we need this check on iOS only.
|
||||||
(defonce preflight-check-passed? (reagent/atom (if platform/ios? false true)))
|
(defonce preflight-check-passed? (reagent/atom (if platform/ios? false true)))
|
||||||
|
|
||||||
(defonce camera-permission-granted? (reagent/atom false))
|
(defonce camera-permission-granted? (reagent/atom false))
|
||||||
|
(defonce dismiss-animations (atom nil))
|
||||||
|
(defonce navigate-back-fn (atom nil))
|
||||||
|
|
||||||
(defn request-camera-permission
|
(defn request-camera-permission
|
||||||
[]
|
[]
|
||||||
|
@ -42,47 +47,83 @@
|
||||||
[]
|
[]
|
||||||
(rf/dispatch [:syncing/preflight-outbound-check #(reset! preflight-check-passed? %)]))
|
(rf/dispatch [:syncing/preflight-outbound-check #(reset! preflight-check-passed? %)]))
|
||||||
|
|
||||||
|
(defn- f-header
|
||||||
|
[{:keys [active-tab read-qr-once? title title-opacity subtitle-opacity reset-animations-fn animated?]}]
|
||||||
|
(let [subtitle-translate-x (reanimated/interpolate subtitle-opacity [0 1] [-13 0])
|
||||||
|
subtitle-translate-y (reanimated/interpolate subtitle-opacity [0 1] [-85 0])
|
||||||
|
subtitle-scale (reanimated/interpolate subtitle-opacity [0 1] [0.9 1])
|
||||||
|
controls-translate-y (reanimated/interpolate subtitle-opacity [0 1] [85 0])]
|
||||||
|
[:<>
|
||||||
|
[rn/view {:style style/header-container}
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity subtitle-opacity
|
||||||
|
:transform [{:translate-y controls-translate-y}]}
|
||||||
|
{})}
|
||||||
|
[quo/button
|
||||||
|
{:icon true
|
||||||
|
:type :blur-bg
|
||||||
|
:size 32
|
||||||
|
:accessibility-label :close-sign-in-by-syncing
|
||||||
|
:override-theme :dark
|
||||||
|
:on-press (fn []
|
||||||
|
(if (and animated? reset-animations-fn)
|
||||||
|
(reset-animations-fn)
|
||||||
|
(rf/dispatch [:navigate-back])))}
|
||||||
|
:i/arrow-left]]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity subtitle-opacity
|
||||||
|
:transform [{:translate-y controls-translate-y}]}
|
||||||
|
{})}
|
||||||
|
[quo/button
|
||||||
|
{:before :i/info
|
||||||
|
:type :blur-bg
|
||||||
|
:size 32
|
||||||
|
:accessibility-label :find-sync-code
|
||||||
|
:override-theme :dark
|
||||||
|
:on-press #(rf/dispatch [:open-modal :find-sync-code])}
|
||||||
|
(i18n/label :t/find-sync-code)]]]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity title-opacity}
|
||||||
|
{})}
|
||||||
|
[quo/text
|
||||||
|
{:size :heading-1
|
||||||
|
:weight :semi-bold
|
||||||
|
:style style/header-text}
|
||||||
|
title]]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity subtitle-opacity
|
||||||
|
:transform [{:translate-x subtitle-translate-x}
|
||||||
|
{:translate-y subtitle-translate-y}
|
||||||
|
{:scale subtitle-scale}]}
|
||||||
|
{})}
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-1
|
||||||
|
:weight :regular
|
||||||
|
:style style/header-sub-text}
|
||||||
|
(i18n/label :t/synchronise-your-data-across-your-devices)]]
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity subtitle-opacity
|
||||||
|
:transform [{:translate-y controls-translate-y}]}
|
||||||
|
style/tabs-container)}
|
||||||
|
[quo/segmented-control
|
||||||
|
{:size 32
|
||||||
|
:override-theme :dark
|
||||||
|
:blur? true
|
||||||
|
:default-active @active-tab
|
||||||
|
:data [{:id 1 :label (i18n/label :t/scan-sync-qr-code)}
|
||||||
|
{:id 2 :label (i18n/label :t/enter-sync-code)}]
|
||||||
|
:on-change (fn [id]
|
||||||
|
(reset! active-tab id)
|
||||||
|
(reset! read-qr-once? false))}]]]))
|
||||||
|
|
||||||
(defn- header
|
(defn- header
|
||||||
[active-tab read-qr-once? title]
|
[props]
|
||||||
[:<>
|
[:f> f-header props])
|
||||||
[rn/view {:style style/header-container}
|
|
||||||
[quo/button
|
|
||||||
{:icon true
|
|
||||||
:type :blur-bg
|
|
||||||
:size 32
|
|
||||||
:accessibility-label :close-sign-in-by-syncing
|
|
||||||
:override-theme :dark
|
|
||||||
:on-press #(rf/dispatch [:navigate-back])}
|
|
||||||
:i/arrow-left]
|
|
||||||
[quo/button
|
|
||||||
{:before :i/info
|
|
||||||
:type :blur-bg
|
|
||||||
:size 32
|
|
||||||
:accessibility-label :find-sync-code
|
|
||||||
:override-theme :dark
|
|
||||||
:on-press #(rf/dispatch [:open-modal :find-sync-code])}
|
|
||||||
(i18n/label :t/find-sync-code)]]
|
|
||||||
[quo/text
|
|
||||||
{:size :heading-1
|
|
||||||
:weight :semi-bold
|
|
||||||
:style style/header-text}
|
|
||||||
title]
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-1
|
|
||||||
:weight :regular
|
|
||||||
:style style/header-sub-text}
|
|
||||||
(i18n/label :t/synchronise-your-data-across-your-devices)]
|
|
||||||
[rn/view {:style style/tabs-container}
|
|
||||||
[quo/segmented-control
|
|
||||||
{:size 32
|
|
||||||
:override-theme :dark
|
|
||||||
:blur? true
|
|
||||||
:default-active @active-tab
|
|
||||||
:data [{:id 1 :label (i18n/label :t/scan-sync-qr-code)}
|
|
||||||
{:id 2 :label (i18n/label :t/enter-sync-code)}]
|
|
||||||
:on-change (fn [id]
|
|
||||||
(reset! active-tab id)
|
|
||||||
(reset! read-qr-once? false))}]]])
|
|
||||||
|
|
||||||
(defn get-labels-and-on-press-method
|
(defn get-labels-and-on-press-method
|
||||||
[]
|
[]
|
||||||
|
@ -192,9 +233,6 @@
|
||||||
(defn- scan-qr-code-tab
|
(defn- scan-qr-code-tab
|
||||||
[qr-view-finder]
|
[qr-view-finder]
|
||||||
[:<>
|
[:<>
|
||||||
[rn/view {:style style/scan-qr-code-container}]
|
|
||||||
(when (empty? @qr-view-finder)
|
|
||||||
[qr-scan-hole-area qr-view-finder])
|
|
||||||
(if (and @preflight-check-passed?
|
(if (and @preflight-check-passed?
|
||||||
@camera-permission-granted?
|
@camera-permission-granted?
|
||||||
(boolean (not-empty @qr-view-finder)))
|
(boolean (not-empty @qr-view-finder)))
|
||||||
|
@ -210,24 +248,30 @@
|
||||||
:style {:color colors/white}}
|
:style {:color colors/white}}
|
||||||
"Yet to be implemented"]])
|
"Yet to be implemented"]])
|
||||||
|
|
||||||
(defn- bottom-view
|
(defn- f-bottom-view
|
||||||
[insets]
|
[insets translate-y]
|
||||||
[rn/touchable-without-feedback
|
[rn/touchable-without-feedback
|
||||||
{:on-press #(js/alert "Yet to be implemented")}
|
{:on-press #(js/alert "Yet to be implemented")}
|
||||||
[rn/view
|
[reanimated/view
|
||||||
{:style (style/bottom-container (:bottom insets))}
|
{:style (style/bottom-container translate-y (:bottom insets))}
|
||||||
[quo/text
|
[quo/text
|
||||||
{:size :paragraph-2
|
{:size :paragraph-2
|
||||||
:weight :medium
|
:weight :medium
|
||||||
:style style/bottom-text}
|
:style style/bottom-text}
|
||||||
(i18n/label :t/i-dont-have-status-on-another-device)]]])
|
(i18n/label :t/i-dont-have-status-on-another-device)]]])
|
||||||
|
|
||||||
|
(defn- bottom-view
|
||||||
|
[insets translate-y]
|
||||||
|
[:f> f-bottom-view insets translate-y])
|
||||||
|
|
||||||
(defn- check-qr-code-data
|
(defn- check-qr-code-data
|
||||||
[event]
|
[event]
|
||||||
(let [connection-string (string/trim (oops/oget event "nativeEvent.codeStringValue"))
|
(let [connection-string (string/trim (oops/oget event "nativeEvent.codeStringValue"))
|
||||||
valid-connection-string? (sync-utils/valid-connection-string? connection-string)]
|
valid-connection-string? (sync-utils/valid-connection-string? connection-string)]
|
||||||
(if valid-connection-string?
|
(if valid-connection-string?
|
||||||
(rf/dispatch [:syncing/input-connection-string-for-bootstrapping connection-string])
|
(debounce/debounce-and-dispatch [:syncing/input-connection-string-for-bootstrapping
|
||||||
|
connection-string]
|
||||||
|
300)
|
||||||
(rf/dispatch [:toasts/upsert
|
(rf/dispatch [:toasts/upsert
|
||||||
{:icon :i/info
|
{:icon :i/info
|
||||||
:icon-color colors/danger-50
|
:icon-color colors/danger-50
|
||||||
|
@ -262,47 +306,124 @@
|
||||||
:background-color colors/neutral-80-opa-80}]]]))
|
:background-color colors/neutral-80-opa-80}]]]))
|
||||||
|
|
||||||
(defn f-view
|
(defn f-view
|
||||||
[{:keys [title show-bottom-view? background]}]
|
[{:keys [title show-bottom-view? background animated?]}]
|
||||||
(let [insets (safe-area/get-insets)
|
(let [insets (safe-area/get-insets)
|
||||||
active-tab (reagent/atom 1)
|
active-tab (reagent/atom 1)
|
||||||
qr-view-finder (reagent/atom {})]
|
qr-view-finder (reagent/atom {})
|
||||||
|
render-camera? (reagent/atom false)]
|
||||||
(fn []
|
(fn []
|
||||||
(let [camera-ref (atom nil)
|
(let [camera-ref (atom nil)
|
||||||
read-qr-once? (atom false)
|
read-qr-once? (atom false)
|
||||||
;; The below check is to prevent scanning of any QR code
|
;; The below check is to prevent scanning of any QR code
|
||||||
;; when the user is in syncing progress screen
|
;; when the user is in syncing progress screen
|
||||||
user-in-syncing-progress-screen? (= (rf/sub [:view-id]) :syncing-progress)
|
user-in-syncing-progress-screen? (= (rf/sub [:view-id]) :syncing-progress)
|
||||||
on-read-code (fn [data]
|
on-read-code (fn [data]
|
||||||
(when (and (not @read-qr-once?)
|
(when (and (not @read-qr-once?)
|
||||||
(not user-in-syncing-progress-screen?))
|
(not user-in-syncing-progress-screen?))
|
||||||
(reset! read-qr-once? true)
|
(reset! read-qr-once? true)
|
||||||
(js/setTimeout (fn []
|
(js/setTimeout (fn []
|
||||||
(reset! read-qr-once? false))
|
(reset! read-qr-once? false))
|
||||||
3000)
|
3000)
|
||||||
(check-qr-code-data data)))
|
(check-qr-code-data data)))
|
||||||
scan-qr-code-tab? (= @active-tab 1)
|
scan-qr-code-tab? (= @active-tab 1)
|
||||||
show-camera? (and scan-qr-code-tab?
|
show-camera? (and scan-qr-code-tab?
|
||||||
@camera-permission-granted?
|
@camera-permission-granted?
|
||||||
@preflight-check-passed?)
|
@preflight-check-passed?)
|
||||||
show-holes? (and show-camera?
|
show-holes? (and show-camera?
|
||||||
(boolean (not-empty @qr-view-finder)))]
|
(boolean (not-empty @qr-view-finder)))
|
||||||
|
title-opacity (reanimated/use-shared-value (if animated? 0 1))
|
||||||
|
subtitle-opacity (reanimated/use-shared-value (if animated? 0 1))
|
||||||
|
content-opacity (reanimated/use-shared-value (if animated? 0 1))
|
||||||
|
content-translate-y (reanimated/interpolate subtitle-opacity [0 1] [85 0])
|
||||||
|
bottom-view-translate-y (reanimated/use-shared-value
|
||||||
|
(if animated? (+ 42.2 (:bottom insets)) 0))
|
||||||
|
reset-animations-fn
|
||||||
|
(fn []
|
||||||
|
(reset! render-camera? false)
|
||||||
|
(js/setTimeout
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:navigate-back])
|
||||||
|
(when @dismiss-animations
|
||||||
|
(@dismiss-animations))
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
content-opacity
|
||||||
|
0
|
||||||
|
(/ constants/onboarding-modal-animation-duration 8)
|
||||||
|
:easing4)
|
||||||
|
(reanimated/animate-shared-value-with-timing
|
||||||
|
subtitle-opacity
|
||||||
|
0
|
||||||
|
(- constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay)
|
||||||
|
:easing4)
|
||||||
|
(reanimated/animate-shared-value-with-timing title-opacity
|
||||||
|
0
|
||||||
|
0
|
||||||
|
:easing4))
|
||||||
|
(if show-camera? 500 0)))]
|
||||||
|
(when animated?
|
||||||
|
(reanimated/animate-shared-value-with-delay subtitle-opacity
|
||||||
|
1 constants/onboarding-modal-animation-duration
|
||||||
|
:easing4
|
||||||
|
(/
|
||||||
|
constants/onboarding-modal-animation-delay
|
||||||
|
2))
|
||||||
|
(reanimated/animate-shared-value-with-delay title-opacity
|
||||||
|
1 0
|
||||||
|
:easing4
|
||||||
|
(+ constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay))
|
||||||
|
(reanimated/animate-delay bottom-view-translate-y
|
||||||
|
0
|
||||||
|
(+ constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay)
|
||||||
|
100))
|
||||||
(rn/use-effect
|
(rn/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
|
(when animated?
|
||||||
|
(reanimated/animate-shared-value-with-delay content-opacity
|
||||||
|
1 constants/onboarding-modal-animation-duration
|
||||||
|
:easing4
|
||||||
|
(/
|
||||||
|
constants/onboarding-modal-animation-delay
|
||||||
|
2))
|
||||||
|
(js/setTimeout #(reset! render-camera? true)
|
||||||
|
(+ constants/onboarding-modal-animation-duration
|
||||||
|
constants/onboarding-modal-animation-delay
|
||||||
|
300))
|
||||||
|
(reset! navigate-back-fn reset-animations-fn))
|
||||||
(when-not @camera-permission-granted?
|
(when-not @camera-permission-granted?
|
||||||
(permissions/permission-granted? :camera
|
(permissions/permission-granted? :camera
|
||||||
#(reset! camera-permission-granted? %)
|
#(reset! camera-permission-granted? %)
|
||||||
#(reset! camera-permission-granted? false)))))
|
#(reset! camera-permission-granted? false)))))
|
||||||
[:<>
|
[:<>
|
||||||
background
|
background
|
||||||
[render-camera show-camera? @qr-view-finder camera-ref on-read-code show-holes?]
|
(when (or (not animated?) @render-camera?)
|
||||||
|
[render-camera show-camera? @qr-view-finder camera-ref on-read-code show-holes?])
|
||||||
[rn/view {:style (style/root-container (:top insets))}
|
[rn/view {:style (style/root-container (:top insets))}
|
||||||
[header active-tab read-qr-once? title]
|
[header
|
||||||
(case @active-tab
|
{:active-tab active-tab
|
||||||
1 [scan-qr-code-tab qr-view-finder]
|
:read-qr-once? read-qr-once?
|
||||||
2 [enter-sync-code-tab]
|
:title title
|
||||||
nil)
|
:title-opacity title-opacity
|
||||||
|
:subtitle-opacity subtitle-opacity
|
||||||
|
:reset-animations-fn reset-animations-fn
|
||||||
|
:animated? animated?}]
|
||||||
|
(when (empty? @qr-view-finder)
|
||||||
|
[:<>
|
||||||
|
[rn/view {:style style/scan-qr-code-container}]
|
||||||
|
[qr-scan-hole-area qr-view-finder]])
|
||||||
|
[reanimated/view
|
||||||
|
{:style (reanimated/apply-animations-to-style
|
||||||
|
{:opacity content-opacity
|
||||||
|
:transform [{:translate-y content-translate-y}]}
|
||||||
|
{})}
|
||||||
|
(case @active-tab
|
||||||
|
1 [scan-qr-code-tab qr-view-finder request-camera-permission]
|
||||||
|
2 [enter-sync-code-tab]
|
||||||
|
nil)]
|
||||||
[rn/view {:style style/flex-spacer}]
|
[rn/view {:style style/flex-spacer}]
|
||||||
(when show-bottom-view? [bottom-view insets])]]))))
|
(when show-bottom-view? [bottom-view insets bottom-view-translate-y])]]))))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[props]
|
[props]
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[re-frame.interop :as interop]
|
[re-frame.interop :as interop]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.languages :as react-native-languages]
|
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
[react-native.shake :as react-native-shake]
|
[react-native.shake :as react-native-shake]
|
||||||
[reagent.impl.batching :as batching]
|
[reagent.impl.batching :as batching]
|
||||||
|
@ -39,9 +38,8 @@
|
||||||
(global-error/register-handler)
|
(global-error/register-handler)
|
||||||
(notifications/listen-notifications)
|
(notifications/listen-notifications)
|
||||||
(.addEventListener rn/app-state "change" #(re-frame/dispatch [:app-state-change %]))
|
(.addEventListener rn/app-state "change" #(re-frame/dispatch [:app-state-change %]))
|
||||||
(react-native-languages/add-change-listener #(fn [lang]
|
(i18n/set-language "en")
|
||||||
(i18n/set-language lang)
|
(i18n-resources/load-language "en")
|
||||||
(i18n-resources/load-language lang)))
|
|
||||||
(react-native-shake/add-shake-listener #(re-frame/dispatch [:shake-event]))
|
(react-native-shake/add-shake-listener #(re-frame/dispatch [:shake-event]))
|
||||||
(utils.universal-links/initialize)
|
(utils.universal-links/initialize)
|
||||||
|
|
||||||
|
|
|
@ -164,11 +164,18 @@
|
||||||
|
|
||||||
(navigation/reg-button-pressed-listener
|
(navigation/reg-button-pressed-listener
|
||||||
(fn [id]
|
(fn [id]
|
||||||
(if (= "dismiss-modal" id)
|
(cond
|
||||||
|
(= "dismiss-modal" id)
|
||||||
(do
|
(do
|
||||||
(when-let [event (get-in views/screens [(last @state/modals) :on-dissmiss])]
|
(when-let [event (get-in views/screens [(last @state/modals) :on-dissmiss])]
|
||||||
(re-frame/dispatch event))
|
(re-frame/dispatch event))
|
||||||
(dissmissModal))
|
(dissmissModal))
|
||||||
|
(= "RNN.hardwareBackButton" id)
|
||||||
|
(when-let [handler (get-in views/screens
|
||||||
|
[(or (last @state/modals) @state/pushed-screen-id)
|
||||||
|
:hardware-back-button-handler])]
|
||||||
|
(handler))
|
||||||
|
:else
|
||||||
(when-let [handler (get-in views/screens [(keyword id) :right-handler])]
|
(when-let [handler (get-in views/screens [(keyword id) :right-handler])]
|
||||||
(handler)))))
|
(handler)))))
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
:orientation ["portrait"]
|
:orientation ["portrait"]
|
||||||
:backgroundColor colors/neutral-80-opa-80-blur})
|
:backgroundColor colors/neutral-80-opa-80-blur})
|
||||||
|
|
||||||
|
(def onboarding-transparent-layout
|
||||||
|
{:componentBackgroundColor :transparent
|
||||||
|
:orientation ["portrait"]
|
||||||
|
:backgroundColor :transparent})
|
||||||
|
|
||||||
(defn navbar
|
(defn navbar
|
||||||
([dark?]
|
([dark?]
|
||||||
{:navigationBar {:backgroundColor (if (or dark? (colors/dark?)) colors/neutral-100 colors/white)}})
|
{:navigationBar {:backgroundColor (if (or dark? (colors/dark?)) colors/neutral-100 colors/white)}})
|
||||||
|
|
|
@ -34,7 +34,37 @@
|
||||||
[status-im2.contexts.shell.share.view :as share]
|
[status-im2.contexts.shell.share.view :as share]
|
||||||
[status-im2.contexts.onboarding.syncing.results.view :as syncing-results]
|
[status-im2.contexts.onboarding.syncing.results.view :as syncing-results]
|
||||||
[status-im2.contexts.onboarding.syncing.progress.view :as syncing-devices]
|
[status-im2.contexts.onboarding.syncing.progress.view :as syncing-devices]
|
||||||
[status-im2.contexts.chat.new-chat.view :as new-chat]))
|
[status-im2.contexts.chat.new-chat.view :as new-chat]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[status-im2.constants :as constants]))
|
||||||
|
|
||||||
|
(def sign-in-modal-animations
|
||||||
|
{:showModal {:translationY {:from (:height (rn/get-window))
|
||||||
|
:to 0
|
||||||
|
:duration constants/onboarding-modal-animation-duration}
|
||||||
|
:alpha {:from 1
|
||||||
|
:to 1
|
||||||
|
:duration 0}}
|
||||||
|
:dismissModal {:translationY {:from 0
|
||||||
|
:to (:height (rn/get-window))
|
||||||
|
:duration constants/onboarding-modal-animation-duration}
|
||||||
|
:alpha {:from 1
|
||||||
|
:to 0
|
||||||
|
:duration constants/onboarding-modal-animation-duration}}})
|
||||||
|
|
||||||
|
(def push-animations-for-transparent-background
|
||||||
|
{:push {:content {:enter {:translationX {:from (:width (rn/get-window))
|
||||||
|
:to 0
|
||||||
|
:duration constants/onboarding-modal-animation-duration}}
|
||||||
|
:exit {:translationX {:from 0
|
||||||
|
:to (- (:width (rn/get-window)))
|
||||||
|
:duration constants/onboarding-modal-animation-duration}}}}
|
||||||
|
:pop {:content {:exit {:translationX {:from 0
|
||||||
|
:to (:width (rn/get-window))
|
||||||
|
:duration constants/onboarding-modal-animation-duration}}
|
||||||
|
:enter {:translationX {:from (- (:width (rn/get-window)))
|
||||||
|
:to 0
|
||||||
|
:duration constants/onboarding-modal-animation-duration}}}}})
|
||||||
|
|
||||||
(defn screens
|
(defn screens
|
||||||
[]
|
[]
|
||||||
|
@ -164,12 +194,26 @@
|
||||||
:popGesture false
|
:popGesture false
|
||||||
:hardwareBackButton {:dismissModalOnPress false
|
:hardwareBackButton {:dismissModalOnPress false
|
||||||
:popStackOnPress false}}}
|
:popStackOnPress false}}}
|
||||||
|
|
||||||
{:name :scan-sync-code-page
|
{:name :scan-sync-code-page
|
||||||
:options options/dark-screen
|
:options options/dark-screen
|
||||||
:component scan-sync-code-page/view}
|
:component scan-sync-code-page/view}
|
||||||
|
|
||||||
|
{:name :sign-in-intro
|
||||||
|
:options {:layout options/onboarding-transparent-layout
|
||||||
|
:animations (merge
|
||||||
|
sign-in-modal-animations
|
||||||
|
push-animations-for-transparent-background)
|
||||||
|
:modalPresentationStyle :overCurrentContext
|
||||||
|
:hardwareBackButton {:dismissModalOnPress false
|
||||||
|
:popStackOnPress false}}
|
||||||
|
:hardware-back-button-handler sign-in/navigate-back
|
||||||
|
:component sign-in/animated-view}
|
||||||
|
|
||||||
{:name :sign-in
|
{:name :sign-in
|
||||||
:options {:layout options/onboarding-layout}
|
:options {:theme :dark
|
||||||
|
:modalPresentationStyle :overCurrentContext
|
||||||
|
:layout options/onboarding-layout}
|
||||||
:component sign-in/view}
|
:component sign-in/view}
|
||||||
|
|
||||||
{:name :syncing-progress
|
{:name :syncing-progress
|
||||||
|
@ -178,6 +222,13 @@
|
||||||
:popGesture false}
|
:popGesture false}
|
||||||
:component syncing-devices/view}
|
:component syncing-devices/view}
|
||||||
|
|
||||||
|
{:name :syncing-progress-intro
|
||||||
|
:options {:theme :dark
|
||||||
|
:layout options/onboarding-transparent-layout
|
||||||
|
:animations push-animations-for-transparent-background
|
||||||
|
:popGesture false}
|
||||||
|
:component syncing-devices/view-onboarding}
|
||||||
|
|
||||||
{:name :syncing-results
|
{:name :syncing-results
|
||||||
:options {:theme :dark}
|
:options {:theme :dark}
|
||||||
:component syncing-results/view}
|
:component syncing-results/view}
|
||||||
|
|
Loading…
Reference in New Issue