mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-13 18:25:45 +00:00
feat: support new universal/deep link format (#17480)
This commit is contained in:
parent
ca6fd3df66
commit
04a7f76271
@ -62,14 +62,14 @@
|
|||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="http" android:host="join.status.im" />
|
<data android:scheme="http" android:host="status.app" />
|
||||||
<data android:scheme="https" android:host="join.status.im" />
|
<data android:scheme="https" android:host="status.app" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter android:autoVerify="true">
|
<intent-filter android:autoVerify="true">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="status-im" />
|
<data android:scheme="status-app" />
|
||||||
<data android:scheme="ethereum" />
|
<data android:scheme="ethereum" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<string>im.status.ethereum.applink</string>
|
<string>im.status.ethereum.applink</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>status-im</string>
|
<string>status-app</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<string>development</string>
|
<string>development</string>
|
||||||
<key>com.apple.developer.associated-domains</key>
|
<key>com.apple.developer.associated-domains</key>
|
||||||
<array>
|
<array>
|
||||||
<string>applinks:join.status.im</string>
|
<string>applinks:status.app</string>
|
||||||
</array>
|
</array>
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
<array>
|
<array>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<string>im.status.ethereum.applink</string>
|
<string>im.status.ethereum.applink</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>status-im</string>
|
<string>status-app</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<string>development</string>
|
<string>development</string>
|
||||||
<key>com.apple.developer.associated-domains</key>
|
<key>com.apple.developer.associated-domains</key>
|
||||||
<array>
|
<array>
|
||||||
<string>applinks:join.status.im</string>
|
<string>applinks:status.app</string>
|
||||||
</array>
|
</array>
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
<array>
|
<array>
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
[status-im.ethereum.eip681 :as eip681]
|
[status-im.ethereum.eip681 :as eip681]
|
||||||
[status-im.ethereum.ens :as ens]
|
[status-im.ethereum.ens :as ens]
|
||||||
[status-im.ethereum.stateofus :as stateofus]
|
[status-im.ethereum.stateofus :as stateofus]
|
||||||
[status-im.utils.deprecated-types :as types]
|
|
||||||
[status-im.utils.wallet-connect :as wallet-connect]
|
[status-im.utils.wallet-connect :as wallet-connect]
|
||||||
[status-im2.constants :as constants]
|
[status-im2.constants :as constants]
|
||||||
[status-im2.contexts.chat.events :as chat.events]
|
[status-im2.contexts.chat.events :as chat.events]
|
||||||
@ -15,29 +14,22 @@
|
|||||||
[utils.address :as address]
|
[utils.address :as address]
|
||||||
[utils.ethereum.chain :as chain]
|
[utils.ethereum.chain :as chain]
|
||||||
[utils.security.core :as security]
|
[utils.security.core :as security]
|
||||||
|
[utils.transforms :as transforms]
|
||||||
[utils.url :as url]
|
[utils.url :as url]
|
||||||
[utils.validators :as validators]))
|
[utils.validators :as validators]))
|
||||||
|
|
||||||
(def ethereum-scheme "ethereum:")
|
(def ethereum-scheme "ethereum:")
|
||||||
|
|
||||||
(def uri-schemes ["status-im://" "status-im:"])
|
(def uri-schemes ["status-app://"])
|
||||||
|
|
||||||
(def web-prefixes ["https://" "http://" "https://www." "http://www."])
|
(def web-prefixes ["https://" "http://" "https://www." "http://www."])
|
||||||
|
|
||||||
(def web2-domain "join.status.im")
|
(def web2-domain "status.app")
|
||||||
|
|
||||||
(def web-urls (map #(str % web2-domain "/") web-prefixes))
|
(def web-urls (map #(str % web2-domain "/") web-prefixes))
|
||||||
|
|
||||||
(def handled-schemes (set (into uri-schemes web-urls)))
|
(def handled-schemes (set (into uri-schemes web-urls)))
|
||||||
|
|
||||||
(def browser-extractor
|
|
||||||
{[#"(.*)" :domain] {"" :browser
|
|
||||||
"/" :browser}})
|
|
||||||
|
|
||||||
(def group-chat-extractor
|
|
||||||
{[#"(.*)" :params] {"" :group-chat
|
|
||||||
"/" :group-chat}})
|
|
||||||
|
|
||||||
(def eip-extractor
|
(def eip-extractor
|
||||||
{#{[:prefix "-" :address]
|
{#{[:prefix "-" :address]
|
||||||
[:address]}
|
[:address]}
|
||||||
@ -47,16 +39,9 @@
|
|||||||
|
|
||||||
(def routes
|
(def routes
|
||||||
[""
|
[""
|
||||||
{handled-schemes {"b/" browser-extractor
|
{handled-schemes {["c/" :community-data] :community
|
||||||
"browser/" browser-extractor
|
["cc/" :chat-data] :community-chat
|
||||||
["p/" :chat-id] :private-chat
|
["u/" :user-data] :user}
|
||||||
["cr/" :community-id] :community-requests
|
|
||||||
["c/" :community-id] :community
|
|
||||||
["cc/" :chat-id] :community-chat
|
|
||||||
"g/" group-chat-extractor
|
|
||||||
["wallet/" :account] :wallet-account
|
|
||||||
["u/" :user-id] :user
|
|
||||||
["user/" :user-id] :user}
|
|
||||||
ethereum-scheme eip-extractor}])
|
ethereum-scheme eip-extractor}])
|
||||||
|
|
||||||
(defn parse-query-params
|
(defn parse-query-params
|
||||||
@ -64,9 +49,52 @@
|
|||||||
(let [url (goog.Uri. url)]
|
(let [url (goog.Uri. url)]
|
||||||
(url/query->map (.getQuery url))))
|
(url/query->map (.getQuery url))))
|
||||||
|
|
||||||
|
(defn parse-fragment
|
||||||
|
[url]
|
||||||
|
(let [url (goog.Uri. url)
|
||||||
|
fragment (.getFragment url)]
|
||||||
|
(when-not (string/blank? fragment)
|
||||||
|
fragment)))
|
||||||
|
|
||||||
(defn match-uri
|
(defn match-uri
|
||||||
[uri]
|
[uri]
|
||||||
(assoc (bidi/match-route routes uri) :uri uri :query-params (parse-query-params uri)))
|
;;
|
||||||
|
(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
|
||||||
|
;; include invalid base64 (invalid length, length of any base64 encoded string must be a
|
||||||
|
;; multiple of 4)
|
||||||
|
;; equal-end-of-base64url can be `=`, `==`, `nil`
|
||||||
|
equal-end-of-base64url
|
||||||
|
(last (re-find #"^(https|status-app)://(status\.app/)?(c|cc|u)/([a-zA-Z0-9_-]+)(={0,2})#" uri))
|
||||||
|
|
||||||
|
uri-without-equal-in-path
|
||||||
|
(if equal-end-of-base64url (string/replace-first uri equal-end-of-base64url "") uri)
|
||||||
|
|
||||||
|
fragment (parse-fragment uri)
|
||||||
|
ens? (ens/is-valid-eth-name? fragment)
|
||||||
|
|
||||||
|
{:keys [handler route-params] :as parsed}
|
||||||
|
(assoc (bidi/match-route routes uri-without-equal-in-path)
|
||||||
|
:uri uri
|
||||||
|
:query-params (parse-query-params uri))]
|
||||||
|
(cond-> parsed
|
||||||
|
ens?
|
||||||
|
(assoc-in [:route-params :ens-name] fragment)
|
||||||
|
|
||||||
|
(and (or (= handler :community) (= handler :community-chat)) fragment)
|
||||||
|
(assoc-in [:route-params :community-id] fragment)
|
||||||
|
|
||||||
|
(and equal-end-of-base64url (= handler :community) (:community-data route-params))
|
||||||
|
(update-in [:route-params :community-data] #(str % equal-end-of-base64url))
|
||||||
|
|
||||||
|
(and equal-end-of-base64url (= handler :community-chat) (:chat-data route-params))
|
||||||
|
(update-in [:route-params :chat-data] #(str % equal-end-of-base64url))
|
||||||
|
|
||||||
|
(and equal-end-of-base64url (= handler :user) (:user-data route-params))
|
||||||
|
(update-in [:route-params :user-data] #(str % equal-end-of-base64url))
|
||||||
|
|
||||||
|
(and (= handler :user) fragment)
|
||||||
|
(assoc-in [:route-params :user-id] fragment))))
|
||||||
|
|
||||||
(defn match-contact-async
|
(defn match-contact-async
|
||||||
[chain {:keys [user-id ens-name]} callback]
|
[chain {:keys [user-id ens-name]} callback]
|
||||||
@ -84,7 +112,7 @@
|
|||||||
user-id
|
user-id
|
||||||
constants/deserialization-key
|
constants/deserialization-key
|
||||||
(fn [response]
|
(fn [response]
|
||||||
(let [{:keys [error]} (types/json->clj response)]
|
(let [{:keys [error]} (transforms/json->clj response)]
|
||||||
(when-not error
|
(when-not error
|
||||||
(match-contact-async
|
(match-contact-async
|
||||||
chain
|
chain
|
||||||
@ -210,41 +238,51 @@
|
|||||||
:community))
|
:community))
|
||||||
|
|
||||||
(defn handle-uri
|
(defn handle-uri
|
||||||
[chain chats uri cb]
|
[chain _chats uri cb]
|
||||||
(let [{:keys [handler route-params query-params]} (match-uri uri)]
|
(let [{:keys [handler route-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
|
||||||
|
|
||||||
(= handler :browser)
|
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
(cb (match-browser uri route-params))
|
;; (= handler :browser)
|
||||||
|
;; (cb (match-browser uri route-params))
|
||||||
|
|
||||||
(= handler :ethereum)
|
(= handler :ethereum)
|
||||||
(cb (match-eip681 uri))
|
(cb (match-eip681 uri))
|
||||||
|
|
||||||
(= handler :user)
|
(and (= handler :user) (:user-id route-params))
|
||||||
(match-contact-async chain route-params cb)
|
(match-contact-async chain route-params cb)
|
||||||
|
|
||||||
(= handler :private-chat)
|
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
(match-private-chat-async chain route-params cb)
|
;; (= handler :private-chat)
|
||||||
|
;; (match-private-chat-async chain route-params cb)
|
||||||
|
|
||||||
(= handler :group-chat)
|
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
(cb (match-group-chat chats query-params))
|
;; (= handler :group-chat)
|
||||||
|
;; (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)
|
||||||
|
|
||||||
(= handler :community-requests)
|
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
(cb {:type handler :community-id (:community-id route-params)})
|
;; (= handler :community-requests)
|
||||||
|
;; (cb {:type handler :community-id (:community-id route-params)})
|
||||||
|
|
||||||
(= handler :community)
|
(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)})
|
||||||
|
|
||||||
(= handler :community-chat)
|
;; ;; TODO: jump to community overview for now, should jump to community channel
|
||||||
(cb {:type handler :chat-id (:chat-id route-params)})
|
;; (and (= handler :community-chat) (:chat-id route-params))
|
||||||
|
;; (cb {:type handler :chat-id (:chat-id route-params)})
|
||||||
|
|
||||||
(= handler :wallet-account)
|
(and (= handler :community-chat) (:community-id route-params))
|
||||||
(cb (match-wallet-account route-params))
|
(cb {:type (community-route-type route-params)
|
||||||
|
:community-id (:community-id route-params)})
|
||||||
|
|
||||||
|
;; ;; NOTE: removed in `match-uri`, might need this in the future
|
||||||
|
;; (= handler :wallet-account)
|
||||||
|
;; (cb (match-wallet-account route-params))
|
||||||
|
|
||||||
(address/address? uri)
|
(address/address? uri)
|
||||||
(cb (address->eip681 uri))
|
(cb (address->eip681 uri))
|
||||||
|
@ -19,33 +19,41 @@
|
|||||||
:query-params (when (= 3 (count expected)) (last expected))
|
:query-params (when (= 3 (count expected)) (last expected))
|
||||||
:uri uri})
|
:uri uri})
|
||||||
|
|
||||||
"status-im://u/statuse2e"
|
"https://status.app/u/G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y#zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"
|
||||||
[:user {:user-id "statuse2e"}]
|
[:user
|
||||||
|
{:user-data
|
||||||
|
"G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y"
|
||||||
|
:user-id "zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"}]
|
||||||
|
|
||||||
(str "status-im://user/" public-key)
|
"status-app://u/G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y#zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"
|
||||||
[:user {:user-id public-key}]
|
[:user
|
||||||
|
{:user-data
|
||||||
|
"G10A4B0JdgwyRww90WXtnP1oNH1ZLQNM0yX0Ja9YyAMjrqSZIYINOHCbFhrnKRAcPGStPxCMJDSZlGCKzmZrJcimHY8BbcXlORrElv_BbQEegnMDPx1g9C5VVNl0fE4y"
|
||||||
|
:user-id "zQ3shwQPhRuDJSjVGVBnTjCdgXy5i9WQaeVPdGJD6yTarJQSj"}]
|
||||||
|
|
||||||
"status-im://b/www.cryptokitties.co"
|
"https://status.app/cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:browser {:domain "www.cryptokitties.c"}]
|
[:community-chat
|
||||||
|
{:chat-data
|
||||||
|
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
||||||
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
(str "status-im://g/args?a=" public-key "&a1=" chat-name-url "&a2=" chat-id)
|
"status-app://cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:group-chat {:params "arg"} {"a" public-key "a1" chat-name "a2" chat-id}]
|
[:community-chat
|
||||||
|
{:chat-data
|
||||||
|
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
||||||
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
(str "https://join.status.im/g/args?a=" public-key "&a1=" chat-name-url "&a2=" chat-id)
|
"https://status.app/c/iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:group-chat {:params "arg"} {"a" public-key "a1" chat-name "a2" chat-id}]
|
[:community
|
||||||
|
{:community-data
|
||||||
|
"iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM="
|
||||||
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
"https://join.status.im/u/statuse2e"
|
"status-app://c/iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||||
[:user {:user-id "statuse2e"}]
|
[:community
|
||||||
|
{:community-data
|
||||||
(str "https://join.status.im/user/" public-key)
|
"iyKACkQKB0Rvb2RsZXMSJ0NvbG9yaW5nIHRoZSB3b3JsZCB3aXRoIGpveSDigKIg4bSXIOKAohiYohsiByMxMzFEMkYqAwEhMwM="
|
||||||
[:user {:user-id public-key}]
|
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||||
|
|
||||||
;; Last char removed by: https://github.com/juxt/bidi/issues/104
|
|
||||||
"https://join.status.im/b/www.cryptokitties.co"
|
|
||||||
[:browser {:domain "www.cryptokitties.c"}]
|
|
||||||
|
|
||||||
"https://join.status.im/b/https://www.google.com/"
|
|
||||||
[:browser {:domain "https://www.google.co"}]
|
|
||||||
|
|
||||||
"ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
|
"ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
|
||||||
[:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}]
|
[:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}]
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
(i18n/label :t/browsing-site-blocked-title)]
|
(i18n/label :t/browsing-site-blocked-title)]
|
||||||
[react/nested-text {:style styles/description-text}
|
[react/nested-text {:style styles/description-text}
|
||||||
(i18n/label :t/browsing-site-blocked-description1)
|
(i18n/label :t/browsing-site-blocked-description1)
|
||||||
[{:on-press #(.openURL ^js react/linking "status-im://chat/public/status")
|
;; NOTE: this link is broken
|
||||||
|
[{:on-press #(.openURL ^js react/linking "status-app://chat/public/status")
|
||||||
:style styles/chat-link-text}
|
:style styles/chat-link-text}
|
||||||
"#status"]
|
"#status"]
|
||||||
(i18n/label :t/browsing-site-blocked-description2)]
|
(i18n/label :t/browsing-site-blocked-description2)]
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
;; domains should be without the trailing slash
|
;; domains should be without the trailing slash
|
||||||
(def domains
|
(def domains
|
||||||
{:external "https://join.status.im"
|
{:external "https://status.app"
|
||||||
:internal "status-im:/"})
|
:internal "status-app:/"})
|
||||||
|
|
||||||
(def links
|
(def links
|
||||||
{:private-chat "%s/p/%s"
|
{:private-chat "%s/p/%s"
|
||||||
@ -81,17 +81,20 @@
|
|||||||
(log/info "universal-links: handling community" community-id)
|
(log/info "universal-links: handling community" community-id)
|
||||||
(navigation/navigate-to cofx :community {:community-id community-id}))
|
(navigation/navigate-to cofx :community {:community-id community-id}))
|
||||||
|
|
||||||
|
|
||||||
(rf/defn handle-navigation-to-desktop-community-from-mobile
|
(rf/defn handle-navigation-to-desktop-community-from-mobile
|
||||||
{:events [:handle-navigation-to-desktop-community-from-mobile]}
|
{:events [:handle-navigation-to-desktop-community-from-mobile]}
|
||||||
[cofx deserialized-key]
|
[cofx deserialized-key]
|
||||||
(navigation/navigate-to cofx :community-overview deserialized-key))
|
(rf/merge
|
||||||
|
cofx
|
||||||
|
{:dispatch [:navigate-to :community-overview deserialized-key]}
|
||||||
|
(navigation/pop-to-root :shell-stack)))
|
||||||
|
|
||||||
(rf/defn handle-desktop-community
|
(rf/defn handle-desktop-community
|
||||||
[cofx {:keys [community-id]}]
|
[cofx {:keys [community-id]}]
|
||||||
(native-module/deserialize-and-compress-key
|
(native-module/deserialize-and-compress-key
|
||||||
community-id
|
community-id
|
||||||
(fn [deserialized-key]
|
(fn [deserialized-key]
|
||||||
|
(rf/dispatch [:chat.ui/resolve-community-info (str deserialized-key)])
|
||||||
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile (str deserialized-key)]))))
|
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile (str deserialized-key)]))))
|
||||||
|
|
||||||
(rf/defn handle-community-chat
|
(rf/defn handle-community-chat
|
||||||
@ -212,9 +215,8 @@
|
|||||||
(.then dispatch-url))
|
(.then dispatch-url))
|
||||||
200)
|
200)
|
||||||
(.addEventListener ^js react/linking "url" url-event-listener)
|
(.addEventListener ^js react/linking "url" url-event-listener)
|
||||||
;;StartSearchForLocalPairingPeers() shouldn't be called ATM from the UI
|
;;StartSearchForLocalPairingPeers() shouldn't be called ATM from the UI It can be called after the
|
||||||
;;It can be called after the error "route ip+net: netlinkrib: permission denied" is fixed on status-go
|
;;error "route ip+net: netlinkrib: permission denied" is fixed on status-go side
|
||||||
;;side
|
|
||||||
#_(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 ->" %)))
|
||||||
|
|
||||||
|
@ -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://join.status.im/u/statuse2e")
|
(is (= (get-in (links/handle-url {:db db} "https://status.app/u/statuse2e")
|
||||||
[::router/handle-uri :uri])
|
[::router/handle-uri :uri])
|
||||||
"https://join.status.im/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"
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
;; domains should be without the trailing slash
|
;; domains should be without the trailing slash
|
||||||
(def domains
|
(def domains
|
||||||
{:external "https://join.status.im"
|
{:external "https://status.app"
|
||||||
:internal "status-im:/"})
|
:internal "status-app:/"})
|
||||||
|
|
||||||
(def links
|
(def links
|
||||||
{:private-chat "%s/p/%s"
|
{:private-chat "%s/p/%s"
|
||||||
|
@ -4,25 +4,25 @@
|
|||||||
[status-im.utils.universal-links.utils :as links]))
|
[status-im.utils.universal-links.utils :as links]))
|
||||||
|
|
||||||
(deftest universal-link-test
|
(deftest universal-link-test
|
||||||
(testing "status-im://blah"
|
(testing "status-app://blah"
|
||||||
(testing "it returns true"
|
(testing "it returns true"
|
||||||
(is (links/universal-link? "status-im://blah"))))
|
(is (links/universal-link? "status-app://blah"))))
|
||||||
(testing "status-im://blah"
|
(testing "status-app://blah"
|
||||||
(testing "it returns true"
|
(testing "it returns true"
|
||||||
(is (links/deep-link? "status-im://blah"))))
|
(is (links/deep-link? "status-app://blah"))))
|
||||||
(testing "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
|
(testing "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"
|
||||||
(testing "it returns true"
|
(testing "it returns true"
|
||||||
(is (links/deep-link? "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"))))
|
(is (links/deep-link? "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"))))
|
||||||
(testing "http://join.status.im/blah"
|
(testing "http://status.app/blah"
|
||||||
(testing "it returns true"
|
(testing "it returns true"
|
||||||
(is (links/universal-link? "http://join.status.im/blah"))))
|
(is (links/universal-link? "http://status.app/blah"))))
|
||||||
(testing "https://join.status.im/blah"
|
(testing "https://status.app/blah"
|
||||||
(testing "it returns true"
|
(testing "it returns true"
|
||||||
(is (links/universal-link? "https://join.status.im/blah"))))
|
(is (links/universal-link? "https://status.app/blah"))))
|
||||||
(testing "unicode characters"
|
(testing "unicode characters"
|
||||||
(testing "it returns false"
|
(testing "it returns false"
|
||||||
(is (not (links/universal-link? "https://join.status.im/browse/www.аррӏе.com")))))
|
(is (not (links/universal-link? "https://status.app/browse/www.аррӏе.com")))))
|
||||||
(testing "not-status-im://blah"
|
(testing "not-status-app://blah"
|
||||||
(testing "it returns false"
|
(testing "it returns false"
|
||||||
(is (not (links/universal-link? "https://not.status.im/blah")))))
|
(is (not (links/universal-link? "https://not.status.im/blah")))))
|
||||||
(testing "http://not.status.im/blah"
|
(testing "http://not.status.im/blah"
|
||||||
@ -31,6 +31,6 @@
|
|||||||
(testing "https://not.status.im/blah"
|
(testing "https://not.status.im/blah"
|
||||||
(testing "it returns false"
|
(testing "it returns false"
|
||||||
(is (not (links/universal-link? "https://not.status.im/blah")))))
|
(is (not (links/universal-link? "https://not.status.im/blah")))))
|
||||||
(testing "http://join.status.im/blah"
|
(testing "http://status.app/blah"
|
||||||
(testing "it returns false"
|
(testing "it returns false"
|
||||||
(is (not (links/deep-link? "http://join.status.im/blah"))))))
|
(is (not (links/deep-link? "http://status.app/blah"))))))
|
||||||
|
@ -178,9 +178,9 @@
|
|||||||
(def regx-bold #"\*[^*]+\*")
|
(def regx-bold #"\*[^*]+\*")
|
||||||
(def regx-italic #"~[^~]+~")
|
(def regx-italic #"~[^~]+~")
|
||||||
(def regx-backquote #"`[^`]+`")
|
(def regx-backquote #"`[^`]+`")
|
||||||
(def regx-universal-link #"((^https?://join.status.im/)|(^status-im://))[\x00-\x7F]+$")
|
(def regx-universal-link #"((^https?://status.app/)|(^status-app://))[\x00-\x7F]+$")
|
||||||
(def regx-community-universal-link #"((^https?://join.status.im/)|(^status-im://))c/([\x00-\x7F]+)$")
|
(def regx-community-universal-link #"((^https?://status.app/)|(^status-app://))c/([\x00-\x7F]+)$")
|
||||||
(def regx-deep-link #"((^ethereum:.*)|(^status-im://[\x00-\x7F]+$))")
|
(def regx-deep-link #"((^ethereum:.*)|(^status-app://[\x00-\x7F]+$))")
|
||||||
(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}")
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
(zipmap (repeat nil))))
|
(zipmap (repeat nil))))
|
||||||
([kv] (-> (init-contact) (merge kv))))
|
([kv] (-> (init-contact) (merge kv))))
|
||||||
|
|
||||||
(def url-regex #"^https?://join.status.im/u/(.+)")
|
(def url-regex #"^https?://status.app/u/(.+)")
|
||||||
|
|
||||||
(defn ->id
|
(defn ->id
|
||||||
[{:keys [input] :as contact}]
|
[{:keys [input] :as contact}]
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
(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://join.status.im/u/" ckey))
|
(def link-ckey (str "https://status.app/u/" ckey))
|
||||||
(def link-ens (str "https://join.status.im/u/" ens))
|
(def link-ens (str "https://status.app/u/" ens))
|
||||||
|
|
||||||
;;; unit tests (no app-db involved)
|
;;; unit tests (no app-db involved)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
(defn community-link
|
(defn community-link
|
||||||
[id]
|
[id]
|
||||||
(str "https://join.status.im/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]}
|
||||||
|
@ -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
|
||||||
join.status.im/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) (= "join.status.im/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 (= "join.status.im/u/zQ3sh...mrdYpzeFUa"
|
(is (= "status.app/u/zQ3sh...mrdYpzeFUa"
|
||||||
(utils.address/get-abbreviated-profile-url
|
(utils.address/get-abbreviated-profile-url
|
||||||
"join.status.im/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 "join.status.im/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 "join.status.im/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
|
||||||
"join.status.im/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 "join.status.im/u/" "abc")))
|
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u/" "abc")))
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "join.status.im/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://join.status.im/u/")
|
(def ^:const status-profile-base-url "https://status.app/u/")
|
||||||
(def ^:const status-profile-base-url-without-https "join.status.im/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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user