Skip to content

Commit

Permalink
General QR code scanner flow (#18677)
Browse files Browse the repository at this point in the history
* QR scanner

* More options for QR

* Router fixes

* Updates for `on-qr-code-scanned`

* Update for communities

* Updates

* Scan profile path

* More fixes

* Last fixes for scanning

* Fixes

* Fixes

* Fixes

* Test fixes

* Fixes

* Updated Utils.m

* Test fix
  • Loading branch information
alwx authored Feb 16, 2024
1 parent 2e23dc7 commit 4956759
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 76 deletions.
5 changes: 4 additions & 1 deletion modules/react-native-status/ios/RCTStatus/Utils.m
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,12 @@ + (void) migrateKeystore:(NSString *)accountData
return StatusgoCheckAddressChecksum(address);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isAddress:(NSString *)address) {
return StatusgoIsAddress(address);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(toChecksumAddress:(NSString *)address) {
return StatusgoToChecksumAddress(address);
}


@end
2 changes: 1 addition & 1 deletion src/legacy/status_im/mobile_sync_settings/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
[(mailserver/process-next-messages-request)
(bottom-sheet/hide-bottom-sheet-old)
(wallet/restart-wallet-service nil)
(add-new-contact/set-new-identity-reconnected)]
#(add-new-contact/set-new-identity-reconnected %)]

logged-in?
[(mailserver/process-next-messages-request)
Expand Down
6 changes: 5 additions & 1 deletion src/legacy/status_im/profile/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,9 @@
{:db (-> db
(assoc :contacts/identity identity)
(assoc :contacts/ens-name ens-name))
:dispatch [:contacts/build-contact identity ens-name true]}
:dispatch [:contacts/build-contact
{:pubkey identity
:ens ens-name
:success-fn (fn [_]
{:dispatch [:open-modal :profile]})}]}
{:dispatch [:navigate-to :my-profile]})))
3 changes: 2 additions & 1 deletion src/legacy/status_im/ui/screens/wallet/recipient/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
:on-change (fn [text]
(re-frame/dispatch [:wallet-legacy/search-recipient-filter-changed text])
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
(debounce/debounce-and-dispatch [:contacts/set-new-identity text] 300))}]]))
(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input text}]
300))}]]))

(defn section
[_ _ _]
Expand Down
2 changes: 1 addition & 1 deletion src/status_im/common/home/top_nav/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
nil)]
[quo/top-nav
{:avatar-on-press #(rf/dispatch [:open-modal :settings])
:scan-on-press #(js/alert "to be implemented")
:scan-on-press #(rf/dispatch [:open-modal :shell-qr-reader])
:activity-center-on-press #(rf/dispatch [:activity-center/open])
:qr-code-on-press #(rf/dispatch [:open-modal :share-shell])
:container-style (merge style/top-nav-container container-style)
Expand Down
28 changes: 19 additions & 9 deletions src/status_im/common/router.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@

(def web2-domain "status.app")

(def user-path "u#")
(def user-with-data-path "u/")
(def community-path "c#")
(def community-with-data-path "c/")
(def channel-path "cc/")

(def web-urls (map #(str % web2-domain "/") web-prefixes))

(defn path-urls
[path]
(map #(str % path) web-urls))

(def handled-schemes (set (into uri-schemes web-urls)))

(def group-chat-extractor
Expand All @@ -41,15 +51,15 @@

(def routes
[""
{handled-schemes {["c/" :community-data] :community
["cc/" :community-data] :community-chat
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
"g/" group-chat-extractor
["wallet/" :account] :wallet-account
["u/" :user-data] :user
"c" :community
"u" :user}
{handled-schemes {[community-with-data-path :community-data] :community
[channel-path :community-data] :community-chat
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
"g/" group-chat-extractor
["wallet/" :account] :wallet-account
[user-with-data-path :user-data] :user
"c" :community
"u" :user}
ethereum-scheme eip-extractor}])

(defn parse-query-params
Expand Down
119 changes: 65 additions & 54 deletions src/status_im/contexts/chat/home/add_new_contact/events.cljs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
(ns status-im.contexts.chat.home.add-new-contact.events
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.common.validators :as validators]
[status-im.contexts.chat.contacts.events :as data-store.contacts]
status-im.contexts.chat.home.add-new-contact.effects
[status-im.navigation.events :as navigation]
[utils.ens.stateofus :as stateofus]
[utils.ethereum.chain :as chain]
[utils.re-frame :as rf]
[utils.string :as utils.string]))

(defn init-contact
Expand Down Expand Up @@ -87,72 +86,64 @@

(def validate-contact (comp ->state ->type ->id))

(defn dispatcher [event input] (fn [arg] (rf/dispatch [event input arg])))
(declare build-contact)

(rf/defn set-new-identity
{:events [:contacts/set-new-identity]}
[{:keys [db]} input scanned]
(defn set-new-identity
[{:keys [db]} [{:keys [input build-success-fn failure-fn]}]]
(let [user-public-key (get-in db [:profile/profile :public-key])
{:keys [input id ens state]
:as contact} (-> {:user-public-key user-public-key
:input input
:scanned scanned}
:scanned input}
init-contact
validate-contact)]
(case state

:empty {:db (dissoc db :contacts/new-identity)}
(:valid :invalid) {:db (assoc db :contacts/new-identity contact)}
:decompress-key {:db (assoc db :contacts/new-identity contact)
:serialization/decompress-public-key
{:compressed-key id
:on-success
(dispatcher :contacts/set-new-identity-success input)
#(re-frame/dispatch [:contacts/set-new-identity-success
{:input input
:pubkey %
:build-success-fn build-success-fn}])
:on-error
(dispatcher :contacts/set-new-identity-error input)}}
#(re-frame/dispatch [:contacts/set-new-identity-error
{:input input
:pubkey %
:failure-fn failure-fn}])}}
:resolve-ens {:db (assoc db :contacts/new-identity contact)
:effects.contacts/resolve-public-key-from-ens
{:chain-id (chain/chain-id db)
:ens ens
:on-success
(dispatcher :contacts/set-new-identity-success input)
#(re-frame/dispatch [:contacts/set-new-identity-success
{:input input
:pubkey %
:build-success-fn build-success-fn}])
:on-error
(dispatcher :contacts/set-new-identity-error input)}})))

#(re-frame/dispatch [:contacts/set-new-identity-error
{:input input
:pubkey %
:failure-fn failure-fn}])}})))

(re-frame/reg-event-fx :contacts/set-new-identity set-new-identity)

(rf/defn build-contact
{:events [:contacts/build-contact]}
[_ pubkey ens open-profile-modal?]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:js-response true
:on-success #(rf/dispatch [:contacts/contact-built
pubkey
open-profile-modal?
(data-store.contacts/<-rpc-js %)])}]})

(rf/defn contact-built
{:events [:contacts/contact-built]}
[{:keys [db]} pubkey open-profile-modal? contact]
(merge {:db (assoc-in db [:contacts/contacts pubkey] contact)}
(when open-profile-modal?
{:dispatch [:open-modal :profile]})))

(rf/defn set-new-identity-success
{:events [:contacts/set-new-identity-success]}
[{:keys [db]} input pubkey]
(defn- set-new-identity-success
[{:keys [db]} [{:keys [input pubkey build-success-fn]}]]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(rf/merge {:db (assoc db
:contacts/new-identity
(->state (assoc contact :public-key pubkey)))}
(build-contact pubkey (:ens contact) false)))))

(rf/defn set-new-identity-error
{:events [:contacts/set-new-identity-error]}
[{:keys [db]} input err]
{:db (assoc db :contacts/new-identity (->state (assoc contact :public-key pubkey)))
:dispatch [:contacts/build-contact
{:pubkey pubkey
:ens (:ens contact)
:success-fn build-success-fn}]})))

(re-frame/reg-event-fx :contacts/set-new-identity-success set-new-identity-success)

(defn- set-new-identity-error
[{:keys [db]} [{:keys [input err failure-fn]}]]
(let [contact (get-in db [:contacts/new-identity])]
(when (= (:input contact) input)
(let [state (cond
Expand All @@ -163,21 +154,41 @@
(string/includes? (:message err) "no such host")))
{:state :invalid :msg :t/lost-connection}
:else {:state :invalid})]
{:db (assoc db :contacts/new-identity (merge contact state))}))))
(merge {:db (assoc db :contacts/new-identity (merge contact state))}
(when failure-fn
(failure-fn)))))))

(re-frame/reg-event-fx :contacts/set-new-identity-error set-new-identity-error)

(rf/defn clear-new-identity
{:events [:contacts/clear-new-identity :contacts/new-chat-focus]}
(defn- build-contact
[_ [{:keys [pubkey ens success-fn]}]]
{:json-rpc/call [{:method "wakuext_buildContact"
:params [{:publicKey pubkey
:ENSName ens}]
:js-response true
:on-success #(re-frame/dispatch [:contacts/build-contact-success
{:pubkey pubkey
:contact (data-store.contacts/<-rpc-js %)
:success-fn success-fn}])}]})

(re-frame/reg-event-fx :contacts/build-contact build-contact)

(defn- build-contact-success
[{:keys [db]} [{:keys [pubkey contact success-fn]}]]
(merge {:db (assoc-in db [:contacts/contacts pubkey] contact)}
(when success-fn
(success-fn contact))))

(re-frame/reg-event-fx :contacts/build-contact-success build-contact-success)

(defn- clear-new-identity
[{:keys [db]}]
{:db (dissoc db :contacts/new-identity)})

(rf/defn qr-code-scanned
{:events [:contacts/qr-code-scanned]}
[{:keys [db] :as cofx} scanned]
(rf/merge cofx
(set-new-identity scanned scanned)
(navigation/navigate-back)))
(re-frame/reg-event-fx :contacts/clear-new-identity clear-new-identity)

(rf/defn set-new-identity-reconnected
(defn set-new-identity-reconnected
[{:keys [db]}]
(let [input (get-in db [:contacts/new-identity :input])]
(rf/dispatch [:contacts/set-new-identity input])))
(re-frame/dispatch [:contacts/set-new-identity {:input input}])))

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(:require
[cljs.test :refer-macros [deftest are]]
matcher-combinators.test
[re-frame.core :as re-frame]
[status-im.contexts.chat.home.add-new-contact.events :as events]))

(def user-ukey
Expand Down Expand Up @@ -90,8 +91,8 @@
:config {:NetworkId 1}}}})

(deftest set-new-identity-test
(with-redefs [events/dispatcher (fn [& args] args)]
(are [i edb] (match? (events/set-new-identity {:db db} i nil) edb)
(with-redefs [re-frame/dispatch (fn [& args] args)]
(are [i edb] (match? (events/set-new-identity {:db db} [{:input i}]) edb)

"" {:db db}

Expand All @@ -103,6 +104,7 @@
:id ukey
:type :public-key
:public-key ukey
:scanned ukey
:state :invalid
:msg :t/not-a-chatkey}))}

Expand All @@ -115,6 +117,7 @@
:type :ens
:ens ens-stateofus-eth
:public-key nil ; not yet...
:scanned ens
:state :resolve-ens}))
:effects.contacts/resolve-public-key-from-ens
{:chain-id 1
Expand All @@ -131,6 +134,7 @@
:id user-ckey
:type :compressed-key
:public-key nil ; not yet...
:scanned user-ckey
:state :decompress-key}))
:serialization/decompress-public-key
{:compressed-key user-ckey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
(rn/dismiss-keyboard!))
[scan-qr-code/view
{:title (i18n/label :t/scan-qr)
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity % %] 300)}]]))
:on-success-scan #(debounce/debounce-and-dispatch [:contacts/set-new-identity {:input %}]
300)}]]))

(defn view
[]
Expand Down
5 changes: 3 additions & 2 deletions src/status_im/contexts/chat/home/add_new_contact/views.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
paste-on-input #(clipboard/get-string
(fn [clipboard-text]
(reset! input-value clipboard-text)
(rf/dispatch [:contacts/set-new-identity clipboard-text nil])))]
(rf/dispatch [:contacts/set-new-identity
{:input clipboard-text}])))]
(let [{:keys [scanned]} (rf/sub [:contacts/new-identity])
empty-input? (and (string/blank? @input-value)
(string/blank? scanned))]
Expand All @@ -86,7 +87,7 @@
:value (or scanned @input-value)
:on-change-text (fn [new-text]
(reset! input-value new-text)
(as-> [:contacts/set-new-identity new-text nil] $
(as-> [:contacts/set-new-identity {:input new-text}] $
(if (string/blank? scanned)
(debounce/debounce-and-dispatch $ 600)
(rf/dispatch-sync $))))}]
Expand Down
Loading

0 comments on commit 4956759

Please sign in to comment.