[Feature] Sign in by scanning sync QR code (#15416)
This commit is contained in:
parent
2f19badc6c
commit
7d4be37111
|
@ -19,7 +19,7 @@
|
|||
"@babel/preset-typescript": "^7.17.12",
|
||||
"@react-native-async-storage/async-storage": "^1.17.9",
|
||||
"@react-native-community/audio-toolkit": "git+https://github.com/tbenr/react-native-audio-toolkit.git#refs/tags/v2.0.3-status-v6",
|
||||
"@react-native-community/blur": "git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.1-status",
|
||||
"@react-native-community/blur": "git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.2-status",
|
||||
"@react-native-community/cameraroll": "git+https://github.com/status-im/react-native-cameraroll.git#refs/tags/v4.0.4-status.0",
|
||||
"@react-native-community/clipboard": "^1.2.2",
|
||||
"@react-native-community/hooks": "^2.5.1",
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def themes-for-blur
|
||||
{:light {:background-color colors/neutral-80-opa-5}
|
||||
:dark {:background-color colors/white-opa-5}})
|
||||
|
||||
(def themes
|
||||
{:light {:background-color colors/neutral-20}
|
||||
:dark {:background-color colors/neutral-80}})
|
||||
|
@ -12,11 +16,12 @@
|
|||
(defn segmented-control
|
||||
[{:keys [default-active on-change]}]
|
||||
(let [active-tab-id (reagent/atom default-active)]
|
||||
(fn [{:keys [data size]}]
|
||||
(fn [{:keys [data size override-theme blur?]}]
|
||||
(let [active-id @active-tab-id]
|
||||
[rn/view
|
||||
{:flex-direction :row
|
||||
:background-color (get-in themes [(theme/get-theme) :background-color])
|
||||
:background-color (get-in (if blur? themes-for-blur themes)
|
||||
[(or override-theme (theme/get-theme)) :background-color])
|
||||
:border-radius (case size
|
||||
32 10
|
||||
28 8
|
||||
|
@ -29,12 +34,14 @@
|
|||
{:margin-left (if (= 0 indx) 0 2)
|
||||
:flex 1}
|
||||
[tab/view
|
||||
{:id id
|
||||
:segmented? true
|
||||
:size size
|
||||
:active (= id active-id)
|
||||
:on-press (fn [tab-id]
|
||||
(reset! active-tab-id tab-id)
|
||||
(when on-change
|
||||
(on-change tab-id)))}
|
||||
{:id id
|
||||
:segmented? true
|
||||
:size size
|
||||
:override-theme override-theme
|
||||
:blur? blur?
|
||||
:active (= id active-id)
|
||||
:on-press (fn [tab-id]
|
||||
(reset! active-tab-id tab-id)
|
||||
(when on-change
|
||||
(on-change tab-id)))}
|
||||
label]])]))))
|
||||
|
|
|
@ -79,11 +79,12 @@
|
|||
[notification-dot/notification-dot
|
||||
{:style style/notification-dot}])
|
||||
[rn/view
|
||||
{:style (style/tab {:size size
|
||||
:disabled disabled
|
||||
:segmented? segmented?
|
||||
:background-color background-color
|
||||
:show-notification-dot? show-notification-dot?})}
|
||||
{:style (style/tab
|
||||
{:size size
|
||||
:disabled disabled
|
||||
:segmented? segmented?
|
||||
:background-color (if (and segmented? (not active)) :transparent background-color)
|
||||
:show-notification-dot? show-notification-dot?})}
|
||||
(when before
|
||||
[rn/view
|
||||
[icons/icon before {:color icon-color}]])
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
quo2.components.settings.accounts.view
|
||||
quo2.components.settings.privacy-option
|
||||
quo2.components.onboarding.small-option-card.view
|
||||
quo2.components.tabs.segmented-tab
|
||||
quo2.components.tabs.account-selector
|
||||
quo2.components.tabs.tabs
|
||||
quo2.components.tags.context-tags
|
||||
|
@ -91,6 +92,7 @@
|
|||
(def audio-tag quo2.components.tags.context-tags/audio-tag)
|
||||
(def community-tag quo2.components.tags.context-tags/community-tag)
|
||||
(def tabs quo2.components.tabs.tabs/tabs)
|
||||
(def segmented-control quo2.components.tabs.segmented-tab/segmented-control)
|
||||
(def account-selector quo2.components.tabs.account-selector/account-selector)
|
||||
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
|
||||
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
(ns react-native.camera-kit
|
||||
(:require ["react-native-camera-kit" :refer (CameraKitCamera)]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(def camera (reagent/adapt-react-class CameraKitCamera))
|
|
@ -481,6 +481,9 @@
|
|||
"Decides which root should be initialised depending on user and app state"
|
||||
[db]
|
||||
(cond
|
||||
(get db :local-pairing/completed-pairing?)
|
||||
(re-frame/dispatch [:syncing/pairing-completed])
|
||||
|
||||
(get db :onboarding-2/new-account?)
|
||||
(re-frame/dispatch [:navigate-to :enable-notifications])
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
[status-im.visibility-status-updates.core :as visibility-status-updates]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
|
||||
[taoensso.timbre :as log]))
|
||||
[taoensso.timbre :as log]
|
||||
[status-im2.constants :as constants]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]))
|
||||
|
||||
(rf/defn status-node-started
|
||||
[{db :db :as cofx} {:keys [error]}]
|
||||
|
@ -53,10 +56,40 @@
|
|||
:peer-stats peer-stats
|
||||
:peers-count (count (:peers peer-stats)))}))
|
||||
|
||||
(defn handle-local-pairing-signals
|
||||
[event]
|
||||
(log/debug "local pairing signal received"
|
||||
{:event event}))
|
||||
(rf/defn handle-local-pairing-signals
|
||||
[{:keys [db] :as cofx} event]
|
||||
(log/info "local pairing signal received"
|
||||
{:event event})
|
||||
(let [connection-success? (= (:type event)
|
||||
constants/local-pairing-event-connection-success)
|
||||
error-on-pairing? (contains? constants/local-pairing-event-errors (:type event))
|
||||
completed-pairing? (and (= (:type event)
|
||||
constants/local-pairing-event-process-success)
|
||||
(= (:action event)
|
||||
constants/local-pairing-action-pairing-account))
|
||||
logged-in? (multiaccounts.model/logged-in? cofx)
|
||||
;; since `connection-success` event is received on both sender and receiver devices
|
||||
;; we check the `logged-in?` status to identify the receiver and take the user to next screen
|
||||
navigate-to-syncing-devices? (and connection-success? (not logged-in?))
|
||||
user-in-syncing-devices-screen? (= (:view-id db) :syncing-devices)]
|
||||
(merge {:db (cond-> db
|
||||
connection-success?
|
||||
(assoc :local-pairing/completed-pairing? false)
|
||||
|
||||
error-on-pairing?
|
||||
(dissoc :local-pairing/completed-pairing?)
|
||||
|
||||
completed-pairing?
|
||||
(assoc :local-pairing/completed-pairing? true))}
|
||||
(when navigate-to-syncing-devices?
|
||||
{:dispatch [:navigate-to :syncing-devices]})
|
||||
(when (and error-on-pairing? user-in-syncing-devices-screen?)
|
||||
{:dispatch-n [[:toasts/upsert
|
||||
{:icon :i/info
|
||||
:icon-color colors/danger-50
|
||||
:override-theme :light
|
||||
:text (i18n/label :t/error-syncing-connection-failed)}]
|
||||
[:navigate-back]]}))))
|
||||
|
||||
(rf/defn process
|
||||
{:events [:signals/signal-received]}
|
||||
|
@ -110,5 +143,6 @@
|
|||
"status.updates.timedout" (visibility-status-updates/handle-visibility-status-updates
|
||||
cofx
|
||||
(js->clj event-js :keywordize-keys true))
|
||||
"localPairing" (handle-local-pairing-signals (js->clj event-js :keywordize-keys true))
|
||||
"localPairing" (handle-local-pairing-signals cofx
|
||||
(js->clj event-js :keywordize-keys true))
|
||||
(log/debug "Event " type " not handled"))))
|
||||
|
|
|
@ -263,6 +263,27 @@
|
|||
An example of a connection string is -> cs2:5vd6J6:Jfc:27xMmHKEYwzRGXcvTtuiLZFfXscMx4Mz8d9wEHUxDj4p7:EG7Z13QScfWBJNJ5cprszzDQ5fBVsYMirXo8MaQFJvpF:3 "
|
||||
"cs")
|
||||
|
||||
;; sender and receiver events
|
||||
(def ^:const local-pairing-event-connection-success "connection-success")
|
||||
(def ^:const local-pairing-event-connection-error "connection-error")
|
||||
(def ^:const local-pairing-event-transfer-success "transfer-success")
|
||||
(def ^:const local-pairing-event-transfer-error "transfer-error")
|
||||
|
||||
;; receiver events
|
||||
(def ^:const local-pairing-event-received-amount "received-account")
|
||||
(def ^:const local-pairing-event-process-success "process-success")
|
||||
(def ^:const local-pairing-event-process-error "process-error")
|
||||
|
||||
(def ^:const local-pairing-event-errors
|
||||
#{local-pairing-event-connection-error
|
||||
local-pairing-event-transfer-error
|
||||
local-pairing-event-process-error})
|
||||
|
||||
(def ^:const local-pairing-action-connect 1)
|
||||
(def ^:const local-pairing-action-pairing-account 2)
|
||||
(def ^:const local-pairing-action-sync-device 3)
|
||||
(def ^:const local-pairing-action-pairing-installation 4)
|
||||
|
||||
(def ^:const serialization-key
|
||||
"We pass this serialization key as a parameter to MultiformatSerializePublicKey
|
||||
function at status-go, This key determines the output base of the serialization.
|
||||
|
|
|
@ -1,14 +1,92 @@
|
|||
(ns status-im2.contexts.onboarding.sign-in.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def navigation-bar {:height 56})
|
||||
(def screen-padding 20)
|
||||
|
||||
(def page-container
|
||||
{:padding-top (if platform/ios? 44 0)
|
||||
:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0
|
||||
:background-color colors/neutral-80-opa-80-blur})
|
||||
(def flex-spacer {:flex 1})
|
||||
|
||||
(def absolute-fill
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(defn root-container
|
||||
[padding-top]
|
||||
{: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)})
|
||||
|
||||
(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]
|
||||
{: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})
|
||||
|
|
|
@ -1,42 +1,234 @@
|
|||
(ns status-im2.contexts.onboarding.sign-in.view
|
||||
(:require [quo2.core :as quo]
|
||||
(:require [clojure.string :as string]
|
||||
[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.common.resources :as resources]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.onboarding.sign-in.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn navigation-bar
|
||||
[]
|
||||
[rn/view {:style style/navigation-bar}
|
||||
[quo/page-nav
|
||||
{:align-mid? true
|
||||
:mid-section {:type :text-only :main-text ""}
|
||||
:left-section {:type :blur-bg
|
||||
:icon :i/arrow-left
|
||||
:icon-override-theme :dark
|
||||
:on-press #(rf/dispatch [:navigate-back])}
|
||||
:right-section-buttons [{:type :blur-bg
|
||||
:icon :i/info
|
||||
:icon-override-theme :dark
|
||||
:on-press #(js/alert "Pending")}]}]])
|
||||
(defonce camera-permission-granted? (reagent/atom false))
|
||||
|
||||
(defn page
|
||||
[]
|
||||
[rn/view {:style style/page-container}
|
||||
[navigation-bar]
|
||||
[rn/view {:style {:padding-horizontal 20}}
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style {:color colors/white}} "Sign in by syncing"]
|
||||
(defn- header
|
||||
[active-tab read-qr-once?]
|
||||
[:<>
|
||||
[rn/view {:style style/header-container}
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:navigate-to :syncing-devices])
|
||||
:style {}} (i18n/label :t/continue)]]])
|
||||
{: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 sign-in
|
||||
(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 {:flex 1}}
|
||||
[background/view true]
|
||||
[page]])
|
||||
[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 view
|
||||
[]
|
||||
(let [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)}])}]))]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [insets (safe-area/use-safe-area)
|
||||
camera-ref (atom nil)
|
||||
read-qr-once? (atom false)
|
||||
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}]
|
||||
[rn/image
|
||||
{:style (merge style/absolute-fill {:height height :width width})
|
||||
:source (resources/get-image :intro-4)}])
|
||||
(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]]))]))
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.contexts.onboarding.syncing.syncing-devices.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||
[utils.re-frame :as rf]))
|
||||
[status-im2.contexts.onboarding.common.background.view :as background]))
|
||||
|
||||
|
||||
(defn navigation-bar
|
||||
|
@ -14,10 +12,6 @@
|
|||
[quo/page-nav
|
||||
{:align-mid? true
|
||||
:mid-section {:type :text-only :main-text ""}
|
||||
:left-section {:type :blur-bg
|
||||
:icon :i/arrow-left
|
||||
:icon-override-theme :dark
|
||||
:on-press #(rf/dispatch [:navigate-back])}
|
||||
:right-section-buttons [{:type :blur-bg
|
||||
:icon :i/info
|
||||
:icon-override-theme :dark
|
||||
|
@ -39,10 +33,7 @@
|
|||
[quo/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style {:color colors/white}} "will show sync failed if unsuccessful"]
|
||||
[quo/button
|
||||
{:on-press #(rf/dispatch [:navigate-to :enable-notifications])
|
||||
:style {}} (i18n/label :t/continue)]]])
|
||||
:style {:color colors/white}} "will show sync failed if unsuccessful"]]])
|
||||
|
||||
(defn syncing-devices
|
||||
[]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im2.contexts.quo-preview.tabs.segmented-tab
|
||||
(:require [quo2.components.tabs.segmented-tab :as quo2]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]))
|
||||
|
@ -12,32 +13,41 @@
|
|||
:options [{:key 28
|
||||
:value "28"}
|
||||
{:key 20
|
||||
:value "20"}]}])
|
||||
:value "20"}]}
|
||||
{:label "Blur?"
|
||||
:key :blur?
|
||||
:type :boolean}])
|
||||
|
||||
(defn cool-preview
|
||||
[]
|
||||
(let [state (reagent/atom {:size 32})]
|
||||
(let [state (reagent/atom {:size 32
|
||||
:blur? false})]
|
||||
(fn []
|
||||
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
||||
[rn/view {:padding-bottom 150}
|
||||
[rn/view {:flex 1}
|
||||
[preview/customizer state descriptor]]
|
||||
[rn/view {:padding-vertical 60}
|
||||
[quo2/segmented-control
|
||||
(merge @state
|
||||
{:default-active 1
|
||||
:data [{:id 1 :label "Tab 1"}
|
||||
{:id 2 :label "Tab 2"}
|
||||
{:id 3 :label "Tab 3"}
|
||||
{:id 4 :label "Tab 4"}]
|
||||
:on-change #(println "Active tab" %)})]]
|
||||
[rn/view {:padding-vertical 60}
|
||||
[quo2/segmented-control
|
||||
(merge @state
|
||||
{:default-active 1
|
||||
:data [{:id 1 :label "Tab 1"}
|
||||
{:id 2 :label "Tab 2"}]
|
||||
:on-change #(println "Active tab" %)})]]]])))
|
||||
[preview/blur-view
|
||||
{:show-blur-background? (:blur? @state)
|
||||
:height 200
|
||||
:style {:width "100%"}
|
||||
:blur-view-props {:blur-type (theme/get-theme)}}
|
||||
[:<>
|
||||
[quo2/segmented-control
|
||||
(merge @state
|
||||
{:default-active 1
|
||||
:data [{:id 1 :label "Tab 1"}
|
||||
{:id 2 :label "Tab 2"}
|
||||
{:id 3 :label "Tab 3"}
|
||||
{:id 4 :label "Tab 4"}]
|
||||
:on-change #(println "Active tab" %)})]
|
||||
[rn/view {:style {:padding-top 24}}
|
||||
[quo2/segmented-control
|
||||
(merge @state
|
||||
{:default-active 1
|
||||
:data [{:id 1 :label "Tab 1"}
|
||||
{:id 2 :label "Tab 2"}]
|
||||
:on-change #(println "Active tab" %)})]]]]]])))
|
||||
|
||||
(defn preview-segmented
|
||||
[]
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
[status-im.data-store.settings :as data-store.settings]
|
||||
[status-im.utils.platform :as utils.platform]))
|
||||
|
||||
(rf/defn local-pairing-completed
|
||||
{:events [:syncing/pairing-completed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(rf/merge cofx
|
||||
{:db (dissoc db :local-pairing/completed-pairing?)
|
||||
:dispatch [:init-root :enable-notifications]}))
|
||||
|
||||
(defn- get-default-node-config
|
||||
[installation-id]
|
||||
(let [db {:networks/current-network config/default-network
|
||||
|
@ -24,7 +31,7 @@
|
|||
(rf/defn initiate-local-pairing-with-connection-string
|
||||
{:events [:syncing/input-connection-string-for-bootstrapping]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
[{:keys [random-guid-generator db]} {connection-string :data}]
|
||||
[{:keys [random-guid-generator db]} connection-string]
|
||||
(let [installation-id (random-guid-generator)
|
||||
default-node-config (get-default-node-config installation-id)
|
||||
default-node-config-string (.stringify js/JSON (clj->js default-node-config))
|
||||
|
|
|
@ -160,6 +160,14 @@
|
|||
{:stack {:id :profiles
|
||||
:children [{:component {:name :profiles
|
||||
:id :profiles
|
||||
:options (merge
|
||||
(status-bar-options)
|
||||
{:topBar {:visible false}})}}]}}}
|
||||
:enable-notifications
|
||||
{:root
|
||||
{:stack {:id :enable-notifications
|
||||
:children [{:component {:name :enable-notifications
|
||||
:id :enable-notifications
|
||||
:options (merge
|
||||
(status-bar-options)
|
||||
{:topBar {:visible false}})}}]}}}}))
|
||||
|
|
|
@ -184,11 +184,13 @@
|
|||
:component enable-notifications/enable-notifications}
|
||||
|
||||
{:name :sign-in
|
||||
:options {:statusBar {:style :light}
|
||||
:options {:statusBar {:style :light
|
||||
:backgroundColor :transparent
|
||||
:translucent true}
|
||||
:topBar {:visible false}
|
||||
:navigationBar {:backgroundColor colors/black}}
|
||||
:insets {:top false}
|
||||
:component sign-in/sign-in}
|
||||
:component sign-in/view}
|
||||
|
||||
{:name :syncing-devices
|
||||
:options {:statusBar {:style :light}
|
||||
|
|
|
@ -2020,5 +2020,19 @@
|
|||
"remove-profile-message": "Remove profile from this device",
|
||||
"remove-profile-confirm-message": "All profile data will removed from device.",
|
||||
"create-new-profile": "Create new profile",
|
||||
"add-existing-status-profile": "Add existing Status profile"
|
||||
"add-existing-status-profile": "Add existing Status profile",
|
||||
"find-sync-code": "Find sync code",
|
||||
"sign-in-by-syncing": "Sign in by syncing",
|
||||
"synchronise-your-data-across-your-devices": "Synchronise your data across your devices",
|
||||
"scan-sync-qr-code": "Scan QR code",
|
||||
"enter-sync-code": "Enter sync code",
|
||||
"enable-access-to-camera": "Enable access to camera",
|
||||
"to-scan-a-qr-enable-your-camera": "To scan a QR, enable your camera",
|
||||
"enable-camera": "Enable camera",
|
||||
"ensure-qr-code-in-focus-to-scan": "Ensure that the QR code is in focus to scan",
|
||||
"i-dont-have-status-on-another-device": "I don’t have Status on another device",
|
||||
"ensure-qr-code-is-in-focus-to-scan":"Ensure that the QR code is in focus to scan",
|
||||
"error-this-is-not-a-sync-qr-code": "Oops! This is not a sync QR code",
|
||||
"error-syncing-connection-failed": "Oops! Connection failed. Try again",
|
||||
"camera-permission-denied": "Permission denied"
|
||||
}
|
||||
|
|
|
@ -1786,9 +1786,9 @@
|
|||
eventemitter3 "^1.2.0"
|
||||
lodash "^4.17.15"
|
||||
|
||||
"@react-native-community/blur@git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.1-status":
|
||||
version "4.3.0"
|
||||
resolved "git+https://github.com/status-im/react-native-blur#7317898ee7c824d2d5501aec72a509baced2b253"
|
||||
"@react-native-community/blur@git+https://github.com/status-im/react-native-blur#refs/tags/v4.3.2-status":
|
||||
version "4.3.2"
|
||||
resolved "git+https://github.com/status-im/react-native-blur#722940e19c7ac8f90d3fccc5e9d34e0fd2342d51"
|
||||
|
||||
"@react-native-community/cameraroll@git+https://github.com/status-im/react-native-cameraroll.git#refs/tags/v4.0.4-status.0":
|
||||
version "4.0.4"
|
||||
|
|
Loading…
Reference in New Issue