chore: update ui for syncing page for onboarding and in profile (#15623)
This commit is contained in:
parent
05073e7453
commit
4b2d62ee1f
|
@ -1,241 +1,11 @@
|
||||||
(ns status-im2.contexts.onboarding.sign-in.view
|
(ns status-im2.contexts.onboarding.sign-in.view
|
||||||
(:require [clojure.string :as string]
|
(:require [utils.i18n :as i18n]
|
||||||
[oops.core :as oops]
|
|
||||||
[quo2.core :as quo]
|
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[react-native.blur :as blur]
|
|
||||||
[react-native.camera-kit :as camera-kit]
|
|
||||||
[react-native.core :as rn]
|
|
||||||
[react-native.hole-view :as hole-view]
|
|
||||||
[react-native.permissions :as permissions]
|
|
||||||
[react-native.platform :as platform]
|
|
||||||
[react-native.safe-area :as safe-area]
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[status-im2.constants :as constants]
|
|
||||||
[status-im2.contexts.onboarding.common.background.view :as background]
|
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||||
[status-im2.contexts.onboarding.sign-in.style :as style]
|
[status-im2.contexts.syncing.scan-sync-code.view :as scan-sync-code]))
|
||||||
[utils.i18n :as i18n]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[utils.transforms :as transforms]))
|
|
||||||
|
|
||||||
(defonce camera-permission-granted? (reagent/atom false))
|
|
||||||
|
|
||||||
(defn- header
|
|
||||||
[active-tab read-qr-once?]
|
|
||||||
[:<>
|
|
||||||
[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/close]
|
|
||||||
[quo/button
|
|
||||||
{:before :i/info
|
|
||||||
:type :blur-bg
|
|
||||||
:size 32
|
|
||||||
:accessibility-label :find-sync-code
|
|
||||||
:override-theme :dark
|
|
||||||
:on-press #(js/alert "Yet to be implemented")}
|
|
||||||
(i18n/label :t/find-sync-code)]]
|
|
||||||
[quo/text
|
|
||||||
{:size :heading-1
|
|
||||||
:weight :semi-bold
|
|
||||||
:style style/header-text}
|
|
||||||
(i18n/label :t/sign-in-by-syncing)]
|
|
||||||
[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- camera-permission-view
|
|
||||||
[request-camera-permission]
|
|
||||||
[rn/view {:style style/camera-permission-container}
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-1
|
|
||||||
:weight :medium
|
|
||||||
:style style/enable-camera-access-header}
|
|
||||||
(i18n/label :t/enable-access-to-camera)]
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-2
|
|
||||||
:weight :regular
|
|
||||||
:style style/enable-camera-access-sub-text}
|
|
||||||
(i18n/label :t/to-scan-a-qr-enable-your-camera)]
|
|
||||||
[quo/button
|
|
||||||
{:before :i/camera
|
|
||||||
:type :primary
|
|
||||||
:size 32
|
|
||||||
:accessibility-label :request-camera-permission
|
|
||||||
:override-theme :dark
|
|
||||||
:on-press request-camera-permission}
|
|
||||||
(i18n/label :t/enable-camera)]])
|
|
||||||
|
|
||||||
(defn- qr-scan-hole-area
|
|
||||||
[qr-view-finder]
|
|
||||||
[rn/view
|
|
||||||
{:style style/qr-view-finder
|
|
||||||
:on-layout (fn [event]
|
|
||||||
(let [layout (transforms/js->clj (oops/oget event "nativeEvent.layout"))
|
|
||||||
width (:width layout)
|
|
||||||
y (if platform/android?
|
|
||||||
(+ (safe-area/get-top) (:y layout))
|
|
||||||
(:y layout))
|
|
||||||
view-finder (-> layout
|
|
||||||
(assoc :height width)
|
|
||||||
(assoc :y y))]
|
|
||||||
(reset! qr-view-finder view-finder)))}])
|
|
||||||
|
|
||||||
|
|
||||||
(defn- border
|
|
||||||
[border1 border2 corner]
|
|
||||||
[rn/view
|
|
||||||
(assoc {:border-color colors/white :width 80 :height 80} border1 2 border2 2 corner 16)])
|
|
||||||
|
|
||||||
(defn- viewfinder
|
|
||||||
[qr-view-finder]
|
|
||||||
(let [size (:width qr-view-finder)]
|
|
||||||
[rn/view {:style (style/viewfinder-container qr-view-finder)}
|
|
||||||
[rn/view {:width size :height size :justify-content :space-between}
|
|
||||||
[rn/view {:flex-direction :row :justify-content :space-between}
|
|
||||||
[border :border-top-width :border-left-width :border-top-left-radius]
|
|
||||||
[border :border-top-width :border-right-width :border-top-right-radius]]
|
|
||||||
[rn/view {:flex-direction :row :justify-content :space-between}
|
|
||||||
[border :border-bottom-width :border-left-width :border-bottom-left-radius]
|
|
||||||
[border :border-bottom-width :border-right-width :border-bottom-right-radius]]]
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-2
|
|
||||||
:weight :regular
|
|
||||||
:style style/viewfinder-text}
|
|
||||||
(i18n/label :t/ensure-qr-code-is-in-focus-to-scan)]]))
|
|
||||||
|
|
||||||
(defn- scan-qr-code-tab
|
|
||||||
[qr-view-finder request-camera-permission]
|
|
||||||
[:<>
|
|
||||||
[rn/view {:style style/scan-qr-code-container}]
|
|
||||||
(when (empty? @qr-view-finder)
|
|
||||||
[qr-scan-hole-area qr-view-finder])
|
|
||||||
(if (and @camera-permission-granted? (boolean (not-empty @qr-view-finder)))
|
|
||||||
[viewfinder @qr-view-finder]
|
|
||||||
[camera-permission-view request-camera-permission])])
|
|
||||||
|
|
||||||
(defn- enter-sync-code-tab
|
|
||||||
[]
|
|
||||||
[rn/view {:style style/enter-sync-code-container}
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-1
|
|
||||||
:weight :medium
|
|
||||||
:style {:color colors/white}}
|
|
||||||
"Yet to be implemented"]])
|
|
||||||
|
|
||||||
(defn- bottom-view
|
|
||||||
[insets]
|
|
||||||
[rn/touchable-without-feedback
|
|
||||||
{:on-press #(js/alert "Yet to be implemented")}
|
|
||||||
[rn/view
|
|
||||||
{:style (style/bottom-container (:bottom insets))}
|
|
||||||
[quo/text
|
|
||||||
{:size :paragraph-2
|
|
||||||
:weight :regular
|
|
||||||
:style style/bottom-text}
|
|
||||||
(i18n/label :t/i-dont-have-status-on-another-device)]]])
|
|
||||||
|
|
||||||
(defn- check-qr-code-data
|
|
||||||
[event]
|
|
||||||
(let [connection-string (string/trim (oops/oget event "nativeEvent.codeStringValue"))
|
|
||||||
valid-connection-string? (string/starts-with?
|
|
||||||
connection-string
|
|
||||||
constants/local-pairing-connection-string-identifier)]
|
|
||||||
(if valid-connection-string?
|
|
||||||
(rf/dispatch [:syncing/input-connection-string-for-bootstrapping connection-string])
|
|
||||||
(rf/dispatch [:toasts/upsert
|
|
||||||
{:icon :i/info
|
|
||||||
:icon-color colors/danger-50
|
|
||||||
:override-theme :light
|
|
||||||
:text (i18n/label :t/error-this-is-not-a-sync-qr-code)}]))))
|
|
||||||
|
|
||||||
(defn f-view
|
|
||||||
[]
|
|
||||||
(let [camera-ref (atom nil)
|
|
||||||
read-qr-once? (atom false)
|
|
||||||
insets (safe-area/get-insets)
|
|
||||||
active-tab (reagent/atom 1)
|
|
||||||
qr-view-finder (reagent/atom {})
|
|
||||||
{:keys [height width]} (rf/sub [:dimensions/window])
|
|
||||||
request-camera-permission (fn []
|
|
||||||
(rf/dispatch
|
|
||||||
[:request-permissions
|
|
||||||
{:permissions [:camera]
|
|
||||||
:on-allowed #(reset! camera-permission-granted? true)
|
|
||||||
:on-denied #(rf/dispatch
|
|
||||||
[:toasts/upsert
|
|
||||||
{:icon :i/info
|
|
||||||
:icon-color colors/danger-50
|
|
||||||
:override-theme :light
|
|
||||||
:text (i18n/label
|
|
||||||
:t/camera-permission-denied)}])}]))]
|
|
||||||
(fn []
|
|
||||||
(let [holes (merge @qr-view-finder {:borderRadius 16})
|
|
||||||
scan-qr-code-tab? (= @active-tab 1)
|
|
||||||
show-camera? (and scan-qr-code-tab? @camera-permission-granted?)
|
|
||||||
show-holes? (and show-camera?
|
|
||||||
(boolean (not-empty @qr-view-finder)))
|
|
||||||
on-read-code (fn [data]
|
|
||||||
(when-not @read-qr-once?
|
|
||||||
(reset! read-qr-once? true)
|
|
||||||
(js/setTimeout (fn []
|
|
||||||
(reset! read-qr-once? false))
|
|
||||||
3000)
|
|
||||||
(check-qr-code-data data)))
|
|
||||||
hole-view-wrapper (if show-camera?
|
|
||||||
[hole-view/hole-view
|
|
||||||
{:style style/absolute-fill
|
|
||||||
:holes (if show-holes?
|
|
||||||
[holes]
|
|
||||||
[])}]
|
|
||||||
[:<>])]
|
|
||||||
(rn/use-effect
|
|
||||||
(fn []
|
|
||||||
(when-not @camera-permission-granted?
|
|
||||||
(permissions/permission-granted? :camera
|
|
||||||
#(reset! camera-permission-granted? %)
|
|
||||||
#(reset! camera-permission-granted? false)))))
|
|
||||||
[rn/view {:style (style/root-container (:top insets))}
|
|
||||||
(if show-camera?
|
|
||||||
[camera-kit/camera
|
|
||||||
{:ref #(reset! camera-ref %)
|
|
||||||
:style (merge style/absolute-fill {:height height :width width})
|
|
||||||
:camera-options {:zoomMode :off}
|
|
||||||
:scan-barcode true
|
|
||||||
:on-read-code on-read-code}]
|
|
||||||
[background/view true])
|
|
||||||
(conj hole-view-wrapper
|
|
||||||
[blur/view
|
|
||||||
{:style style/absolute-fill
|
|
||||||
:overlay-color colors/neutral-80-opa-80
|
|
||||||
:blur-type :dark
|
|
||||||
:blur-amount (if platform/ios? 15 5)}])
|
|
||||||
[header active-tab read-qr-once?]
|
|
||||||
(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}]
|
|
||||||
[bottom-view insets]]))))
|
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[]
|
[]
|
||||||
[:f> f-view])
|
[scan-sync-code/view
|
||||||
|
{:title (i18n/label :t/sign-in-by-syncing)
|
||||||
|
:show-bottom-view? true
|
||||||
|
:background [background/view true]}])
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
(ns status-im2.contexts.syncing.scan-sync-code.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]
|
||||||
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
|
(def screen-padding 20)
|
||||||
|
|
||||||
|
(def flex-spacer {:flex 1})
|
||||||
|
|
||||||
|
(def absolute-fill
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:left 0
|
||||||
|
:right 0})
|
||||||
|
|
||||||
|
(def hole
|
||||||
|
(merge absolute-fill
|
||||||
|
{:z-index 2 :opacity 0.95}))
|
||||||
|
|
||||||
|
(defn root-container
|
||||||
|
[padding-top]
|
||||||
|
{:z-index 5
|
||||||
|
:flex 1
|
||||||
|
:padding-top padding-top})
|
||||||
|
|
||||||
|
(def header-container
|
||||||
|
{:flex-direction :row
|
||||||
|
:justify-content :space-between
|
||||||
|
:padding-horizontal screen-padding
|
||||||
|
:margin-vertical 12})
|
||||||
|
|
||||||
|
(def header-text
|
||||||
|
{:padding-horizontal screen-padding
|
||||||
|
:padding-top 12
|
||||||
|
:padding-bottom 8
|
||||||
|
:color colors/white})
|
||||||
|
|
||||||
|
(def header-sub-text
|
||||||
|
{:padding-horizontal screen-padding
|
||||||
|
:color colors/white})
|
||||||
|
|
||||||
|
(def tabs-container
|
||||||
|
{:padding-horizontal screen-padding
|
||||||
|
:margin-top 20})
|
||||||
|
|
||||||
|
(def scan-qr-code-container
|
||||||
|
{:margin-top 19})
|
||||||
|
|
||||||
|
(def qr-view-finder
|
||||||
|
{:margin-horizontal screen-padding
|
||||||
|
:height 1
|
||||||
|
:display :flex})
|
||||||
|
|
||||||
|
(defn viewfinder-container
|
||||||
|
[viewfinder]
|
||||||
|
{:position :absolute
|
||||||
|
:left (:x viewfinder)
|
||||||
|
:top (:y viewfinder)
|
||||||
|
:overflow :hidden})
|
||||||
|
|
||||||
|
(def viewfinder-text
|
||||||
|
{:color colors/white-opa-70
|
||||||
|
:text-align :center
|
||||||
|
:padding-top 16})
|
||||||
|
|
||||||
|
(def camera-permission-container
|
||||||
|
{:height 335
|
||||||
|
:margin-horizontal screen-padding
|
||||||
|
:background-color colors/white-opa-5
|
||||||
|
:border-color colors/white-opa-10
|
||||||
|
:border-radius 12
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(def enable-camera-access-header
|
||||||
|
{:color colors/white})
|
||||||
|
|
||||||
|
(def enable-camera-access-sub-text
|
||||||
|
{:color colors/white-opa-70
|
||||||
|
:margin-bottom 16})
|
||||||
|
|
||||||
|
(def enter-sync-code-container
|
||||||
|
{:margin-top 20
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn bottom-container
|
||||||
|
[padding-bottom]
|
||||||
|
{:z-index 6
|
||||||
|
:padding-top 12
|
||||||
|
:padding-bottom padding-bottom
|
||||||
|
:background-color colors/white-opa-5
|
||||||
|
:border-top-left-radius 20
|
||||||
|
:border-top-right-radius 20
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(def bottom-text
|
||||||
|
{:color colors/white
|
||||||
|
:padding-bottom 12})
|
||||||
|
|
||||||
|
(def camera-style
|
||||||
|
{:height "100%"
|
||||||
|
:borderRadius 16
|
||||||
|
:background-color :transparent})
|
||||||
|
|
||||||
|
(def camera-container
|
||||||
|
{:position :absolute
|
||||||
|
:top (if platform/android? 40 0)
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom 0
|
||||||
|
:border-radius 16})
|
|
@ -0,0 +1,239 @@
|
||||||
|
(ns status-im2.contexts.syncing.scan-sync-code.view
|
||||||
|
(:require [clojure.string :as string]
|
||||||
|
[oops.core :as oops]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[react-native.camera-kit :as camera-kit]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[react-native.blur :as blur]
|
||||||
|
[react-native.hole-view :as hole-view]
|
||||||
|
[react-native.permissions :as permissions]
|
||||||
|
[react-native.safe-area :as safe-area]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[status-im2.contexts.syncing.scan-sync-code.style :as style]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[status-im2.contexts.syncing.utils :as sync-utils]))
|
||||||
|
|
||||||
|
(defonce camera-permission-granted? (reagent/atom false))
|
||||||
|
|
||||||
|
(defn- header
|
||||||
|
[active-tab read-qr-once? title]
|
||||||
|
[:<>
|
||||||
|
[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/close]
|
||||||
|
[quo/button
|
||||||
|
{:before :i/info
|
||||||
|
:type :blur-bg
|
||||||
|
:size 32
|
||||||
|
:accessibility-label :find-sync-code
|
||||||
|
:override-theme :dark
|
||||||
|
:on-press #(js/alert "Yet to be implemented")}
|
||||||
|
(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- camera-permission-view
|
||||||
|
[request-camera-permission]
|
||||||
|
[rn/view {:style style/camera-permission-container}
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-1
|
||||||
|
:weight :medium
|
||||||
|
:style style/enable-camera-access-header}
|
||||||
|
(i18n/label :t/enable-access-to-camera)]
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :regular
|
||||||
|
:style style/enable-camera-access-sub-text}
|
||||||
|
(i18n/label :t/to-scan-a-qr-enable-your-camera)]
|
||||||
|
[quo/button
|
||||||
|
{:before :i/camera
|
||||||
|
:type :primary
|
||||||
|
:size 32
|
||||||
|
:accessibility-label :request-camera-permission
|
||||||
|
:override-theme :dark
|
||||||
|
:on-press request-camera-permission}
|
||||||
|
(i18n/label :t/enable-camera)]])
|
||||||
|
|
||||||
|
(defn- qr-scan-hole-area
|
||||||
|
[qr-view-finder]
|
||||||
|
[rn/view
|
||||||
|
{:style style/qr-view-finder
|
||||||
|
:on-layout (fn [event]
|
||||||
|
(let [layout (js->clj (oops/oget event "nativeEvent.layout")
|
||||||
|
:keywordize-keys
|
||||||
|
true)
|
||||||
|
view-finder (assoc layout :height (:width layout))]
|
||||||
|
(reset! qr-view-finder view-finder)))}])
|
||||||
|
|
||||||
|
(defn- border
|
||||||
|
[border1 border2 corner]
|
||||||
|
[rn/view
|
||||||
|
(assoc {:border-color colors/white :width 80 :height 80} border1 2 border2 2 corner 16)])
|
||||||
|
|
||||||
|
(defn- viewfinder
|
||||||
|
[qr-view-finder]
|
||||||
|
(let [size (:width qr-view-finder)]
|
||||||
|
[:<>
|
||||||
|
[rn/view {:style (style/viewfinder-container qr-view-finder)}
|
||||||
|
|
||||||
|
[rn/view {:width size :height size :justify-content :space-between}
|
||||||
|
[rn/view {:flex-direction :row :justify-content :space-between}
|
||||||
|
[border :border-top-width :border-left-width :border-top-left-radius]
|
||||||
|
[border :border-top-width :border-right-width :border-top-right-radius]]
|
||||||
|
[rn/view {:flex-direction :row :justify-content :space-between}
|
||||||
|
[border :border-bottom-width :border-left-width :border-bottom-left-radius]
|
||||||
|
[border :border-bottom-width :border-right-width :border-bottom-right-radius]]]
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :regular
|
||||||
|
:style style/viewfinder-text}
|
||||||
|
(i18n/label :t/ensure-qr-code-is-in-focus-to-scan)]]]))
|
||||||
|
|
||||||
|
(defn- scan-qr-code-tab
|
||||||
|
[qr-view-finder request-camera-permission]
|
||||||
|
[:<>
|
||||||
|
[rn/view {:style style/scan-qr-code-container}]
|
||||||
|
(when (empty? @qr-view-finder)
|
||||||
|
[qr-scan-hole-area qr-view-finder])
|
||||||
|
(if (and @camera-permission-granted? (boolean (not-empty @qr-view-finder)))
|
||||||
|
[viewfinder @qr-view-finder]
|
||||||
|
[camera-permission-view request-camera-permission])])
|
||||||
|
|
||||||
|
(defn- enter-sync-code-tab
|
||||||
|
[]
|
||||||
|
[rn/view {:style style/enter-sync-code-container}
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-1
|
||||||
|
:weight :medium
|
||||||
|
:style {:color colors/white}}
|
||||||
|
"Yet to be implemented"]])
|
||||||
|
|
||||||
|
(defn- bottom-view
|
||||||
|
[insets]
|
||||||
|
[rn/touchable-without-feedback
|
||||||
|
{:on-press #(js/alert "Yet to be implemented")}
|
||||||
|
[rn/view
|
||||||
|
{:style (style/bottom-container (:bottom insets))}
|
||||||
|
[quo/text
|
||||||
|
{:size :paragraph-2
|
||||||
|
:weight :regular
|
||||||
|
:style style/bottom-text}
|
||||||
|
(i18n/label :t/i-dont-have-status-on-another-device)]]])
|
||||||
|
|
||||||
|
(defn- check-qr-code-data
|
||||||
|
[event]
|
||||||
|
(let [connection-string (string/trim (oops/oget event "nativeEvent.codeStringValue"))
|
||||||
|
valid-connection-string? (sync-utils/valid-connection-string? connection-string)]
|
||||||
|
(if valid-connection-string?
|
||||||
|
(rf/dispatch [:syncing/input-connection-string-for-bootstrapping connection-string])
|
||||||
|
(rf/dispatch [:toasts/upsert
|
||||||
|
{:icon :i/info
|
||||||
|
:icon-color colors/danger-50
|
||||||
|
:override-theme :light
|
||||||
|
:text (i18n/label :t/error-this-is-not-a-sync-qr-code)}]))))
|
||||||
|
|
||||||
|
(defn render-camera
|
||||||
|
[show-camera? qr-view-finder camera-ref on-read-code show-holes?]
|
||||||
|
(when (and show-camera? (:x qr-view-finder))
|
||||||
|
[:<>
|
||||||
|
[rn/view {:style style/camera-container}
|
||||||
|
[camera-kit/camera
|
||||||
|
{:ref #(reset! camera-ref %)
|
||||||
|
:style style/camera-style
|
||||||
|
:camera-options {:zoomMode :off}
|
||||||
|
:scan-barcode true
|
||||||
|
:on-read-code on-read-code}]]
|
||||||
|
[hole-view/hole-view
|
||||||
|
{:style style/hole
|
||||||
|
:holes (if show-holes?
|
||||||
|
[(merge qr-view-finder
|
||||||
|
{:borderRadius 16})]
|
||||||
|
[])}
|
||||||
|
[blur/view
|
||||||
|
{:style style/absolute-fill
|
||||||
|
:blur-amount 10
|
||||||
|
:blur-type :transparent
|
||||||
|
:overlay-color colors/neutral-80-opa-80
|
||||||
|
:background-color colors/neutral-80-opa-80}]
|
||||||
|
]]))
|
||||||
|
|
||||||
|
(defn f-view
|
||||||
|
[{:keys [title show-bottom-view? background]}]
|
||||||
|
(let [insets (safe-area/get-insets)
|
||||||
|
active-tab (reagent/atom 1)
|
||||||
|
qr-view-finder (reagent/atom {})
|
||||||
|
request-camera-permission (fn []
|
||||||
|
(rf/dispatch
|
||||||
|
[:request-permissions
|
||||||
|
{:permissions [:camera]
|
||||||
|
:on-allowed #(reset! camera-permission-granted? true)
|
||||||
|
:on-denied #(rf/dispatch
|
||||||
|
[:toasts/upsert
|
||||||
|
{:icon :i/info
|
||||||
|
:icon-color colors/danger-50
|
||||||
|
:override-theme :light
|
||||||
|
:text (i18n/label
|
||||||
|
:t/camera-permission-denied)}])}]))]
|
||||||
|
(fn []
|
||||||
|
(let [camera-ref (atom nil)
|
||||||
|
read-qr-once? (atom false)
|
||||||
|
on-read-code (fn [data]
|
||||||
|
(when-not @read-qr-once?
|
||||||
|
(reset! read-qr-once? true)
|
||||||
|
(js/setTimeout (fn []
|
||||||
|
(reset! read-qr-once? false))
|
||||||
|
3000)
|
||||||
|
(check-qr-code-data data)))
|
||||||
|
scan-qr-code-tab? (= @active-tab 1)
|
||||||
|
show-camera? (and scan-qr-code-tab? @camera-permission-granted?)
|
||||||
|
show-holes? (and show-camera?
|
||||||
|
(boolean (not-empty @qr-view-finder)))]
|
||||||
|
(rn/use-effect
|
||||||
|
(fn []
|
||||||
|
(when-not @camera-permission-granted?
|
||||||
|
(permissions/permission-granted? :camera
|
||||||
|
#(reset! camera-permission-granted? %)
|
||||||
|
#(reset! camera-permission-granted? false)))))
|
||||||
|
[:<>
|
||||||
|
background
|
||||||
|
[render-camera show-camera? @qr-view-finder camera-ref on-read-code show-holes?]
|
||||||
|
[rn/view {:style (style/root-container (:top insets))}
|
||||||
|
[header active-tab read-qr-once? title]
|
||||||
|
(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}]
|
||||||
|
(when show-bottom-view? [bottom-view insets])
|
||||||
|
]]))))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[props]
|
||||||
|
[:f> f-view props])
|
|
@ -0,0 +1,10 @@
|
||||||
|
(ns status-im2.contexts.syncing.scan-sync-code-page.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def background
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:background-color colors/neutral-95})
|
|
@ -0,0 +1,12 @@
|
||||||
|
(ns status-im2.contexts.syncing.scan-sync-code-page.view
|
||||||
|
(:require [react-native.core :as rn]
|
||||||
|
[status-im2.contexts.syncing.scan-sync-code-page.style :as style]
|
||||||
|
[status-im2.contexts.syncing.scan-sync-code.view :as scan-sync-code]
|
||||||
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
|
(defn view
|
||||||
|
[]
|
||||||
|
[scan-sync-code/view
|
||||||
|
{:title (i18n/label :t/scan-sync-code)
|
||||||
|
:background [rn/view
|
||||||
|
{:style style/background} true]}])
|
|
@ -1,20 +1,19 @@
|
||||||
(ns status-im2.contexts.syncing.setup-syncing.view
|
(ns status-im2.contexts.syncing.setup-syncing.view
|
||||||
(:require [utils.i18n :as i18n]
|
(:require [utils.i18n :as i18n]
|
||||||
[clojure.string :as string]
|
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
[quo2.foundations.colors :as colors]
|
[quo2.foundations.colors :as colors]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[utils.datetime :as datetime]
|
[utils.datetime :as datetime]
|
||||||
[status-im2.contexts.syncing.setup-syncing.style :as style]
|
[status-im2.contexts.syncing.setup-syncing.style :as style]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[status-im2.constants :as constants]
|
|
||||||
[react-native.clipboard :as clipboard]
|
[react-native.clipboard :as clipboard]
|
||||||
[status-im2.contexts.syncing.sheets.enter-password.view :as enter-password]
|
[status-im2.contexts.syncing.sheets.enter-password.view :as enter-password]
|
||||||
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
|
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im2.common.resources :as resources]
|
[status-im2.common.resources :as resources]
|
||||||
[react-native.hooks :as hooks]
|
[react-native.hooks :as hooks]
|
||||||
[react-native.safe-area :as safe-area]))
|
[react-native.safe-area :as safe-area]
|
||||||
|
[status-im2.contexts.syncing.utils :as sync-utils]))
|
||||||
|
|
||||||
(def code-valid-for-ms 120000)
|
(def code-valid-for-ms 120000)
|
||||||
(def one-min-ms 60000)
|
(def one-min-ms 60000)
|
||||||
|
@ -35,13 +34,6 @@
|
||||||
:icon-override-theme :dark
|
:icon-override-theme :dark
|
||||||
:on-press #(rf/dispatch [:open-modal :how-to-pair])}]}]])
|
:on-press #(rf/dispatch [:open-modal :how-to-pair])}]}]])
|
||||||
|
|
||||||
(defn valid-cs?
|
|
||||||
[connection-string]
|
|
||||||
(when connection-string
|
|
||||||
(string/starts-with?
|
|
||||||
connection-string
|
|
||||||
constants/local-pairing-connection-string-identifier)))
|
|
||||||
|
|
||||||
(defn f-use-interval
|
(defn f-use-interval
|
||||||
[clock cleanup-clock delay]
|
[clock cleanup-clock delay]
|
||||||
(hooks/use-interval clock cleanup-clock delay))
|
(hooks/use-interval clock cleanup-clock delay))
|
||||||
|
@ -53,7 +45,7 @@
|
||||||
delay (reagent/atom nil)
|
delay (reagent/atom nil)
|
||||||
timestamp (reagent/atom nil)
|
timestamp (reagent/atom nil)
|
||||||
set-code (fn [connection-string]
|
set-code (fn [connection-string]
|
||||||
(when (valid-cs? connection-string)
|
(when (sync-utils/valid-connection-string? connection-string)
|
||||||
(reset! timestamp (* 1000 (js/Math.ceil (/ (datetime/timestamp) 1000))))
|
(reset! timestamp (* 1000 (js/Math.ceil (/ (datetime/timestamp) 1000))))
|
||||||
(reset! delay 1000)
|
(reset! delay 1000)
|
||||||
(reset! code connection-string)))
|
(reset! code connection-string)))
|
||||||
|
@ -84,14 +76,14 @@
|
||||||
:weight :semi-bold
|
:weight :semi-bold
|
||||||
:style {:color colors/white}}
|
:style {:color colors/white}}
|
||||||
(i18n/label :t/setup-syncing)]]
|
(i18n/label :t/setup-syncing)]]
|
||||||
[rn/view {:style (style/qr-container (valid-cs? @code))}
|
[rn/view {:style (style/qr-container (sync-utils/valid-connection-string? @code))}
|
||||||
(if (valid-cs? @code)
|
(if (sync-utils/valid-connection-string? @code)
|
||||||
[qr-code-viewer/qr-code-view 331 @code]
|
[qr-code-viewer/qr-code-view 331 @code]
|
||||||
[quo/qr-code
|
[quo/qr-code
|
||||||
{:source (resources/get-image :qr-code)
|
{:source (resources/get-image :qr-code)
|
||||||
:height 220
|
:height 220
|
||||||
:width "100%"}])
|
:width "100%"}])
|
||||||
(when-not (valid-cs? @code)
|
(when-not (sync-utils/valid-connection-string? @code)
|
||||||
[quo/button
|
[quo/button
|
||||||
{:on-press (fn []
|
{:on-press (fn []
|
||||||
;TODO https://github.com/status-im/status-mobile/issues/15570
|
;TODO https://github.com/status-im/status-mobile/issues/15570
|
||||||
|
@ -103,7 +95,7 @@
|
||||||
:size 40
|
:size 40
|
||||||
:style style/generate-button
|
:style style/generate-button
|
||||||
:before :i/reveal} (i18n/label :t/reveal-sync-code)])
|
:before :i/reveal} (i18n/label :t/reveal-sync-code)])
|
||||||
(when (valid-cs? @code)
|
(when (sync-utils/valid-connection-string? @code)
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style style/valid-cs-container}
|
{:style style/valid-cs-container}
|
||||||
[rn/view
|
[rn/view
|
||||||
|
@ -144,5 +136,5 @@
|
||||||
[quo/action-drawer
|
[quo/action-drawer
|
||||||
[[{:icon :i/scan
|
[[{:icon :i/scan
|
||||||
:override-theme :dark
|
:override-theme :dark
|
||||||
:on-press #(js/alert "to be implemented")
|
:on-press #(rf/dispatch [:navigate-to :scan-sync-code-page])
|
||||||
:label (i18n/label :t/scan-or-enter-sync-code)}]]]]]])))
|
:label (i18n/label :t/scan-or-enter-sync-code)}]]]]]])))
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
(ns status-im2.contexts.syncing.utils
|
||||||
|
(:require [clojure.string :as string]
|
||||||
|
[status-im2.constants :as constants]))
|
||||||
|
|
||||||
|
(defn valid-connection-string?
|
||||||
|
[connection-string]
|
||||||
|
(when connection-string
|
||||||
|
(string/starts-with?
|
||||||
|
connection-string
|
||||||
|
constants/local-pairing-connection-string-identifier)))
|
|
@ -24,6 +24,7 @@
|
||||||
[status-im2.contexts.onboarding.profiles.view :as profiles]
|
[status-im2.contexts.onboarding.profiles.view :as profiles]
|
||||||
[status-im2.contexts.quo-preview.main :as quo.preview]
|
[status-im2.contexts.quo-preview.main :as quo.preview]
|
||||||
[status-im2.contexts.shell.view :as shell]
|
[status-im2.contexts.shell.view :as shell]
|
||||||
|
[status-im2.contexts.syncing.scan-sync-code-page.view :as scan-sync-code-page]
|
||||||
[status-im2.contexts.syncing.syncing-devices-list.view :as settings-syncing]
|
[status-im2.contexts.syncing.syncing-devices-list.view :as settings-syncing]
|
||||||
[status-im2.contexts.syncing.how-to-pair.view :as how-to-pair]
|
[status-im2.contexts.syncing.how-to-pair.view :as how-to-pair]
|
||||||
[status-im2.navigation.options :as options]
|
[status-im2.navigation.options :as options]
|
||||||
|
@ -140,6 +141,8 @@
|
||||||
:popGesture false
|
:popGesture false
|
||||||
:hardwareBackButton {:dismissModalOnPress false
|
:hardwareBackButton {:dismissModalOnPress false
|
||||||
:popStackOnPress false}}}
|
:popStackOnPress false}}}
|
||||||
|
{:name :scan-sync-code-page
|
||||||
|
:component scan-sync-code-page/view}
|
||||||
|
|
||||||
{:name :sign-in
|
{:name :sign-in
|
||||||
:options {:layout options/onboarding-layout}
|
:options {:layout options/onboarding-layout}
|
||||||
|
|
Loading…
Reference in New Issue