mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-13 02:04:28 +00:00
fix(universal-link): more new link format, handle old link format (#17721)
Co-authored-by: pavloburykh <pavlo@status.im>
This commit is contained in:
parent
2d92b515b8
commit
859cb19886
@ -106,11 +106,9 @@
|
|||||||
:target :node-test
|
:target :node-test
|
||||||
;; Uncomment line below to `make test-watch` a specific file
|
;; Uncomment line below to `make test-watch` a specific file
|
||||||
;; :ns-regexp "status-im2.subs.messages-test$"
|
;; :ns-regexp "status-im2.subs.messages-test$"
|
||||||
:main
|
:main status-im.test-runner/main
|
||||||
status-im.test-runner/main
|
|
||||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||||
:ui-driven
|
:ui-driven true
|
||||||
true
|
|
||||||
:closure-defines
|
:closure-defines
|
||||||
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
{status-im2.config/POKT_TOKEN #shadow/env "POKT_TOKEN"
|
||||||
status-im2.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
status-im2.config/INFURA_TOKEN #shadow/env "INFURA_TOKEN"
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
(defn universal-link
|
(defn universal-link
|
||||||
[community-id]
|
[community-id]
|
||||||
(str (:external universal-links/domains)
|
(str (:external universal-links/domains)
|
||||||
"/c/"
|
"/c#"
|
||||||
community-id))
|
community-id))
|
||||||
|
|
||||||
(defn <-request-to-join-community-rpc
|
(defn <-request-to-join-community-rpc
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
|
|
||||||
(def handled-schemes (set (into uri-schemes web-urls)))
|
(def handled-schemes (set (into uri-schemes web-urls)))
|
||||||
|
|
||||||
|
(def group-chat-extractor
|
||||||
|
{[#"(.*)" :params] {"" :group-chat
|
||||||
|
"/" :group-chat}})
|
||||||
|
|
||||||
(def eip-extractor
|
(def eip-extractor
|
||||||
{#{[:prefix "-" :address]
|
{#{[:prefix "-" :address]
|
||||||
[:address]}
|
[:address]}
|
||||||
@ -39,9 +43,15 @@
|
|||||||
|
|
||||||
(def routes
|
(def routes
|
||||||
[""
|
[""
|
||||||
{handled-schemes {["c/" :community-data] :community
|
{handled-schemes {["c/" :community-data] :community
|
||||||
["cc/" :chat-data] :community-chat
|
["cc/" :community-data] :community-chat
|
||||||
["u/" :user-data] :user}
|
["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}
|
||||||
ethereum-scheme eip-extractor}])
|
ethereum-scheme eip-extractor}])
|
||||||
|
|
||||||
(defn parse-query-params
|
(defn parse-query-params
|
||||||
@ -58,7 +68,6 @@
|
|||||||
|
|
||||||
(defn match-uri
|
(defn match-uri
|
||||||
[uri]
|
[uri]
|
||||||
;;
|
|
||||||
(let [;; bidi has trouble parse path with `=` in it extract `=` here and add back to parsed
|
(let [;; bidi has trouble parse path with `=` in it extract `=` here and add back to parsed
|
||||||
;; base64url regex based on https://datatracker.ietf.org/doc/html/rfc4648#section-5 may
|
;; base64url regex based on https://datatracker.ietf.org/doc/html/rfc4648#section-5 may
|
||||||
;; include invalid base64 (invalid length, length of any base64 encoded string must be a
|
;; include invalid base64 (invalid length, length of any base64 encoded string must be a
|
||||||
@ -70,6 +79,7 @@
|
|||||||
uri-without-equal-in-path
|
uri-without-equal-in-path
|
||||||
(if equal-end-of-base64url (string/replace-first uri equal-end-of-base64url "") uri)
|
(if equal-end-of-base64url (string/replace-first uri equal-end-of-base64url "") uri)
|
||||||
|
|
||||||
|
;; fragment is the one after `#`, usually user-id, ens-name, community-id
|
||||||
fragment (parse-fragment uri)
|
fragment (parse-fragment uri)
|
||||||
ens? (ens/is-valid-eth-name? fragment)
|
ens? (ens/is-valid-eth-name? fragment)
|
||||||
|
|
||||||
@ -87,8 +97,18 @@
|
|||||||
(and equal-end-of-base64url (= handler :community) (:community-data route-params))
|
(and equal-end-of-base64url (= handler :community) (:community-data route-params))
|
||||||
(update-in [:route-params :community-data] #(str % equal-end-of-base64url))
|
(update-in [:route-params :community-data] #(str % equal-end-of-base64url))
|
||||||
|
|
||||||
(and equal-end-of-base64url (= handler :community-chat) (:chat-data route-params))
|
(and equal-end-of-base64url (= handler :community-chat) (:community-data route-params))
|
||||||
(update-in [:route-params :chat-data] #(str % equal-end-of-base64url))
|
(update-in [:route-params :community-data] #(str % equal-end-of-base64url))
|
||||||
|
|
||||||
|
(and fragment (= handler :community-chat) (:community-data route-params))
|
||||||
|
(assoc-in [:route-params :community-id] fragment)
|
||||||
|
|
||||||
|
(and fragment
|
||||||
|
(= handler :community-chat)
|
||||||
|
(:community-data route-params)
|
||||||
|
(string? (:community-data route-params))
|
||||||
|
(re-find constants/regx-starts-with-uuid (:community-data route-params)))
|
||||||
|
(assoc-in [:route-params :community-channel-id] (:community-data route-params))
|
||||||
|
|
||||||
(and equal-end-of-base64url (= handler :user) (:user-data route-params))
|
(and equal-end-of-base64url (= handler :user) (:user-data route-params))
|
||||||
(update-in [:route-params :user-data] #(str % equal-end-of-base64url))
|
(update-in [:route-params :user-data] #(str % equal-end-of-base64url))
|
||||||
@ -174,6 +194,15 @@
|
|||||||
(cb {:type :private-chat
|
(cb {:type :private-chat
|
||||||
:error :invalid-chat-id})))))
|
:error :invalid-chat-id})))))
|
||||||
|
|
||||||
|
(defn match-community-channel-async
|
||||||
|
[{:keys [community-channel-id community-id]} cb]
|
||||||
|
(if (validators/valid-compressed-key? community-id)
|
||||||
|
(native-module/deserialize-and-compress-key
|
||||||
|
community-id
|
||||||
|
#(cb {:type :community-chat :chat-id (str % community-channel-id)}))
|
||||||
|
(cb {:type :community-chat
|
||||||
|
:error :not-found})))
|
||||||
|
|
||||||
(defn match-browser
|
(defn match-browser
|
||||||
[uri {:keys [domain]}]
|
[uri {:keys [domain]}]
|
||||||
;; NOTE: We rebuild domain from original URI and matched domain
|
;; NOTE: We rebuild domain from original URI and matched domain
|
||||||
@ -238,8 +267,8 @@
|
|||||||
:community))
|
:community))
|
||||||
|
|
||||||
(defn handle-uri
|
(defn handle-uri
|
||||||
[chain _chats uri cb]
|
[chain chats uri cb]
|
||||||
(let [{:keys [handler route-params]} (match-uri uri)]
|
(let [{:keys [handler route-params query-params]} (match-uri uri)]
|
||||||
(log/info "[router] uri " uri " matched " handler " with " route-params)
|
(log/info "[router] uri " uri " matched " handler " with " route-params)
|
||||||
(cond
|
(cond
|
||||||
|
|
||||||
@ -253,36 +282,35 @@
|
|||||||
(and (= handler :user) (:user-id route-params))
|
(and (= handler :user) (:user-id route-params))
|
||||||
(match-contact-async chain route-params cb)
|
(match-contact-async chain route-params cb)
|
||||||
|
|
||||||
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
;; (= handler :private-chat)
|
(= handler :private-chat)
|
||||||
;; (match-private-chat-async chain route-params cb)
|
(match-private-chat-async chain route-params cb)
|
||||||
|
|
||||||
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
;; (= handler :group-chat)
|
(= handler :group-chat)
|
||||||
;; (cb (match-group-chat chats query-params))
|
(cb (match-group-chat chats query-params))
|
||||||
|
|
||||||
(validators/valid-public-key? uri)
|
(validators/valid-public-key? uri)
|
||||||
(match-contact-async chain {:user-id uri} cb)
|
(match-contact-async chain {:user-id uri} cb)
|
||||||
|
|
||||||
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
;; (= handler :community-requests)
|
(= handler :community-requests)
|
||||||
;; (cb {:type handler :community-id (:community-id route-params)})
|
(cb {:type handler :community-id (:community-id route-params)})
|
||||||
|
|
||||||
(and (= handler :community) (:community-id route-params))
|
(and (= handler :community) (:community-id route-params))
|
||||||
(cb {:type (community-route-type route-params)
|
(cb {:type (community-route-type route-params)
|
||||||
:community-id (:community-id route-params)})
|
:community-id (:community-id route-params)})
|
||||||
|
|
||||||
;; ;; TODO: jump to community overview for now, should jump to community channel
|
(and (= handler :community-chat) (:community-channel-id route-params) (:community-id route-params))
|
||||||
;; (and (= handler :community-chat) (:chat-id route-params))
|
(match-community-channel-async route-params cb)
|
||||||
;; (cb {:type handler :chat-id (:chat-id route-params)})
|
|
||||||
|
|
||||||
(and (= handler :community-chat) (:community-id route-params))
|
(and (= handler :community-chat) (:community-id route-params))
|
||||||
(cb {:type (community-route-type route-params)
|
(cb {:type (community-route-type route-params)
|
||||||
:community-id (:community-id route-params)})
|
:community-id (:community-id route-params)})
|
||||||
|
|
||||||
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
;; (= handler :wallet-account)
|
(= handler :wallet-account)
|
||||||
;; (cb (match-wallet-account route-params))
|
(cb (match-wallet-account route-params))
|
||||||
|
|
||||||
(address/address? uri)
|
(address/address? uri)
|
||||||
(cb (address->eip681 uri))
|
(cb (address->eip681 uri))
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
:query-params (when (= 3 (count expected)) (last expected))
|
:query-params (when (= 3 (count expected)) (last expected))
|
||||||
:uri uri})
|
:uri uri})
|
||||||
|
|
||||||
|
"https://status.app/u#zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"
|
||||||
|
[:user
|
||||||
|
{:user-id "zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"}]
|
||||||
"https://status.app/u/G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y#zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"
|
"https://status.app/u/G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y#zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"
|
||||||
[:user
|
[:user
|
||||||
{:user-data
|
{:user-data
|
||||||
@ -31,23 +34,46 @@
|
|||||||
"G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y"
|
"G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y"
|
||||||
:user-id "zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"}]
|
:user-id "zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"}]
|
||||||
|
|
||||||
|
"status-app://u#zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"
|
||||||
|
[:user
|
||||||
|
{:user-id "zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"}]
|
||||||
|
|
||||||
"https://status.app/cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
"https://status.app/cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:community-chat
|
[:community-chat
|
||||||
{:chat-data
|
{:community-data
|
||||||
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
||||||
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
"status-app://cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
"status-app://cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:community-chat
|
[:community-chat
|
||||||
{:chat-data
|
{:community-data
|
||||||
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
||||||
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
|
"https://status.app/cc/c432709e-fc73-440d-bb67-cb3a0929dfda#zQ3shZL6dXiFCbDyxnXxwQa9v8QFC2q19subFtyxd7kVszMVo"
|
||||||
|
[:community-chat
|
||||||
|
{:community-data
|
||||||
|
"c432709e-fc73-440d-bb67-cb3a0929dfda"
|
||||||
|
:community-channel-id
|
||||||
|
"c432709e-fc73-440d-bb67-cb3a0929dfda"
|
||||||
|
:community-id "zQ3shZL6dXiFCbDyxnXxwQa9v8QFC2q19subFtyxd7kVszMVo"}]
|
||||||
|
|
||||||
|
"status-app://cc/c432709e-fc73-440d-bb67-cb3a0929dfda#zQ3shZL6dXiFCbDyxnXxwQa9v8QFC2q19subFtyxd7kVszMVo"
|
||||||
|
[:community-chat
|
||||||
|
{:community-data
|
||||||
|
"c432709e-fc73-440d-bb67-cb3a0929dfda"
|
||||||
|
:community-channel-id
|
||||||
|
"c432709e-fc73-440d-bb67-cb3a0929dfda"
|
||||||
|
:community-id "zQ3shZL6dXiFCbDyxnXxwQa9v8QFC2q19subFtyxd7kVszMVo"}]
|
||||||
|
|
||||||
"https://status.app/c/iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
"https://status.app/c/iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:community
|
[:community
|
||||||
{:community-data
|
{:community-data
|
||||||
"iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM="
|
"iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM="
|
||||||
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
"https://status.app/c#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
|
[:community
|
||||||
|
{:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
"status-app://c/iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
"status-app://c/iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:community
|
[:community
|
||||||
@ -55,6 +81,10 @@
|
|||||||
"iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM="
|
"iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM="
|
||||||
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
|
"status-app://c#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
|
[:community
|
||||||
|
{:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
"ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
|
"ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
|
||||||
[:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}]
|
[:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}]
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
(ns status-im.utils.universal-links.core
|
(ns status-im.utils.universal-links.core
|
||||||
(:require
|
(:require
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[goog.string :as gstring]
|
|
||||||
[native-module.core :as native-module]
|
[native-module.core :as native-module]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.group-chats.core :as group-chats]
|
[status-im.group-chats.core :as group-chats]
|
||||||
@ -9,7 +8,6 @@
|
|||||||
[status-im.router.core :as router]
|
[status-im.router.core :as router]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.wallet.choose-recipient.core :as choose-recipient]
|
[status-im.wallet.choose-recipient.core :as choose-recipient]
|
||||||
[status-im2.constants :as constants]
|
|
||||||
[status-im2.navigation.events :as navigation]
|
[status-im2.navigation.events :as navigation]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.ethereum.chain :as chain]
|
[utils.ethereum.chain :as chain]
|
||||||
@ -27,27 +25,11 @@
|
|||||||
(def links
|
(def links
|
||||||
{:private-chat "%s/p/%s"
|
{:private-chat "%s/p/%s"
|
||||||
:community-requests "%s/cr/%s"
|
:community-requests "%s/cr/%s"
|
||||||
:community "%s/c/%s"
|
:community "%s/c#%s"
|
||||||
:group-chat "%s/g/%s"
|
:group-chat "%s/g/%s"
|
||||||
:user "%s/u/%s"
|
:user "%s/u#%s"
|
||||||
:browse "%s/b/%s"})
|
:browse "%s/b/%s"})
|
||||||
|
|
||||||
(defn generate-link
|
|
||||||
[link-type domain-type param]
|
|
||||||
(gstring/format (get links link-type)
|
|
||||||
(get domains domain-type)
|
|
||||||
param))
|
|
||||||
|
|
||||||
(defn universal-link?
|
|
||||||
[url]
|
|
||||||
(boolean
|
|
||||||
(re-matches constants/regx-universal-link url)))
|
|
||||||
|
|
||||||
(defn deep-link?
|
|
||||||
[url]
|
|
||||||
(boolean
|
|
||||||
(re-matches constants/regx-deep-link url)))
|
|
||||||
|
|
||||||
(rf/defn handle-browse
|
(rf/defn handle-browse
|
||||||
[cofx {:keys [url]}]
|
[cofx {:keys [url]}]
|
||||||
(log/info "universal-links: handling browse" url)
|
(log/info "universal-links: handling browse" url)
|
||||||
@ -220,7 +202,6 @@
|
|||||||
#_(native-module/start-searching-for-local-pairing-peers
|
#_(native-module/start-searching-for-local-pairing-peers
|
||||||
#(log/info "[local-pairing] errors from local-pairing-preflight-outbound-check ->" %)))
|
#(log/info "[local-pairing] errors from local-pairing-preflight-outbound-check ->" %)))
|
||||||
|
|
||||||
|
|
||||||
(defn finalize
|
(defn finalize
|
||||||
"Remove event listener for url"
|
"Remove event listener for url"
|
||||||
[]
|
[]
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
(is (nil? (get-in (links/handle-url {:db db} "some-url")
|
(is (nil? (get-in (links/handle-url {:db db} "some-url")
|
||||||
[:db :universal-links/url]))))
|
[:db :universal-links/url]))))
|
||||||
(testing "Handle a custom string"
|
(testing "Handle a custom string"
|
||||||
(is (= (get-in (links/handle-url {:db db} "https://status.app/u/statuse2e")
|
(is (= (get-in (links/handle-url {:db db} "https://status.app/u#statuse2e")
|
||||||
[::router/handle-uri :uri])
|
[::router/handle-uri :uri])
|
||||||
"https://status.app/u/statuse2e")))))))
|
"https://status.app/u#statuse2e")))))))
|
||||||
|
|
||||||
(deftest url-event-listener
|
(deftest url-event-listener
|
||||||
(testing "the url is not nil"
|
(testing "the url is not nil"
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
(def links
|
(def links
|
||||||
{:private-chat "%s/p/%s"
|
{:private-chat "%s/p/%s"
|
||||||
:user "%s/u/%s"
|
:user "%s/u#%s"
|
||||||
:browse "%s/b/%s"})
|
:browse "%s/b/%s"})
|
||||||
|
|
||||||
(defn universal-link?
|
(defn universal-link?
|
||||||
|
@ -184,6 +184,7 @@
|
|||||||
(def regx-ens #"^(?=.{5,255}$)([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
|
(def regx-ens #"^(?=.{5,255}$)([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$")
|
||||||
(def regx-address #"^0x[a-fA-F0-9]{40}$")
|
(def regx-address #"^0x[a-fA-F0-9]{40}$")
|
||||||
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
|
(def regx-address-contains #"(?i)0x[a-fA-F0-9]{40}")
|
||||||
|
(def regx-starts-with-uuid #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
|
||||||
|
|
||||||
(def ^:const dapp-permission-contact-code "contact-code")
|
(def ^:const dapp-permission-contact-code "contact-code")
|
||||||
(def ^:const dapp-permission-web3 "web3")
|
(def ^:const dapp-permission-web3 "web3")
|
||||||
|
@ -34,14 +34,14 @@
|
|||||||
(zipmap (repeat nil))))
|
(zipmap (repeat nil))))
|
||||||
([kv] (-> (init-contact) (merge kv))))
|
([kv] (-> (init-contact) (merge kv))))
|
||||||
|
|
||||||
(def url-regex #"^https?://status.app/u/(.+)")
|
(def url-regex #"^https?://status.app/u(/([a-zA-Z0-9_-]+)(={0,2}))?#(.+)")
|
||||||
|
|
||||||
(defn ->id
|
(defn ->id
|
||||||
[{:keys [input] :as contact}]
|
[{:keys [input] :as contact}]
|
||||||
(let [trimmed-input (utils.string/safe-trim input)]
|
(let [trimmed-input (utils.string/safe-trim input)]
|
||||||
(->> {:id (if (empty? trimmed-input)
|
(->> {:id (if (empty? trimmed-input)
|
||||||
nil
|
nil
|
||||||
(if-some [[_ id] (re-matches url-regex trimmed-input)]
|
(if-some [id (last (re-matches url-regex trimmed-input))]
|
||||||
id
|
id
|
||||||
trimmed-input))}
|
trimmed-input))}
|
||||||
(merge contact))))
|
(merge contact))))
|
||||||
@ -175,8 +175,11 @@
|
|||||||
(let [contact (get-in db [:contacts/new-identity])]
|
(let [contact (get-in db [:contacts/new-identity])]
|
||||||
(when (= (:input contact) input)
|
(when (= (:input contact) input)
|
||||||
(let [state (cond
|
(let [state (cond
|
||||||
(or (string/includes? (:message err) "fallback failed")
|
(and (string? err) (string/includes? err "invalid public key"))
|
||||||
(string/includes? (:message err) "no such host"))
|
{:state :invalid :msg :t/not-a-chatkey}
|
||||||
|
(and (string? (:message err))
|
||||||
|
(or (string/includes? (:message err) "fallback failed")
|
||||||
|
(string/includes? (:message err) "no such host")))
|
||||||
{:state :invalid :msg :t/lost-connection}
|
{:state :invalid :msg :t/lost-connection}
|
||||||
:else {:state :invalid})]
|
:else {:state :invalid})]
|
||||||
{:db (assoc db :contacts/new-identity (merge contact state))}))))
|
{:db (assoc db :contacts/new-identity (merge contact state))}))))
|
||||||
|
@ -11,8 +11,9 @@
|
|||||||
(def ckey "zQ3shWj4WaBdf2zYKCkXe6PHxDxNTzZyid1i75879Ue9cX9gA")
|
(def ckey "zQ3shWj4WaBdf2zYKCkXe6PHxDxNTzZyid1i75879Ue9cX9gA")
|
||||||
(def ens "esep")
|
(def ens "esep")
|
||||||
(def ens-stateofus-eth (str ens ".stateofus.eth"))
|
(def ens-stateofus-eth (str ens ".stateofus.eth"))
|
||||||
(def link-ckey (str "https://status.app/u/" ckey))
|
(def link-ckey (str "https://status.app/u#" ckey))
|
||||||
(def link-ens (str "https://status.app/u/" ens))
|
(def link-ckey-with-encoded-data (str "https://status.app/u/CwSACgcKBVBhdmxvAw==#" ckey))
|
||||||
|
(def link-ens (str "https://status.app/u#" ens))
|
||||||
|
|
||||||
;;; unit tests (no app-db involved)
|
;;; unit tests (no app-db involved)
|
||||||
|
|
||||||
@ -22,56 +23,61 @@
|
|||||||
:input i}))
|
:input i}))
|
||||||
(events/init-contact e))
|
(events/init-contact e))
|
||||||
|
|
||||||
"" {:user-public-key user-ukey
|
"" {:user-public-key user-ukey
|
||||||
:input ""
|
:input ""
|
||||||
:type :empty
|
:type :empty
|
||||||
:state :empty}
|
:state :empty}
|
||||||
|
|
||||||
" " {:user-public-key user-ukey
|
" " {:user-public-key user-ukey
|
||||||
:input " "
|
:input " "
|
||||||
:type :empty
|
:type :empty
|
||||||
:state :empty}
|
:state :empty}
|
||||||
|
|
||||||
ukey {:user-public-key user-ukey
|
ukey {:user-public-key user-ukey
|
||||||
:input ukey
|
:input ukey
|
||||||
:id ukey
|
:id ukey
|
||||||
:type :public-key
|
:type :public-key
|
||||||
:public-key ukey
|
:public-key ukey
|
||||||
:state :invalid
|
:state :invalid
|
||||||
:msg :t/not-a-chatkey}
|
:msg :t/not-a-chatkey}
|
||||||
|
|
||||||
ens {:user-public-key user-ukey
|
ens {:user-public-key user-ukey
|
||||||
:input ens
|
:input ens
|
||||||
:id ens
|
:id ens
|
||||||
:type :ens
|
:type :ens
|
||||||
:ens ens-stateofus-eth
|
:ens ens-stateofus-eth
|
||||||
:state :resolve-ens}
|
:state :resolve-ens}
|
||||||
|
|
||||||
(str " " ens) {:user-public-key user-ukey
|
(str " " ens) {:user-public-key user-ukey
|
||||||
:input (str " " ens)
|
:input (str " " ens)
|
||||||
:id ens
|
:id ens
|
||||||
:type :ens
|
:type :ens
|
||||||
:ens ens-stateofus-eth
|
:ens ens-stateofus-eth
|
||||||
:state :resolve-ens}
|
:state :resolve-ens}
|
||||||
|
|
||||||
ckey {:user-public-key user-ukey
|
ckey {:user-public-key user-ukey
|
||||||
:input ckey
|
:input ckey
|
||||||
:id ckey
|
:id ckey
|
||||||
:type :compressed-key
|
:type :compressed-key
|
||||||
:state :decompress-key}
|
:state :decompress-key}
|
||||||
|
|
||||||
link-ckey {:user-public-key user-ukey
|
link-ckey {:user-public-key user-ukey
|
||||||
:input link-ckey
|
:input link-ckey
|
||||||
:id ckey
|
:id ckey
|
||||||
:type :compressed-key
|
:type :compressed-key
|
||||||
:state :decompress-key}
|
:state :decompress-key}
|
||||||
|
link-ckey-with-encoded-data {:user-public-key user-ukey
|
||||||
|
:input link-ckey-with-encoded-data
|
||||||
|
:id ckey
|
||||||
|
:type :compressed-key
|
||||||
|
:state :decompress-key}
|
||||||
|
|
||||||
link-ens {:user-public-key user-ukey
|
link-ens {:user-public-key user-ukey
|
||||||
:input link-ens
|
:input link-ens
|
||||||
:id ens
|
:id ens
|
||||||
:type :ens
|
:type :ens
|
||||||
:ens ens-stateofus-eth
|
:ens ens-stateofus-eth
|
||||||
:state :resolve-ens}))
|
:state :resolve-ens}))
|
||||||
|
|
||||||
;;; event handler tests (no callbacks)
|
;;; event handler tests (no callbacks)
|
||||||
|
|
||||||
|
@ -80,11 +80,10 @@
|
|||||||
:button (when empty-input?
|
:button (when empty-input?
|
||||||
{:on-press paste-on-input
|
{:on-press paste-on-input
|
||||||
:text (i18n/label :t/paste)})
|
:text (i18n/label :t/paste)})
|
||||||
;; NOTE: `scanned` has priority over `@input-value`, we clean it when the input
|
;; NOTE: `scanned` has priority over `@input-value`, we clean it when the input is updated
|
||||||
;; is updated so that it's `nil` and `@input-value` is shown.
|
;; so that it's `nil` and `@input-value` is shown. To fastly clean it, we use
|
||||||
;; To fastly clean it, we use `dispatch-sync`.
|
;; `dispatch-sync`. This call could be avoided if `::qr-scanner/scan-code` were able to
|
||||||
;; This call could be avoided if `::qr-scanner/scan-code` were able to receive a
|
;; receive a callback function, not only a re-frame event as callback.
|
||||||
;; callback function, not only a re-frame event as callback.
|
|
||||||
:value (or scanned @input-value)
|
:value (or scanned @input-value)
|
||||||
:on-change-text (fn [new-text]
|
:on-change-text (fn [new-text]
|
||||||
(reset! input-value new-text)
|
(reset! input-value new-text)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
(defn community-link
|
(defn community-link
|
||||||
[id]
|
[id]
|
||||||
(str "https://status.app/c/" id))
|
(str "https://status.app/c#" id))
|
||||||
|
|
||||||
(rf/defn cache-link-preview-data
|
(rf/defn cache-link-preview-data
|
||||||
{:events [:chat.ui/cache-link-preview-data]}
|
{:events [:chat.ui/cache-link-preview-data]}
|
||||||
|
@ -62,16 +62,16 @@
|
|||||||
[]
|
[]
|
||||||
(let [media-server-port (rf/sub [:mediaserver/port])
|
(let [media-server-port (rf/sub [:mediaserver/port])
|
||||||
state (reagent/atom
|
state (reagent/atom
|
||||||
{:url "https://join.status.im/status"
|
{:url "https://status.app/u#zQ34e1zlOdas0pKnvrweeedsasas12adjie8"
|
||||||
:size 250
|
:size 250
|
||||||
:avatar :none
|
:avatar :none
|
||||||
:profile-picture (resources/get-mock-image :user-picture-male5)
|
:profile-picture (resources/get-mock-image :user-picture-male5)
|
||||||
:customization-color :army
|
:customization-color :army
|
||||||
:full-name "Full Name"
|
:full-name "Full Name"
|
||||||
:emoji "🍒"
|
:emoji "🍒"
|
||||||
:picture (resources/get-mock-image :community-logo)
|
:picture (resources/get-mock-image :community-logo)
|
||||||
:f-name "First Name"
|
:f-name "First Name"
|
||||||
:l-name "Last Name"})]
|
:l-name "Last Name"})]
|
||||||
(fn []
|
(fn []
|
||||||
(let [qr-media-server-uri (image-server/get-qr-image-uri-for-any-url
|
(let [qr-media-server-uri (image-server/get-qr-image-uri-for-any-url
|
||||||
{:url (:url @state)
|
{:url (:url @state)
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
(str (name network) ":")))
|
(str (name network) ":")))
|
||||||
|
|
||||||
(def ^:private profile-link
|
(def ^:private profile-link
|
||||||
"https://join.status.im/u/zQ3shfc5Wqnu")
|
"https://status.app/u#zQ34e1zlOdas0pKnvrweeedsasas12adjie8")
|
||||||
|
|
||||||
(def ^:private wallet-address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2")
|
(def ^:private wallet-address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2")
|
||||||
|
|
||||||
|
@ -43,11 +43,11 @@
|
|||||||
|
|
||||||
(defn get-abbreviated-profile-url
|
(defn get-abbreviated-profile-url
|
||||||
"The goal here is to generate a string that begins with
|
"The goal here is to generate a string that begins with
|
||||||
status.app/u/ joined with the 1st 5 characters
|
status.app/u# joined with the 1st 5 characters
|
||||||
of the compressed public key followed by an ellipsis followed by
|
of the compressed public key followed by an ellipsis followed by
|
||||||
the last 10 characters of the compressed public key"
|
the last 10 characters of the compressed public key"
|
||||||
[base-url public-key]
|
[base-url public-key]
|
||||||
(if (and public-key base-url (> (count public-key) 17) (= "status.app/u/" base-url))
|
(if (and public-key base-url (> (count public-key) 17) (= "status.app/u#" base-url))
|
||||||
(let [first-part-of-public-pk (subs public-key 0 5)
|
(let [first-part-of-public-pk (subs public-key 0 5)
|
||||||
ellipsis "..."
|
ellipsis "..."
|
||||||
public-key-size (count public-key)
|
public-key-size (count public-key)
|
||||||
|
@ -22,22 +22,22 @@
|
|||||||
|
|
||||||
(deftest test-get-abbreviated-profile-url
|
(deftest test-get-abbreviated-profile-url
|
||||||
(testing "Ensure the function correctly generates an abbreviated profile URL for a valid public key"
|
(testing "Ensure the function correctly generates an abbreviated profile URL for a valid public key"
|
||||||
(is (= "status.app/u/zQ3sh...mrdYpzeFUa"
|
(is (= "status.app/u#zQ3sh...mrdYpzeFUa"
|
||||||
(utils.address/get-abbreviated-profile-url
|
(utils.address/get-abbreviated-profile-url
|
||||||
"status.app/u/"
|
"status.app/u#"
|
||||||
"zQ3shPrnUhhR42JJn3QdhodGest8w8MjiH8hPaimrdYpzeFUa"))))
|
"zQ3shPrnUhhR42JJn3QdhodGest8w8MjiH8hPaimrdYpzeFUa"))))
|
||||||
|
|
||||||
(testing "Ensure the function returns nil when given an empty public key"
|
(testing "Ensure the function returns nil when given an empty public key"
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u/" ""))))
|
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u#" ""))))
|
||||||
|
|
||||||
(testing "Ensure the function returns nil when given a nil public key"
|
(testing "Ensure the function returns nil when given a nil public key"
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u/" nil))))
|
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u#" nil))))
|
||||||
|
|
||||||
(testing "Ensure the function returns nil when given an incorrect base URL"
|
(testing "Ensure the function returns nil when given an incorrect base URL"
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url
|
(is (nil? (utils.address/get-abbreviated-profile-url
|
||||||
"status.app/uwu/"
|
"status.app/uwu#"
|
||||||
"zQ3shPrnUhhR42JJn3QdhodGest8w8MjiH8hPaimrdYpzeFUa"))))
|
"zQ3shPrnUhhR42JJn3QdhodGest8w8MjiH8hPaimrdYpzeFUa"))))
|
||||||
|
|
||||||
(testing "Ensure the function returns nil when given a public key shorter than 17 characters"
|
(testing "Ensure the function returns nil when given a public key shorter than 17 characters"
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u/" "abc")))
|
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u#" "abc")))
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u/" "1234")))))
|
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u#" "1234")))))
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
(def ^:const account-initials-action "/accountInitials")
|
(def ^:const account-initials-action "/accountInitials")
|
||||||
(def ^:const contact-images-action "/contactImages")
|
(def ^:const contact-images-action "/contactImages")
|
||||||
(def ^:const generate-qr-action "/GenerateQRCode")
|
(def ^:const generate-qr-action "/GenerateQRCode")
|
||||||
(def ^:const status-profile-base-url "https://status.app/u/")
|
(def ^:const status-profile-base-url "https://status.app/u#")
|
||||||
(def ^:const status-profile-base-url-without-https "status.app/u/")
|
(def ^:const status-profile-base-url-without-https "status.app/u#")
|
||||||
|
|
||||||
(defn get-font-file-ready
|
(defn get-font-file-ready
|
||||||
"setup font file and get the absolute path to it
|
"setup font file and get the absolute path to it
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.171.7",
|
"version": "v0.171.8",
|
||||||
"commit-sha1": "74396b461df0c18593262a67c9fd79d706287f7a",
|
"commit-sha1": "678fc03b376e02df7142e89f2c626e3ba1c03807",
|
||||||
"src-sha256": "1d46lav3g6m1f6ifpypjlsp2qm82c6yk4478awb8f68azpdkvcg5"
|
"src-sha256": "0bapjbyyyrvg2k3jimpfshcwc77lylamhlm9si3mbnrbm1dl89xc"
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ class TestActivityCenterContactRequestMultipleDevicePR(MultipleSharedDeviceTestC
|
|||||||
self.device_2.create_user(third_user=True, username=new_username_2)
|
self.device_2.create_user(third_user=True, username=new_username_2)
|
||||||
|
|
||||||
self.device_2.just_fyi('Device2 sends a contact request to Device1 using his profile link')
|
self.device_2.just_fyi('Device2 sends a contact request to Device1 using his profile link')
|
||||||
self.home_2.driver.set_clipboard_text("https://status.app/u/" + self.public_key_1)
|
self.home_2.driver.set_clipboard_text("https://status.app/u#" + self.public_key_1)
|
||||||
self.home_2.chats_tab.click()
|
self.home_2.chats_tab.click()
|
||||||
self.home_2.new_chat_button.click_until_presence_of_element(self.home_2.add_a_contact_chat_bottom_sheet_button)
|
self.home_2.new_chat_button.click_until_presence_of_element(self.home_2.add_a_contact_chat_bottom_sheet_button)
|
||||||
self.home_2.add_a_contact_chat_bottom_sheet_button.click()
|
self.home_2.add_a_contact_chat_bottom_sheet_button.click()
|
||||||
|
@ -564,4 +564,4 @@ class HomeView(BaseView):
|
|||||||
self.link_to_profile_text.click()
|
self.link_to_profile_text.click()
|
||||||
c_text = self.driver.get_clipboard_text()
|
c_text = self.driver.get_clipboard_text()
|
||||||
self.click_system_back_button()
|
self.click_system_back_button()
|
||||||
return c_text.split("/")[-1]
|
return c_text.split("#")[-1]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user