[iOS] Perform preflight check for local network permission (#16150)
Signed-off-by: Mohamed Javid <19339952+smohamedjavid@users.noreply.github.com>
This commit is contained in:
parent
9b52bba95d
commit
2df1b46975
|
@ -304,6 +304,14 @@ RCT_EXPORT_METHOD(hashMessage:(NSString *)message
|
|||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(localPairingPreflightOutboundCheck:(RCTResponseSenderBlock)callback) {
|
||||
#if DEBUG
|
||||
NSLog(@"LocalPairingPreflightOutboundCheck() method called");
|
||||
#endif
|
||||
NSString *result = StatusgoLocalPairingPreflightOutboundCheck();
|
||||
callback(@[result]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getConnectionStringForBootstrappingAnotherDevice:(NSString *)configJSON
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
|
||||
|
|
|
@ -248,6 +248,13 @@
|
|||
(log/debug "[native-module] hash-message")
|
||||
(.hashMessage ^js (status) message callback))
|
||||
|
||||
(defn local-pairing-preflight-outbound-check
|
||||
"Checks whether the device has allows connecting to the local server"
|
||||
[callback]
|
||||
(log/info "[native-module] Performing local pairing preflight check")
|
||||
(when platform/ios?
|
||||
(.localPairingPreflightOutboundCheck ^js (status) callback)))
|
||||
|
||||
(defn get-connection-string-for-bootstrapping-another-device
|
||||
"Generates connection string form status-go for the purpose of local pairing on the sender end"
|
||||
[config-json callback]
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im2.constants :as constants]))
|
||||
[status-im2.constants :as constants]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(rf/defn status-node-started
|
||||
[{db :db :as cofx} {:keys [error]}]
|
||||
|
@ -55,7 +56,7 @@
|
|||
:peers-count (count (:peers peer-stats)))}))
|
||||
|
||||
(rf/defn handle-local-pairing-signals
|
||||
[{:keys [db] :as cofx} {:keys [type action data] :as event}]
|
||||
[{:keys [db] :as cofx} {:keys [type action data error] :as event}]
|
||||
(log/info "local pairing signal received"
|
||||
{:event event})
|
||||
(let [{:keys [account password]} data
|
||||
|
@ -78,7 +79,7 @@
|
|||
(and (some? account) (some? password)))
|
||||
multiaccount-data (when received-account?
|
||||
(merge account {:password password}))
|
||||
navigate-to-syncing-devices? (and connection-success? receiver?)
|
||||
navigate-to-syncing-devices? (and (or connection-success? error-on-pairing?) receiver?)
|
||||
user-in-syncing-devices-screen? (= (:view-id db) :syncing-progress)]
|
||||
(merge {:db (cond-> db
|
||||
connection-success?
|
||||
|
@ -92,12 +93,21 @@
|
|||
|
||||
completed-pairing?
|
||||
(assoc-in [:syncing :pairing-status] :completed))}
|
||||
(when (and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
||||
{:dispatch [:navigate-to :syncing-progress]})
|
||||
(when (and completed-pairing? sender?)
|
||||
{:dispatch [:syncing/clear-states]})
|
||||
(when (and completed-pairing? receiver?)
|
||||
{:dispatch [:multiaccounts.login/local-paired-user]}))))
|
||||
(cond
|
||||
(and navigate-to-syncing-devices? (not user-in-syncing-devices-screen?))
|
||||
{:dispatch [:navigate-to :syncing-progress]}
|
||||
|
||||
(and completed-pairing? sender?)
|
||||
{:dispatch [:syncing/clear-states]}
|
||||
|
||||
(and completed-pairing? receiver?)
|
||||
{:dispatch [:multiaccounts.login/local-paired-user]}
|
||||
|
||||
(and error-on-pairing? (some? error))
|
||||
{:dispatch [:toasts/upsert
|
||||
{:icon :i/alert
|
||||
:icon-color colors/danger-50
|
||||
:text error}]}))))
|
||||
|
||||
(rf/defn process
|
||||
{:events [:signals/signal-received]}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
(ns status-im2.contexts.syncing.events
|
||||
(:require [native-module.core :as native-module]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.data-store.settings :as data-store.settings]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.utils.platform :as utils.platform]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.security.core :as security]
|
||||
[status-im2.config :as config]
|
||||
[status-im.node.core :as node]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.data-store.settings :as data-store.settings]
|
||||
[status-im.utils.platform :as utils.platform]
|
||||
[status-im2.constants :as constants]))
|
||||
[utils.transforms :as transforms]))
|
||||
|
||||
(rf/defn local-pairing-update-role
|
||||
{:events [:syncing/update-role]}
|
||||
|
@ -31,6 +32,19 @@
|
|||
:custom-bootnodes-enabled? false}}]
|
||||
(node/get-multiaccount-node-config db)))
|
||||
|
||||
(rf/defn preflight-outbound-check-for-local-pairing
|
||||
{:events [:syncing/preflight-outbound-check]}
|
||||
[_ set-checks-passed]
|
||||
(let [callback
|
||||
(fn [raw-response]
|
||||
(log/info "Local pairing preflight check"
|
||||
{:response raw-response
|
||||
:event :syncing/preflight-outbound-check})
|
||||
(let [^js response-js (transforms/json->js raw-response)
|
||||
error (transforms/js->clj (.-error response-js))]
|
||||
(set-checks-passed (empty? error))))]
|
||||
(native-module/local-pairing-preflight-outbound-check callback)))
|
||||
|
||||
(rf/defn initiate-local-pairing-with-connection-string
|
||||
{:events [:syncing/input-connection-string-for-bootstrapping]
|
||||
:interceptors [(re-frame/inject-cofx :random-guid-generator)]}
|
||||
|
|
|
@ -13,10 +13,35 @@
|
|||
[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]))
|
||||
[status-im2.contexts.syncing.utils :as sync-utils]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
;; 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 camera-permission-granted? (reagent/atom false))
|
||||
|
||||
(defn request-camera-permission
|
||||
[]
|
||||
(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)}])}]))
|
||||
|
||||
(defn perform-preflight-check
|
||||
"Performing the check for the first time
|
||||
will trigger local network access permission in iOS.
|
||||
This permission is required for local pairing
|
||||
https://github.com/status-im/status-mobile/issues/16135"
|
||||
[]
|
||||
(rf/dispatch [:syncing/preflight-outbound-check #(reset! preflight-check-passed? %)]))
|
||||
|
||||
(defn- header
|
||||
[active-tab read-qr-once? title]
|
||||
[:<>
|
||||
|
@ -59,27 +84,49 @@
|
|||
(reset! active-tab id)
|
||||
(reset! read-qr-once? false))}]]])
|
||||
|
||||
(defn- camera-permission-view
|
||||
[request-camera-permission]
|
||||
(defn get-labels-and-on-press-method
|
||||
[]
|
||||
(if @camera-permission-granted?
|
||||
{:title-label-key :t/enable-access-to-local-network
|
||||
:description-label-key :t/to-pair-with-your-other-device-in-the-network
|
||||
:button-icon :i/world
|
||||
:button-label :t/enable-network-access
|
||||
:accessibility-label :perform-preflight-check
|
||||
:on-press perform-preflight-check}
|
||||
{:title-label-key :t/enable-access-to-camera
|
||||
:description-label-key :t/to-scan-a-qr-enable-your-camera
|
||||
:button-icon :i/camera
|
||||
:button-label :t/enable-camera
|
||||
:accessibility-label :request-camera-permission
|
||||
:on-press request-camera-permission}))
|
||||
|
||||
(defn- camera-and-local-network-access-permission-view
|
||||
[]
|
||||
(let [{:keys [title-label-key
|
||||
description-label-key
|
||||
button-icon
|
||||
button-label
|
||||
accessibility-label
|
||||
on-press]} (get-labels-and-on-press-method)]
|
||||
[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)]
|
||||
(i18n/label title-label-key)]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:style style/enable-camera-access-sub-text}
|
||||
(i18n/label :t/to-scan-a-qr-enable-your-camera)]
|
||||
(i18n/label description-label-key)]
|
||||
[quo/button
|
||||
{:before :i/camera
|
||||
{:before button-icon
|
||||
:type :primary
|
||||
:size 32
|
||||
:accessibility-label :request-camera-permission
|
||||
:accessibility-label accessibility-label
|
||||
:override-theme :dark
|
||||
:on-press request-camera-permission}
|
||||
(i18n/label :t/enable-camera)]])
|
||||
:on-press on-press}
|
||||
(i18n/label button-label)]]))
|
||||
|
||||
(defn- qr-scan-hole-area
|
||||
[qr-view-finder]
|
||||
|
@ -117,14 +164,16 @@
|
|||
(i18n/label :t/ensure-qr-code-is-in-focus-to-scan)]]]))
|
||||
|
||||
(defn- scan-qr-code-tab
|
||||
[qr-view-finder request-camera-permission]
|
||||
[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 @camera-permission-granted? (boolean (not-empty @qr-view-finder)))
|
||||
(if (and @preflight-check-passed?
|
||||
@camera-permission-granted?
|
||||
(boolean (not-empty @qr-view-finder)))
|
||||
[viewfinder @qr-view-finder]
|
||||
[camera-permission-view request-camera-permission])])
|
||||
[camera-and-local-network-access-permission-view])])
|
||||
|
||||
(defn- enter-sync-code-tab
|
||||
[]
|
||||
|
@ -187,19 +236,7 @@
|
|||
[{: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)}])}]))]
|
||||
qr-view-finder (reagent/atom {})]
|
||||
(fn []
|
||||
(let [camera-ref (atom nil)
|
||||
read-qr-once? (atom false)
|
||||
|
@ -215,7 +252,9 @@
|
|||
3000)
|
||||
(check-qr-code-data data)))
|
||||
scan-qr-code-tab? (= @active-tab 1)
|
||||
show-camera? (and scan-qr-code-tab? @camera-permission-granted?)
|
||||
show-camera? (and scan-qr-code-tab?
|
||||
@camera-permission-granted?
|
||||
@preflight-check-passed?)
|
||||
show-holes? (and show-camera?
|
||||
(boolean (not-empty @qr-view-finder)))]
|
||||
(rn/use-effect
|
||||
|
@ -230,7 +269,7 @@
|
|||
[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]
|
||||
1 [scan-qr-code-tab qr-view-finder]
|
||||
2 [enter-sync-code-tab]
|
||||
nil)
|
||||
[rn/view {:style style/flex-spacer}]
|
||||
|
|
|
@ -2092,6 +2092,9 @@
|
|||
"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-local-network": "Enable access to local network",
|
||||
"to-pair-with-your-other-device-in-the-network": "To pair with your other device in the network",
|
||||
"enable-network-access": "Enable network access",
|
||||
"enable-access-to-camera": "Enable access to camera",
|
||||
"link-preview-loading-message": "Generating preview",
|
||||
"to-scan-a-qr-enable-your-camera": "To scan a QR, enable your camera",
|
||||
|
|
Loading…
Reference in New Issue