feat: add encoded data for profile sharing url (#18019)
This commit is contained in:
parent
9c6584f91b
commit
72f518d70b
|
@ -8,7 +8,23 @@
|
||||||
(def ^:private ?customization-color
|
(def ^:private ?customization-color
|
||||||
[:or :string :keyword])
|
[:or :string :keyword])
|
||||||
|
|
||||||
|
(def ^:private ?public-key
|
||||||
|
[:re #"^0x04[0-9a-f]{128}$"])
|
||||||
|
|
||||||
|
(def ^:private ?rpc-call
|
||||||
|
[:sequential
|
||||||
|
{:min 1}
|
||||||
|
[:map
|
||||||
|
{:closed true}
|
||||||
|
[:method :string]
|
||||||
|
[:params [:sequential :any]]
|
||||||
|
[:js-response {:optional true} :any]
|
||||||
|
[:on-success [:or fn? [:cat keyword? [:* :any]]]]
|
||||||
|
[:on-error [:or fn? [:cat keyword? [:* :any]]]]]])
|
||||||
|
|
||||||
(defn register-schemas
|
(defn register-schemas
|
||||||
[]
|
[]
|
||||||
(registry/register ::theme ?theme)
|
(registry/register ::theme ?theme)
|
||||||
(registry/register ::customization-color ?customization-color))
|
(registry/register ::customization-color ?customization-color)
|
||||||
|
(registry/register ::public-key ?public-key)
|
||||||
|
(registry/register ::rpc-call ?rpc-call))
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
(ns schema.re-frame
|
||||||
|
(:require
|
||||||
|
[schema.registry :as registry]))
|
||||||
|
|
||||||
|
(def ^:private ?cofx
|
||||||
|
[:map])
|
||||||
|
|
||||||
|
(defn register-schemas
|
||||||
|
[]
|
||||||
|
(registry/register ::cofx ?cofx))
|
|
@ -3,10 +3,8 @@
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]))
|
||||||
[utils.universal-links :as universal-links]))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:copy-to-clipboard
|
:copy-to-clipboard
|
||||||
|
@ -37,12 +35,6 @@
|
||||||
100)]
|
100)]
|
||||||
(swap! tooltips assoc tooltip-id {:opacity 1.0 :interval-id interval-id :cnt 0}))))))
|
(swap! tooltips assoc tooltip-id {:opacity 1.0 :interval-id interval-id :cnt 0}))))))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
|
||||||
:profile/share-profile-link
|
|
||||||
(fn [contact-code]
|
|
||||||
(let [link (universal-links/generate-link :user :external contact-code)]
|
|
||||||
(list-selection/open-share {:message link}))))
|
|
||||||
|
|
||||||
(rf/defn finish-success
|
(rf/defn finish-success
|
||||||
{:events [:my-profile/finish-success]}
|
{:events [:my-profile/finish-success]}
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
|
@ -81,11 +73,6 @@
|
||||||
[_ tooltip-id]
|
[_ tooltip-id]
|
||||||
{:show-tooltip tooltip-id})
|
{:show-tooltip tooltip-id})
|
||||||
|
|
||||||
(rf/defn share-profile-link
|
|
||||||
{:events [:profile/share-profile-link]}
|
|
||||||
[_ value]
|
|
||||||
{:profile/share-profile-link value})
|
|
||||||
|
|
||||||
(rf/defn show-profile
|
(rf/defn show-profile
|
||||||
{:events [:chat.ui/show-profile]}
|
{:events [:chat.ui/show-profile]}
|
||||||
[{:keys [db]} identity ens-name]
|
[{:keys [db]} identity ens-name]
|
||||||
|
|
|
@ -3,21 +3,16 @@
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]))
|
||||||
[utils.universal-links :as universal-links]))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
::share
|
::share
|
||||||
(fn [content]
|
(fn [content]
|
||||||
(.share ^js react/sharing (clj->js content))))
|
(.share ^js react/sharing (clj->js content))))
|
||||||
|
|
||||||
(rf/defn share-link
|
(rf/reg-event-fx
|
||||||
{:events [:invite.events/share-link]}
|
:invite.events/share-link
|
||||||
[{:keys [db]}]
|
(fn [{:keys [db]}]
|
||||||
(let [{:keys [public-key preferred-name]} (get db :profile/profile)
|
(let [{:keys [universal-profile-url]} (get db :profile/profile)
|
||||||
profile-link (universal-links/generate-link :user
|
message (i18n/label :t/join-me {:url universal-profile-url})]
|
||||||
:external
|
{::share {:message message}})))
|
||||||
(or preferred-name
|
|
||||||
public-key))
|
|
||||||
message (i18n/label :t/join-me {:url profile-link})]
|
|
||||||
{::share {:message message}}))
|
|
||||||
|
|
|
@ -21,55 +21,54 @@
|
||||||
[status-im2.config :as config]
|
[status-im2.config :as config]
|
||||||
[status-im2.contexts.profile.utils :as profile.utils]
|
[status-im2.contexts.profile.utils :as profile.utils]
|
||||||
[utils.ens.stateofus :as stateofus]
|
[utils.ens.stateofus :as stateofus]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n])
|
||||||
[utils.universal-links :as universal-links])
|
|
||||||
(:require-macros [status-im.utils.views :as views]))
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
|
|
||||||
(views/defview share-chat-key
|
(views/defview share-chat-key
|
||||||
[]
|
[]
|
||||||
(views/letsubs [{:keys [address ens-name]} [:popover/popover]
|
(views/letsubs [{:keys [address ens-name]} [:popover/popover]
|
||||||
width (reagent/atom nil)]
|
{:keys [universal-profile-url]} [:profile/profile]
|
||||||
(let [link (universal-links/generate-link :user :external (or ens-name address))]
|
width (reagent/atom nil)]
|
||||||
[react/view {:on-layout #(reset! width (-> ^js % .-nativeEvent .-layout .-width))}
|
[react/view {:on-layout #(reset! width (-> ^js % .-nativeEvent .-layout .-width))}
|
||||||
[react/view {:style {:padding-top 16 :padding-horizontal 16}}
|
[react/view {:style {:padding-top 16 :padding-horizontal 16}}
|
||||||
(when @width
|
(when @width
|
||||||
[qr-codes/qr-code
|
[qr-codes/qr-code
|
||||||
{:url address
|
{:url address
|
||||||
:size (- @width 32)}])
|
:size (- @width 32)}])
|
||||||
(when ens-name
|
(when ens-name
|
||||||
[react/view
|
[react/view
|
||||||
[copyable-text/copyable-text-view
|
[copyable-text/copyable-text-view
|
||||||
{:label :t/ens-username
|
{:label :t/ens-username
|
||||||
:container-style {:margin-top 12 :margin-bottom 4}
|
:container-style {:margin-top 12 :margin-bottom 4}
|
||||||
:copied-text ens-name}
|
:copied-text ens-name}
|
||||||
[quo/text
|
[quo/text
|
||||||
{:monospace true
|
{:monospace true
|
||||||
:accessibility-label :ens-username}
|
:accessibility-label :ens-username}
|
||||||
ens-name]]
|
ens-name]]
|
||||||
[react/view
|
[react/view
|
||||||
{:height 1
|
{:height 1
|
||||||
:margin-top 12
|
:margin-top 12
|
||||||
:margin-horizontal -16
|
:margin-horizontal -16
|
||||||
:background-color colors/gray-lighter}]])
|
:background-color colors/gray-lighter}]])
|
||||||
[copyable-text/copyable-text-view
|
[copyable-text/copyable-text-view
|
||||||
{:label :t/chat-key
|
{:label :t/chat-key
|
||||||
:container-style {:margin-top 12 :margin-bottom 4}
|
:container-style {:margin-top 12 :margin-bottom 4}
|
||||||
:copied-text address}
|
:copied-text address}
|
||||||
[quo/text
|
[quo/text
|
||||||
{:number-of-lines 1
|
{:number-of-lines 1
|
||||||
:ellipsize-mode :middle
|
:ellipsize-mode :middle
|
||||||
:accessibility-label :chat-key
|
:accessibility-label :chat-key
|
||||||
:monospace true}
|
:monospace true}
|
||||||
address]]]
|
address]]]
|
||||||
[react/view styles/share-link-button
|
[react/view styles/share-link-button
|
||||||
[quo/button
|
[quo/button
|
||||||
{:on-press (fn []
|
{:on-press (fn []
|
||||||
(re-frame/dispatch [:hide-popover])
|
(re-frame/dispatch [:hide-popover])
|
||||||
(js/setTimeout
|
(js/setTimeout
|
||||||
#(list-selection/open-share {:message link})
|
#(list-selection/open-share {:message universal-profile-url})
|
||||||
250))
|
250))
|
||||||
:accessibility-label :share-my-contact-code-button}
|
:accessibility-label :share-my-contact-code-button}
|
||||||
(i18n/label :t/share-link)]]])))
|
(i18n/label :t/share-link)]]]))
|
||||||
|
|
||||||
(defn content
|
(defn content
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[react-native.async-storage :as async-storage]
|
[react-native.async-storage :as async-storage]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[schema.core :as schema]
|
||||||
[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]
|
||||||
|
@ -16,14 +17,6 @@
|
||||||
{:external "https://status.app"
|
{:external "https://status.app"
|
||||||
:internal "status-app:/"})
|
:internal "status-app:/"})
|
||||||
|
|
||||||
(def links
|
|
||||||
{:private-chat "%s/p/%s"
|
|
||||||
:community-requests "%s/cr/%s"
|
|
||||||
:community "%s/c#%s"
|
|
||||||
:group-chat "%s/g/%s"
|
|
||||||
:user "%s/u#%s"
|
|
||||||
:browse "%s/b/%s"})
|
|
||||||
|
|
||||||
(rf/defn handle-browse
|
(rf/defn handle-browse
|
||||||
[_ {:keys [url]}]
|
[_ {:keys [url]}]
|
||||||
(log/info "universal-links: handling browse" url)
|
(log/info "universal-links: handling browse" url)
|
||||||
|
@ -183,6 +176,61 @@
|
||||||
{:db (dissoc db :universal-links/url)}
|
{:db (dissoc db :universal-links/url)}
|
||||||
(handle-url url))))
|
(handle-url url))))
|
||||||
|
|
||||||
|
(defn generate-profile-url
|
||||||
|
([cofx] (generate-profile-url cofx nil))
|
||||||
|
([{:keys [db]} [{:keys [public-key cb]}]]
|
||||||
|
(let [profile-public-key (get-in db [:profile/profile :public-key])
|
||||||
|
profile? (or (not public-key) (= public-key profile-public-key))
|
||||||
|
ens-name? (if profile?
|
||||||
|
(get-in db [:profile/profile :ens-name?])
|
||||||
|
(get-in db [:contacts/contacts public-key :ens-name]))
|
||||||
|
public-key (if profile? profile-public-key public-key)]
|
||||||
|
(when public-key
|
||||||
|
{:json-rpc/call
|
||||||
|
[{:method (if ens-name? "wakuext_shareUserURLWithENS" "wakuext_shareUserURLWithData")
|
||||||
|
:params [public-key]
|
||||||
|
:on-success (fn [url]
|
||||||
|
(rf/dispatch [:universal-links/save-profile-url public-key url])
|
||||||
|
(when (fn? cb) (cb)))
|
||||||
|
:on-error #(log/error "failed to wakuext_shareUserURLWithData"
|
||||||
|
{:error %
|
||||||
|
:public-key public-key})}]}))))
|
||||||
|
|
||||||
|
(schema/=> generate-profile-url
|
||||||
|
[:=>
|
||||||
|
[:catn
|
||||||
|
[:cofx :schema.re-frame/cofx]
|
||||||
|
[:args
|
||||||
|
[:schema
|
||||||
|
[:?
|
||||||
|
[:map
|
||||||
|
[:public-key {:optional true} :schema.common/public-key]
|
||||||
|
[:cb {:optional true} fn?]]]]]]
|
||||||
|
[:map
|
||||||
|
[:json-rpc/call :schema.common/rpc-call]]])
|
||||||
|
|
||||||
|
(rf/reg-event-fx :universal-links/generate-profile-url generate-profile-url)
|
||||||
|
|
||||||
|
(defn save-profile-url
|
||||||
|
[{:keys [db]} [public-key url]]
|
||||||
|
(when url
|
||||||
|
{:db
|
||||||
|
(cond-> db
|
||||||
|
(get-in db [:contacts/contacts public-key])
|
||||||
|
(assoc-in [:contacts/contacts public-key :universal-profile-url] url)
|
||||||
|
(= public-key (get-in db [:profile/profile :public-key]))
|
||||||
|
(assoc-in [:profile/profile :universal-profile-url] url))}))
|
||||||
|
|
||||||
|
(schema/=> save-profile-url
|
||||||
|
[:=>
|
||||||
|
[:catn
|
||||||
|
[:cofx :schema.re-frame/cofx]
|
||||||
|
[:args
|
||||||
|
[:schema [:cat :schema.common/public-key :string]]]]
|
||||||
|
[:maybe :map]])
|
||||||
|
|
||||||
|
(rf/reg-event-fx :universal-links/save-profile-url save-profile-url)
|
||||||
|
|
||||||
(defn unwrap-js-url
|
(defn unwrap-js-url
|
||||||
[e]
|
[e]
|
||||||
(-> e
|
(-> e
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns status-im2.common.universal-links-test
|
(ns status-im2.common.universal-links-test
|
||||||
(:require
|
(:require
|
||||||
[cljs.test :refer-macros [deftest is testing]]
|
[cljs.test :refer-macros [deftest is are testing]]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im2.common.universal-links :as links]))
|
[status-im2.common.universal-links :as links]))
|
||||||
|
|
||||||
|
@ -34,3 +34,67 @@
|
||||||
(with-redefs [re-frame/dispatch #(reset! actual %)]
|
(with-redefs [re-frame/dispatch #(reset! actual %)]
|
||||||
(links/url-event-listener #js {})
|
(links/url-event-listener #js {})
|
||||||
(is (= nil @actual)))))))
|
(is (= nil @actual)))))))
|
||||||
|
|
||||||
|
(deftest generate-profile-url
|
||||||
|
(testing "user has ens name"
|
||||||
|
(testing "it calls the ens rpc method with ens name as param"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
db {:profile/profile {:ens-name? true :public-key pubkey}}
|
||||||
|
rst (links/generate-profile-url {:db db})]
|
||||||
|
(are [result expected] (= result expected)
|
||||||
|
"wakuext_shareUserURLWithENS" (-> rst :json-rpc/call first :method)
|
||||||
|
pubkey (-> rst :json-rpc/call first :params first)))))
|
||||||
|
(testing "user has no ens name"
|
||||||
|
(testing "it calls the ens rpc method with public keyas param"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
db {:profile/profile {:public-key pubkey}}
|
||||||
|
rst (links/generate-profile-url {:db db})]
|
||||||
|
(are [result expected] (= result expected)
|
||||||
|
"wakuext_shareUserURLWithData" (-> rst :json-rpc/call first :method)
|
||||||
|
pubkey (-> rst :json-rpc/call first :params first)))))
|
||||||
|
(testing "contact has ens name"
|
||||||
|
(testing "it calls the ens rpc method with ens name as param"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
ens "ensname.eth"
|
||||||
|
db {:contacts/contacts {pubkey {:ens-name ens}}}
|
||||||
|
rst (links/generate-profile-url {:db db} [{:public-key pubkey}])]
|
||||||
|
(are [result expected] (= result expected)
|
||||||
|
"wakuext_shareUserURLWithENS" (-> rst :json-rpc/call first :method)
|
||||||
|
pubkey (-> rst :json-rpc/call first :params first)))))
|
||||||
|
(testing "contact has no ens name"
|
||||||
|
(testing "it calls the ens rpc method with public keyas param"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
db {:contacts/contacts {pubkey {:public-key pubkey}}}
|
||||||
|
rst (links/generate-profile-url {:db db} [{:public-key pubkey}])]
|
||||||
|
(are [result expected] (= result expected)
|
||||||
|
"wakuext_shareUserURLWithData" (-> rst :json-rpc/call first :method)
|
||||||
|
pubkey (-> rst :json-rpc/call first :params first))))))
|
||||||
|
|
||||||
|
(deftest save-profile-url
|
||||||
|
(testing "given a contact public key and profile url"
|
||||||
|
(testing "it updates the contact in db"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
url "url"
|
||||||
|
db {:contacts/contacts {pubkey {:public-key pubkey}}}
|
||||||
|
rst (links/save-profile-url {:db db} [pubkey url])]
|
||||||
|
(is (= (get-in rst [:db :contacts/contacts pubkey :universal-profile-url]) url)))))
|
||||||
|
(testing "given a user public key and profile url"
|
||||||
|
(testing "it updates the user profile in db"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
url "url"
|
||||||
|
db {:profile/profile {:public-key pubkey}}
|
||||||
|
rst (links/save-profile-url {:db db} [pubkey url])]
|
||||||
|
(is (= (get-in rst [:db :profile/profile :universal-profile-url]) url)))))
|
||||||
|
(testing "given a invalid url"
|
||||||
|
(testing "it returns the db untouched"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
url "url"
|
||||||
|
db {:profile/profile {:public-key pubkey}}
|
||||||
|
rst (links/save-profile-url {:db db} ["invalid pubkey" url])]
|
||||||
|
(is (= (:db rst) db)))))
|
||||||
|
(testing "given a nil as url"
|
||||||
|
(testing "it returns nil"
|
||||||
|
(let [pubkey "pubkey"
|
||||||
|
db {:profile/profile {:public-key pubkey}}
|
||||||
|
rst (links/save-profile-url {:db db} ["invalid pubkey"])]
|
||||||
|
(is (nil? rst))))))
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
[status-im2.contexts.profile.settings.events :as profile.settings.events]
|
[status-im2.contexts.profile.settings.events :as profile.settings.events]
|
||||||
[status-im2.contexts.push-notifications.events :as notifications]
|
[status-im2.contexts.push-notifications.events :as notifications]
|
||||||
[status-im2.contexts.shell.activity-center.events :as activity-center]
|
[status-im2.contexts.shell.activity-center.events :as activity-center]
|
||||||
[status-im2.contexts.wallet.events :as wallet]
|
|
||||||
[status-im2.navigation.events :as navigation]
|
[status-im2.navigation.events :as navigation]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
|
@ -85,7 +84,9 @@
|
||||||
:networks/current-network current-network
|
:networks/current-network current-network
|
||||||
:networks/networks (merge networks config/default-networks-by-id)
|
:networks/networks (merge networks config/default-networks-by-id)
|
||||||
:profile/profile (merge profile-overview settings))
|
:profile/profile (merge profile-overview settings))
|
||||||
(assoc-in [:wallet :ui :tokens-loading?] true))}
|
(assoc-in [:wallet :ui :tokens-loading?] true))
|
||||||
|
:fx [[:dispatch [:wallet/get-ethereum-chains]]
|
||||||
|
[:dispatch [:universal-links/generate-profile-url]]]}
|
||||||
(notifications/load-preferences)
|
(notifications/load-preferences)
|
||||||
(data-store.chats/fetch-chats-preview
|
(data-store.chats/fetch-chats-preview
|
||||||
{:on-success
|
{:on-success
|
||||||
|
@ -100,7 +101,6 @@
|
||||||
(activity-center/notifications-fetch-pending-contact-requests)
|
(activity-center/notifications-fetch-pending-contact-requests)
|
||||||
(activity-center/update-seen-state)
|
(activity-center/update-seen-state)
|
||||||
(activity-center/notifications-fetch-unread-count)
|
(activity-center/notifications-fetch-unread-count)
|
||||||
(wallet/get-ethereum-chains)
|
|
||||||
(redirect-to-root))))
|
(redirect-to-root))))
|
||||||
|
|
||||||
;; login phase 2, we want to load and show chats faster so we split login into 2 phases
|
;; login phase 2, we want to load and show chats faster so we split login into 2 phases
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
(str (name network) ":")))
|
(str (name network) ":")))
|
||||||
|
|
||||||
(def ^:private profile-link
|
(def ^:private profile-link
|
||||||
"https://status.app/u#zQ34e1zlOdas0pKnvrweeedsasas12adjie8")
|
"https://status.app/u/CwWACgkKB0VlZWVlZWUD#zQ3shUeRSwU6rnUk5JfK2k5HRiM5Hy3wU3UZQrKVzopmAHcQv")
|
||||||
|
|
||||||
(def ^:private wallet-address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2")
|
(def ^:private wallet-address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd2")
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
[status-im2.contexts.shell.share.style :as style]
|
[status-im2.contexts.shell.share.style :as style]
|
||||||
[utils.address :as address]
|
[utils.address :as address]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.image-server :as image-server]
|
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn header
|
(defn header
|
||||||
|
@ -47,27 +46,25 @@
|
||||||
(defn profile-tab
|
(defn profile-tab
|
||||||
[]
|
[]
|
||||||
(let [{:keys [emoji-hash
|
(let [{:keys [emoji-hash
|
||||||
compressed-key
|
customization-color
|
||||||
customization-color]
|
universal-profile-url]
|
||||||
:as profile} (rf/sub [:profile/profile])
|
:as profile} (rf/sub [:profile/profile])
|
||||||
profile-url (str image-server/status-profile-base-url compressed-key)
|
|
||||||
abbreviated-url (address/get-abbreviated-profile-url
|
abbreviated-url (address/get-abbreviated-profile-url
|
||||||
image-server/status-profile-base-url-without-https
|
universal-profile-url)
|
||||||
compressed-key)
|
|
||||||
emoji-hash-string (string/join emoji-hash)]
|
emoji-hash-string (string/join emoji-hash)]
|
||||||
[:<>
|
[:<>
|
||||||
[rn/view {:style style/qr-code-container}
|
[rn/view {:style style/qr-code-container}
|
||||||
[qr-codes/share-qr-code
|
[qr-codes/share-qr-code
|
||||||
{:type :profile
|
{:type :profile
|
||||||
:unblur-on-android? true
|
:unblur-on-android? true
|
||||||
:qr-data profile-url
|
:qr-data universal-profile-url
|
||||||
:qr-data-label-shown abbreviated-url
|
:qr-data-label-shown abbreviated-url
|
||||||
:on-share-press #(list-selection/open-share {:message profile-url})
|
:on-share-press #(list-selection/open-share {:message universal-profile-url})
|
||||||
:on-text-press #(rf/dispatch [:share/copy-text-and-show-toast
|
:on-text-press #(rf/dispatch [:share/copy-text-and-show-toast
|
||||||
{:text-to-copy profile-url
|
{:text-to-copy universal-profile-url
|
||||||
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
|
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
|
||||||
:on-text-long-press #(rf/dispatch [:share/copy-text-and-show-toast
|
:on-text-long-press #(rf/dispatch [:share/copy-text-and-show-toast
|
||||||
{:text-to-copy profile-url
|
{:text-to-copy universal-profile-url
|
||||||
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
|
:post-copy-message (i18n/label :t/link-to-profile-copied)}])
|
||||||
:profile-picture (:uri (profile.utils/photo profile))
|
:profile-picture (:uri (profile.utils/photo profile))
|
||||||
:full-name (profile.utils/displayed-name profile)
|
:full-name (profile.utils/displayed-name profile)
|
||||||
|
|
|
@ -190,14 +190,14 @@
|
||||||
(first derived-address-details)]))]
|
(first derived-address-details)]))]
|
||||||
{:fx [[:dispatch [:wallet/create-derived-addresses account-details on-success]]]})))
|
{:fx [[:dispatch [:wallet/create-derived-addresses account-details on-success]]]})))
|
||||||
|
|
||||||
(rf/defn get-ethereum-chains
|
(rf/reg-event-fx
|
||||||
{:events [:wallet/get-ethereum-chains]}
|
:wallet/get-ethereum-chains
|
||||||
[{:keys [db]}]
|
(fn [_]
|
||||||
{:fx [[:json-rpc/call
|
{:json-rpc/call
|
||||||
[{:method "wallet_getEthereumChains"
|
[{:method "wallet_getEthereumChains"
|
||||||
:params []
|
:params []
|
||||||
:on-success [:wallet/get-ethereum-chains-success]
|
:on-success [:wallet/get-ethereum-chains-success]
|
||||||
:on-error #(log/info "failed to get networks " %)}]]]})
|
:on-error #(log/info "failed to get networks " %)}]}))
|
||||||
|
|
||||||
(rf/reg-event-fx
|
(rf/reg-event-fx
|
||||||
:wallet/get-ethereum-chains-success
|
:wallet/get-ethereum-chains-success
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
malli.util
|
malli.util
|
||||||
schema.common
|
schema.common
|
||||||
[schema.core :as schema]
|
[schema.core :as schema]
|
||||||
|
schema.re-frame
|
||||||
schema.registry
|
schema.registry
|
||||||
[taoensso.timbre :as log]))
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
@ -76,7 +77,8 @@
|
||||||
`:schema.common/theme`."
|
`:schema.common/theme`."
|
||||||
[]
|
[]
|
||||||
(schema.registry/merge (malli.util/schemas))
|
(schema.registry/merge (malli.util/schemas))
|
||||||
(schema.common/register-schemas))
|
(schema.common/register-schemas)
|
||||||
|
(schema.re-frame/register-schemas))
|
||||||
|
|
||||||
(defn setup!
|
(defn setup!
|
||||||
"Configure Malli and initializes instrumentation.
|
"Configure Malli and initializes instrumentation.
|
||||||
|
|
|
@ -42,22 +42,22 @@
|
||||||
(get-shortened-key (eip55/address->checksum (normalized-hex address)))))
|
(get-shortened-key (eip55/address->checksum (normalized-hex address)))))
|
||||||
|
|
||||||
(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
|
||||||
status.app/u# joined with the 1st 5 characters
|
with the 1st 5 characters of the encoded data followed by an ellipsis
|
||||||
of the compressed public key followed by an ellipsis followed by
|
followed by the last 10 characters of the compressed public key"
|
||||||
the last 10 characters of the compressed public key"
|
[universal-profile-url]
|
||||||
[base-url public-key]
|
(when-let [re-find-result (re-find #"^https://(status.app/u/)(.*)#(.*)$" universal-profile-url)]
|
||||||
(if (and public-key base-url (> (count public-key) 17) (= "status.app/u#" base-url))
|
(let [[_whole-url base-url encoded-data public-key] re-find-result]
|
||||||
(let [first-part-of-public-pk (subs public-key 0 5)
|
(when (> (count public-key) 9)
|
||||||
ellipsis "..."
|
(let [first-part-of-encoded-data (subs encoded-data 0 5)
|
||||||
public-key-size (count public-key)
|
ellipsis "..."
|
||||||
last-part-of-public-key (subs public-key (- public-key-size 10) public-key-size)
|
public-key-size (count public-key)
|
||||||
abbreviated-url (str base-url
|
last-part-of-public-key (subs public-key (- public-key-size 10) public-key-size)
|
||||||
first-part-of-public-pk
|
abbreviated-url (str base-url
|
||||||
ellipsis
|
first-part-of-encoded-data
|
||||||
last-part-of-public-key)]
|
ellipsis
|
||||||
abbreviated-url)
|
last-part-of-public-key)]
|
||||||
nil))
|
abbreviated-url)))))
|
||||||
|
|
||||||
(defn get-shortened-compressed-key
|
(defn get-shortened-compressed-key
|
||||||
"The goal here is to generate a string that begins with 1st 3
|
"The goal here is to generate a string that begins with 1st 3
|
||||||
|
|
|
@ -22,22 +22,17 @@
|
||||||
|
|
||||||
(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/abcde...mrdYpzeFUa"
|
||||||
(utils.address/get-abbreviated-profile-url
|
(utils.address/get-abbreviated-profile-url
|
||||||
"status.app/u#"
|
"https://status.app/u/abcdefg#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/abcdefg")))
|
||||||
|
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u/abcdefg#"))))
|
||||||
(testing "Ensure the function returns nil when given a nil public key"
|
|
||||||
(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#"
|
"https://status.app/uwu/abcdefg#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 10 characters"
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u#" "abc")))
|
(is (nil? (utils.address/get-abbreviated-profile-url "https://status.app/u/abcdefg#012345678")))))
|
||||||
(is (nil? (utils.address/get-abbreviated-profile-url "status.app/u#" "1234")))))
|
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
(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-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
|
||||||
|
@ -264,30 +262,6 @@
|
||||||
:ring? (if (nil? override-ring?) ring? override-ring?)
|
:ring? (if (nil? override-ring?) ring? override-ring?)
|
||||||
:ring-width ring-width})))
|
:ring-width ring-width})))
|
||||||
|
|
||||||
(defn get-account-qr-image-uri
|
|
||||||
[{:keys [key-uid public-key port qr-size]}]
|
|
||||||
(let [profile-qr-url (str status-profile-base-url public-key)
|
|
||||||
base-64-qr-url (js/btoa profile-qr-url)
|
|
||||||
profile-image-type "large"
|
|
||||||
error-correction-level (correction-level->index :highest)
|
|
||||||
superimpose-profile? true
|
|
||||||
media-server-url (str image-server-uri-prefix
|
|
||||||
port
|
|
||||||
generate-qr-action
|
|
||||||
"?level="
|
|
||||||
error-correction-level
|
|
||||||
"&url="
|
|
||||||
base-64-qr-url
|
|
||||||
"&keyUid="
|
|
||||||
key-uid
|
|
||||||
"&allowProfileImage="
|
|
||||||
superimpose-profile?
|
|
||||||
"&size="
|
|
||||||
(* 2 qr-size)
|
|
||||||
"&imageName="
|
|
||||||
profile-image-type)]
|
|
||||||
media-server-url))
|
|
||||||
|
|
||||||
(defn get-qr-image-uri-for-any-url
|
(defn get-qr-image-uri-for-any-url
|
||||||
[{:keys [url port qr-size error-level]}]
|
[{:keys [url port qr-size error-level]}]
|
||||||
(let [qr-url-base64 (js/btoa url)
|
(let [qr-url-base64 (js/btoa url)
|
||||||
|
|
Loading…
Reference in New Issue