[#7871] Handle multiple opened screens with qr code readers
This commit is contained in:
parent
49fbf21f8d
commit
148d43fdab
|
@ -34,7 +34,7 @@
|
|||
|
||||
(= permission constants/dapp-permission-qr-code)
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :yielding-control?] true)
|
||||
(qr-scanner/scan-qr-code {:modal? false}
|
||||
(qr-scanner/scan-qr-code {}
|
||||
{:handler :browser.bridge.callback/qr-code-scanned
|
||||
:cancel-handler :browser.bridge.callback/qr-code-canceled
|
||||
:data {:dapp-name dapp-name
|
||||
|
|
|
@ -55,8 +55,7 @@
|
|||
(handlers/register-handler-fx
|
||||
:extensions/camera-qr-code
|
||||
(fn [{:keys [db] :as cofx} [_ _ {:keys [on-success on-failure]}]]
|
||||
(qr-scanner/scan-qr-code cofx {:modal? false
|
||||
:deny-handler :extensions/camera-denied}
|
||||
(qr-scanner/scan-qr-code cofx {:deny-handler :extensions/camera-denied}
|
||||
{:handler :extensions/camera-qr-code-scanned
|
||||
:cancel-handler :extensions/camera-cancel
|
||||
:data {:on-success on-success
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(fx/defn scan-qr-code
|
||||
[{:keys [db]} {:keys [modal? deny-handler] :as identifier} qr-codes]
|
||||
{:db (assoc db :qr-codes qr-codes)
|
||||
[{:keys [db]} {:keys [deny-handler] :as identifier} qr-codes]
|
||||
{:db (assoc-in db [:qr-codes identifier] qr-codes)
|
||||
:request-permissions-fx {:permissions [:camera]
|
||||
:on-allowed #(re-frame/dispatch [(if modal? :navigate-to-modal :navigate-to)
|
||||
:qr-scanner {:current-qr-context identifier}])
|
||||
:on-allowed #(re-frame/dispatch
|
||||
[:navigate-to :qr-scanner
|
||||
{:current-qr-context identifier}])
|
||||
:on-denied (if (nil? deny-handler)
|
||||
(fn []
|
||||
(utils/set-timeout
|
||||
|
@ -23,7 +24,7 @@
|
|||
(merge {:db (-> db
|
||||
(update :qr-codes dissoc context)
|
||||
(dissoc :current-qr-context))}
|
||||
(when-let [qr-codes (:qr-codes db)]
|
||||
(when-let [qr-codes (get-in db [:qr-codes context])]
|
||||
{:dispatch [(:handler qr-codes) context data (dissoc qr-codes :handler)]})))
|
||||
|
||||
(fx/defn set-qr-code-cancel
|
||||
|
@ -31,6 +32,6 @@
|
|||
(merge {:db (-> db
|
||||
(update :qr-codes dissoc context)
|
||||
(dissoc :current-qr-context))}
|
||||
(when-let [qr-codes (:qr-codes db)]
|
||||
(when-let [qr-codes (get-in db [:qr-codes context])]
|
||||
(when-let [handler (:cancel-handler qr-codes)]
|
||||
{:dispatch [handler context qr-codes]}))))
|
||||
{:dispatch [handler context qr-codes]}))))
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
{:db (if (= view-id go-to-view-id)
|
||||
db
|
||||
(push-view db go-to-view-id))
|
||||
::navigate-to go-to-view-id}))
|
||||
::navigate-to [go-to-view-id screen-params]}))
|
||||
|
||||
(fx/defn navigate-reset
|
||||
[{:keys [db]} {:keys [index actions] :as config}]
|
||||
|
@ -76,9 +76,9 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::navigate-to
|
||||
(fn [view-id]
|
||||
(log/debug :navigate-to view-id)
|
||||
(navigation/navigate-to (name view-id))))
|
||||
(fn [[view-id params]]
|
||||
(log/debug :navigate-to view-id params)
|
||||
(navigation/navigate-to (name view-id) params)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::navigate-back
|
||||
|
|
|
@ -23,20 +23,25 @@
|
|||
(defn on-barcode-read [identifier data]
|
||||
(re-frame/dispatch [:qr-scanner.callback/scan-qr-code-success identifier (camera/get-qr-code-data data)]))
|
||||
|
||||
(defview qr-scanner []
|
||||
(letsubs [{identifier :current-qr-context} [:get-screen-params]
|
||||
camera-initialized? (reagent/atom false)
|
||||
;; identifier is passed via navigation params instead of subs in order to ensure
|
||||
;; that two separate instances of `qr-scanner` screen can work simultaneously
|
||||
(defview qr-scanner [{identifier :current-qr-context} screen-focused?]
|
||||
(letsubs [camera-initialized? (reagent/atom false)
|
||||
barcode-read? (reagent/atom false)]
|
||||
[react/view styles/barcode-scanner-container
|
||||
[qr-scanner-toolbar (or (:toolbar-title identifier) (i18n/label :t/scan-qr)) identifier]
|
||||
[camera/camera {:onBarCodeRead #(if (:multiple? identifier)
|
||||
(on-barcode-read identifier %)
|
||||
(when-not @barcode-read?
|
||||
(do (reset! barcode-read? true)
|
||||
(on-barcode-read identifier %))))
|
||||
:ref #(reset! camera-initialized? true)
|
||||
:captureAudio false
|
||||
:style styles/barcode-scanner}]
|
||||
;; camera component should be hidden if screen is not shown
|
||||
;; otherwise another screen with camera from a different stack
|
||||
;; will not work properly
|
||||
(when @screen-focused?
|
||||
[camera/camera {:onBarCodeRead #(if (:multiple? identifier)
|
||||
(on-barcode-read identifier %)
|
||||
(when-not @barcode-read?
|
||||
(do (reset! barcode-read? true)
|
||||
(on-barcode-read identifier %))))
|
||||
:ref #(reset! camera-initialized? true)
|
||||
:captureAudio false
|
||||
:style styles/barcode-scanner}])
|
||||
[react/view styles/rectangle-container
|
||||
[react/view styles/rectangle
|
||||
[react/image {:source {:uri :corner_left_top}
|
||||
|
|
|
@ -21,10 +21,11 @@
|
|||
|
||||
(defonce view-id (reagent.core/atom nil))
|
||||
|
||||
(defn navigation-events [current-view-id modal?]
|
||||
(defn navigation-events [current-view-id modal? screen-focused?]
|
||||
[:> navigation/navigation-events
|
||||
{:on-will-focus
|
||||
(fn []
|
||||
(reset! screen-focused? true)
|
||||
(when (not= @view-id current-view-id)
|
||||
(reset! view-id current-view-id))
|
||||
(log/debug :on-will-focus current-view-id)
|
||||
|
@ -34,13 +35,18 @@
|
|||
:on-did-focus
|
||||
(fn []
|
||||
(when-not modal?
|
||||
(status-bar/set-status-bar current-view-id)))}])
|
||||
(status-bar/set-status-bar current-view-id)))
|
||||
:on-will-blur
|
||||
(fn [] (reset! screen-focused? false))}])
|
||||
|
||||
(defn wrap
|
||||
"Wraps screen with main view and adds navigation-events component"
|
||||
[view-id component]
|
||||
(fn []
|
||||
(let [main-view (react/create-main-screen-view view-id)]
|
||||
(fn [args]
|
||||
(let [main-view (react/create-main-screen-view view-id)
|
||||
;; params passed to :navigate-to
|
||||
params (get-in args [:navigation :state :params])
|
||||
screen-focused? (reagent.core/atom true)]
|
||||
(if platform/ios?
|
||||
[main-view (assoc common-styles/flex
|
||||
:margin-bottom
|
||||
|
@ -64,38 +70,40 @@
|
|||
|
||||
:else
|
||||
tabs.styles/minimized-tabs-height))
|
||||
[component]
|
||||
[navigation-events view-id false]]
|
||||
[component params screen-focused?]
|
||||
[navigation-events view-id false screen-focused?]]
|
||||
|
||||
[main-view common-styles/flex
|
||||
[component]
|
||||
[navigation-events view-id false]]))))
|
||||
[component params screen-focused?]
|
||||
[navigation-events view-id false screen-focused?]]))))
|
||||
|
||||
(defn wrap-modal [modal-view component]
|
||||
"Wraps modal screen with necessary styling and adds :on-request-close handler
|
||||
on Android"
|
||||
(fn []
|
||||
(if platform/android?
|
||||
[react/view common-styles/modal
|
||||
[react/modal
|
||||
{:transparent true
|
||||
:animation-type :slide
|
||||
:on-request-close (fn []
|
||||
(cond
|
||||
(#{:wallet-send-transaction-modal
|
||||
:wallet-sign-message-modal}
|
||||
modal-view)
|
||||
(re-frame/dispatch
|
||||
[:wallet/discard-transaction-navigate-back])
|
||||
(fn [args]
|
||||
(let [params (get-in args [:navigation :state :params])
|
||||
active? (reagent.core/atom true)]
|
||||
(if platform/android?
|
||||
[react/view common-styles/modal
|
||||
[react/modal
|
||||
{:transparent true
|
||||
:animation-type :slide
|
||||
:on-request-close (fn []
|
||||
(cond
|
||||
(#{:wallet-send-transaction-modal
|
||||
:wallet-sign-message-modal}
|
||||
modal-view)
|
||||
(re-frame/dispatch
|
||||
[:wallet/discard-transaction-navigate-back])
|
||||
|
||||
:else
|
||||
(re-frame/dispatch [:navigate-back])))}
|
||||
:else
|
||||
(re-frame/dispatch [:navigate-back])))}
|
||||
[react/main-screen-modal-view modal-view
|
||||
[component params active?]]
|
||||
[navigation-events modal-view true active?]]]
|
||||
[react/main-screen-modal-view modal-view
|
||||
[component]]
|
||||
[navigation-events modal-view true]]]
|
||||
[react/main-screen-modal-view modal-view
|
||||
[component]
|
||||
[navigation-events modal-view true]])))
|
||||
[component params active?]
|
||||
[navigation-events modal-view true active?]]))))
|
||||
|
||||
(defn prepare-config [config]
|
||||
(-> config
|
||||
|
|
|
@ -82,7 +82,7 @@
|
|||
platform/android?
|
||||
(not js/goog.DEBUG)
|
||||
(not (contains? #{:intro :login :progress} @view-id)))
|
||||
(navigation/navigate-to @view-id)))
|
||||
(navigation/navigate-to @view-id nil)))
|
||||
;; see https://reactnavigation.org/docs/en/state-persistence.html#development-mode
|
||||
:persistenceKey (when js/goog.DEBUG rand-label)}]
|
||||
[bottom-sheet]]))})))
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
(defn can-be-called? []
|
||||
@navigator-ref)
|
||||
|
||||
(defn navigate-to [route]
|
||||
(defn navigate-to [route params]
|
||||
(when (can-be-called?)
|
||||
(.dispatch
|
||||
@navigator-ref
|
||||
(.navigate
|
||||
navigation-actions
|
||||
#js {:routeName (name route)}))))
|
||||
#js {:routeName (name route)
|
||||
:params (clj->js params)}))))
|
||||
|
||||
(defn- navigate [params]
|
||||
(when (can-be-called?)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
(defn has-navigated-to-browser? [result]
|
||||
(and (= (get result :status-im.ui.screens.navigation/navigate-to)
|
||||
:browser)
|
||||
[:browser nil])
|
||||
(= (get-in result [:db :view-id])
|
||||
:browser)))
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@
|
|||
:error true}}
|
||||
(-> actual :db :mailserver.edit/mailserver))))
|
||||
(testing "it navigates to edit-mailserver view"
|
||||
(is (= :edit-mailserver
|
||||
(is (= [:edit-mailserver nil]
|
||||
(:status-im.ui.screens.navigation/navigate-to actual))))))
|
||||
(testing "when an id is given"
|
||||
(testing "when the mailserver is in the list"
|
||||
|
@ -159,7 +159,7 @@
|
|||
:error false}}
|
||||
(-> actual :db :mailserver.edit/mailserver))))
|
||||
(testing "it navigates to edit-mailserver view"
|
||||
(is (= :edit-mailserver
|
||||
(is (= [:edit-mailserver nil]
|
||||
(:status-im.ui.screens.navigation/navigate-to actual))))))
|
||||
(testing "when the mailserver is not in the list"
|
||||
(let [actual (mailserver/edit cofx "not-existing")]
|
||||
|
@ -172,7 +172,7 @@
|
|||
:error true}}
|
||||
(-> actual :db :mailserver.edit/mailserver))))
|
||||
(testing "it navigates to edit-mailserver view"
|
||||
(is (= :edit-mailserver
|
||||
(is (= [:edit-mailserver nil]
|
||||
(:status-im.ui.screens.navigation/navigate-to actual)))))))))
|
||||
|
||||
(deftest connected-mailserver
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
(testing "Request notifications permissions."
|
||||
(is (contains? efx :notifications/request-notifications-permissions)))
|
||||
(testing "Navigate to :home."
|
||||
(is (= :home (efx :status-im.ui.screens.navigation/navigate-to))))
|
||||
(is (= [:home nil] (efx :status-im.ui.screens.navigation/navigate-to))))
|
||||
(testing "Account selected."
|
||||
(is (contains? new-db :account/account)))
|
||||
(testing "Chats initialized."
|
||||
|
|
Loading…
Reference in New Issue