Add profile pictures

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Gheorghe Pinzaru 2020-11-30 14:11:06 +03:00 committed by Andrea Maria Piana
parent 09822e142b
commit 5643c4d537
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
45 changed files with 309 additions and 449 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

View File

@ -196,7 +196,7 @@
group-contacts))
:else users)
{:keys [name preferred-name public-key photo-path]}
{:keys [name preferred-name public-key]}
(:multiaccount db)]
(reduce
(fn [acc [key {:keys [alias name identicon]}]]
@ -210,7 +210,6 @@
public-key
{:alias name
:name (or preferred-name name)
:identicon photo-path
:public-key public-key})
contacts)))

View File

@ -4,8 +4,6 @@
[status-im.data-store.contacts :as contacts-store]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.mailserver.core :as mailserver]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.transport.filters.core :as transport.filters]
[status-im.tribute-to-talk.db :as tribute-to-talk]
[status-im.tribute-to-talk.whitelist :as whitelist]
@ -44,17 +42,11 @@
(defn- own-info
[db]
(let [{:keys [name preferred-name photo-path address]} (:multiaccount db)]
(let [{:keys [name preferred-name identicon address]} (:multiaccount db)]
{:name (or preferred-name name)
:profile-image photo-path
:profile-image identicon
:address address}))
(fx/defn handle-update-from-contact-request [{:keys [db] :as cofx} {:keys [last-updated photo-path]}]
(when (> last-updated (get-in db [:multiaccount :last-updated]))
(fx/merge cofx
(multiaccounts.update/multiaccount-update :last-updated last-updated {:dont-sync? true})
(multiaccounts.update/multiaccount-update :photo-path photo-path {:dont-sync? true}))))
(fx/defn ensure-contacts
[{:keys [db]} contacts]
{:db (update db :contacts/contacts
@ -126,37 +118,6 @@
{:db (dissoc db :contacts/new-identity)}
(upsert-contact contact)))))
(fx/defn handle-contact-update
[{{:contacts/keys [contacts] :as db} :db :as cofx}
public-key
timestamp
{:keys [name profile-image address] :as m}]
;; We need to convert to timestamp ms as before we were using now in ms to
;; set last updated
;; Using whisper timestamp mostly works but breaks in a few scenarios:
;; 2 updates sent in the same second
;; when using multi-device & clocks are out of sync
;; Using logical clocks is probably the correct way to handle it, but an overkill
;; for now
(let [timestamp-ms (* timestamp 1000)
prev-last-updated (get-in db [:contacts/contacts public-key :last-updated])
current-public-key (multiaccounts.model/current-public-key cofx)]
(when (and (not= current-public-key public-key)
(< prev-last-updated timestamp-ms))
(let [contact (get contacts public-key)
;; Backward compatibility with <= 0.9.21, as they don't send
;; address in contact updates
contact-props
(cond-> {:public-key public-key
:photo-path profile-image
:name name
:last-updated timestamp-ms
:system-tags (conj (get contact :system-tags #{})
:contact/request-received)}
address (assoc :address address))]
(upsert-contact cofx contact-props)))))
(fx/defn initialize-contacts [cofx]
(contacts-store/fetch-contacts-rpc cofx #(re-frame/dispatch [::contacts-loaded %])))

View File

@ -1,98 +1,2 @@
(ns status-im.contact.core-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.contact.core :as model]
[status-im.ethereum.json-rpc :as json-rpc]))
(ns status-im.contact.core-test)
(def public-key "0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917")
(deftest handle-contact-update-test
(with-redefs [json-rpc/call (constantly nil)]
(testing "the contact is not in contacts"
(let [actual (model/handle-contact-update
{:db {}}
public-key
1
{:name "name"
:profile-image "image"})
contact (get-in actual [:db :contacts/contacts public-key])]
(testing "it adds a new contact"
(is (= {:public-key public-key
:photo-path "image"
:name "name"
:last-updated 1000
:system-tags #{:contact/request-received}}
contact)))))
(testing "the contact is already in contacts"
(testing "timestamp is greater than last-updated"
(let [actual (model/handle-contact-update
{:db {:contacts/contacts
{public-key {:public-key public-key
:photo-path "old-image"
:name "old-name"
:last-updated 0
:system-tags #{:contact/added}}}}}
public-key
1
{:name "new-name"
:profile-image "new-image"})
contact (get-in actual [:db :contacts/contacts public-key])]
(testing "it updates the contact and adds contact/request-received to system tags"
(is (= {:public-key public-key
:photo-path "new-image"
:name "new-name"
:last-updated 1000
:system-tags #{:contact/added :contact/request-received}}
contact)))))
(testing "timestamp is equal to last-updated"
(let [actual (model/handle-contact-update
{:db {:contacts/contacts
{public-key {:public-key public-key
:photo-path "old-image"
:name "old-name"
:last-updated 1000
:system-tags #{:contact/added}}}}}
public-key
1
{:name "new-name"
:profile-image "new-image"})]
(testing "it does nothing"
(is (nil? actual)))))
(testing "timestamp is less than last-updated"
(let [actual (model/handle-contact-update
{:db {:contacts/contacts
{public-key {:public-key public-key
:photo-path "old-image"
:name "old-name"
:last-updated 1000
:system-tags #{:contact/added :contact/request-received}}}}}
public-key
0
{:name "new-name"
:profile-image "new-image"})]
(testing "it does nothing"
(is (nil? actual))))))
(testing "backward compatibility"
(let [actual (model/handle-contact-update
{:db {:contacts/contacts
{public-key {:public-key public-key
:photo-path "old-image"
:name "old-name"
:last-updated 0
:system-tags #{:contact/added}}}}}
public-key
1
{:name "new-name"
:profile-image "new-image"})
contact (get-in actual [:db :contacts/contacts public-key])]
(testing "it updates the contact"
(is (= {:public-key public-key
:photo-path "new-image"
:name "new-name"
:last-updated 1000
:system-tags #{:contact/added :contact/request-received}} contact)))))
(testing "the message is coming from us"
(testing "it does not update contacts"
(is (nil? (model/handle-contact-update {:db {:multiaccount {:public-key "me"}}} "me" 1 {})))))))

View File

@ -20,8 +20,8 @@
(get contacts public-key
(public-key->new-contact public-key))))
(defn- contact-by-address [[_ contact] address]
(when (ethereum/address= (:address contact) address)
(defn- contact-by-address [[addr contact] address]
(when (ethereum/address= addr address)
contact))
(defn find-contact-by-address [contacts address]
@ -54,7 +54,7 @@
[members admins contacts {:keys [public-key] :as current-account}]
(let [current-contact (some->
current-account
(select-keys [:name :preferred-name :public-key :photo-path])
(select-keys [:name :preferred-name :public-key :identicon])
(clojure.set/rename-keys {:name :alias
:preferred-name :name}))
all-contacts (cond-> contacts

View File

@ -13,21 +13,21 @@
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}
admins #{"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"}
contacts {"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
{:last-updated 0,
:name "User B",
:photo-path "photo1",
:last-online 0,
:public-key
"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
:system-tags #{}}}
current-multiaccount {:last-updated 0,
:signed-up? true,
:sharing-usage-data? false,
:name "User A",
:photo-path "photo2",
contacts {"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
{:last-updated 0,
:name "User B",
:identicon "photo1",
:last-online 0,
:public-key
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}]
"0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
:system-tags #{}}}
current-multiaccount {:last-updated 0,
:signed-up? true,
:sharing-usage-data? false,
:name "User A",
:identicon "photo2",
:public-key
"0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}]
(is (= (contact.db/get-all-contacts-in-group-chat chat-contact-ids
admins
contacts
@ -39,11 +39,11 @@
:public-key "0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917"
:system-tags #{}}
{:alias "User A"
:photo-path "photo2"
:identicon "photo2"
:public-key "0x048a2f8b80c60f89a91b4c1316e56f75b087f446e7b8701ceca06a40142d8efe1f5aa36bd0fee9e248060a8d5207b43ae98bef4617c18c71e66f920f324869c09f"}
{:last-updated 0
:name "User B"
:photo-path "photo1"
:identicon "photo1"
:last-online 0
:public-key "0x04985040682b77a32bb4bb58268a0719bd24ca4d07c255153fe1eb2ccd5883669627bd1a092d7cc76e8e4b9104327667b19dcda3ac469f572efabe588c38c1985f"
:system-tags #{}}]))))))

View File

@ -19,7 +19,6 @@
#{}
%))
(clojure.set/rename-keys {:id :public-key
:photoPath :photo-path
:tributeToTalk :tribute-to-talk
:ensVerifiedAt :ens-verified-at
:ensVerified :ens-verified
@ -38,7 +37,6 @@
:ens-verified-at :ensVerifiedAt
:last-ens-clock-value :lastENSClockValue
:ens-verification-retries :ensVerificationRetries
:photo-path :photoPath
:tribute-to-talk :tributeToTalk
:system-tags :systemTags
:last-updated :lastUpdated

View File

@ -6,14 +6,14 @@
(let [contact {:public-key "pk"
:address "address"
:name "name"
:photo-path "photo-path"
:identicon "identicon"
:tribute-to-talk "tribute-to-talk"
:last-updated 1
:system-tags #{:a :b}}
expected-contact {:id "pk"
:address "address"
:name "name"
:photoPath "photo-path"
:identicon "identicon"
:tributeToTalk "\"tribute-to-talk\""
:lastUpdated 1
@ -28,14 +28,14 @@
(let [contact {:id "pk"
:address "address"
:name "name"
:photoPath "photo-path"
:identicon "identicon"
:tributeToTalk "\"tribute-to-talk\""
:lastUpdated 1
:systemTags [":a" ":b"]}
expected-contact {:public-key "pk"
:address "address"
:name "name"
:photo-path "photo-path"
:identicon "identicon"
:tribute-to-talk "tribute-to-talk"
:last-updated 1

View File

@ -111,6 +111,10 @@
"wakuext_getPushNotificationsServers" {}
"wakuext_enablePushNotificationsBlockMentions" {}
"wakuext_disablePushNotificationsBlockMentions" {}
"multiaccounts_getIdentityImages" {}
"multiaccounts_getIdentityImage" {}
"multiaccounts_storeIdentityImage" {}
"multiaccounts_deleteIdentityImage" {}
"status_chats" {}
"localnotifications_switchWalletNotifications" {}
"localnotifications_notificationPreferences" {}

View File

@ -139,14 +139,13 @@
(handlers/register-handler-fx
:multiaccounts.login.ui/multiaccount-selected
(fn [{:keys [db] :as cofx} [_ key-uid]]
(let [{:keys [photo-path name public-key]}
(get-in db [:multiaccounts/multiaccounts key-uid])]
(let [multiaccount (get-in db [:multiaccounts/multiaccounts key-uid])]
(fx/merge
cofx
{:db (-> db
(dissoc :intro-wizard)
(update :keycard dissoc :application-info))}
(multiaccounts.login/open-login key-uid photo-path name public-key)))))
(multiaccounts.login/open-login multiaccount)))))
(handlers/register-handler-fx
:login/filters-initialized

View File

@ -27,9 +27,8 @@
[cofx {:keys [logout?]}]
(let [{{:multiaccounts/keys [multiaccounts]} :db} cofx]
(when (and (seq multiaccounts) (not logout?))
(let [{:keys [key-uid public-key photo-path name]}
(first (sort-by :timestamp > (vals multiaccounts)))]
(multiaccounts.login/open-login cofx key-uid photo-path name public-key)))))
(let [multiaccount (first (sort-by :timestamp > (vals multiaccounts)))]
(multiaccounts.login/open-login cofx multiaccount)))))
(fx/defn initialize-multiaccounts
{:events [::initialize-multiaccounts]}

View File

@ -311,11 +311,11 @@
[{:keys [db] :as cofx} data]
(let [{:keys [key-uid encryption-public-key whisper-private-key]
:as account-data} (js->clj data :keywordize-keys true)
{:keys [photo-path name]} (get-in db [:multiaccounts/multiaccounts key-uid])
{:keys [identicon name]} (get-in db [:multiaccounts/multiaccounts key-uid])
key-uid (get-in db [:keycard :application-info :key-uid])
multiaccount-data (types/clj->json {:name name
:key-uid key-uid
:photo-path photo-path})
:identicon identicon})
save-keys? (get-in db [:multiaccounts/login :save-password?])]
(fx/merge cofx
{:db
@ -328,7 +328,7 @@
(update :multiaccounts/login assoc
:password encryption-public-key
:key-uid key-uid
:photo-path photo-path
:identicon identicon
:name name))
:keycard/get-application-info {:pairing (get-pairing db key-uid)}

View File

@ -145,13 +145,13 @@
[{:keys [db] :as cofx} key-uid [encryption-public-key whisper-private-key :as creds]]
(if (nil? creds)
(navigation/navigate-to-cofx cofx :keycard-login-pin nil)
(let [{:keys [photo-path name]} (get-in db [:multiaccounts/multiaccounts key-uid])
multiaccount-data (types/clj->json {:name name
:key-uid key-uid
:photo-path photo-path})
account-data {:key-uid key-uid
:encryption-public-key encryption-public-key
:whisper-private-key whisper-private-key}]
(let [{:keys [identicon name]} (get-in db [:multiaccounts/multiaccounts key-uid])
multiaccount-data (types/clj->json {:name name
:key-uid key-uid
:identicon identicon})
account-data {:key-uid key-uid
:encryption-public-key encryption-public-key
:whisper-private-key whisper-private-key}]
{:db
(-> db
(assoc-in [:keycard :pin :status] nil)
@ -162,7 +162,7 @@
(update :multiaccounts/login assoc
:password encryption-public-key
:key-uid key-uid
:photo-path photo-path
:identicon identicon
:name name
:save-password? true))
:keycard/login-with-keycard

View File

@ -137,7 +137,7 @@
(let [{{:keys [multiaccount secrets flow]} :keycard} db
{:keys [address
name
photo-path
identicon
public-key
whisper-public-key
wallet-public-key
@ -149,14 +149,14 @@
encryption-public-key
instance-uid
key-uid
recovered]} multiaccount
{:keys [pairing paired-on]} secrets
{:keys [name photo-path]}
recovered]} multiaccount
{:keys [pairing paired-on]} secrets
{:keys [name identicon]}
(if (nil? name)
;; name might have been generated during recovery via passphrase
(get-in db [:intro-wizard :derived constants/path-whisper-keyword])
{:name name
:photo-path photo-path})]
:identicon identicon})]
;; if a name is still `nil` we have to generate it before multiaccount's
;; creation otherwise spec validation will fail
(if (nil? name)
@ -176,7 +176,7 @@
{:public-key whisper-public-key
:address (eip55/address->checksum whisper-address)
:name name
:photo-path photo-path}
:identicon identicon}
constants/path-default-wallet-keyword
{:public-key wallet-public-key
:address (eip55/address->checksum wallet-address)}}
@ -264,7 +264,7 @@
{:events [::on-name-and-photo-generated]
:interceptors [(re-frame/inject-cofx :random-guid-generator)
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
[{:keys [db] :as cofx} whisper-name photo-path]
[{:keys [db] :as cofx} whisper-name identicon]
(fx/merge
cofx
{:db (update-in db [:keycard :multiaccount]
@ -272,5 +272,5 @@
(assoc multiacc
:recovered true
:name whisper-name
:photo-path photo-path)))}
:identicon identicon)))}
(create-keycard-multiaccount)))

View File

@ -183,7 +183,7 @@
(let [derived-data-extended
(update derived-data
constants/path-whisper-keyword
merge {:name name :photo-path photo-path})]
merge {:name name :identicon photo-path})]
(reset! derived-acc
{:root-key root-data
:derived derived-data-extended})))))))))))

View File

@ -2,7 +2,9 @@
(:require [re-frame.core :as re-frame]
[status-im.ethereum.stateofus :as stateofus]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]
[status-im.native-module.core :as native-module]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.fx :as fx]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]
@ -10,6 +12,7 @@
[status-im.theme.core :as theme]
[status-im.utils.utils :as utils]
[quo.platform :as platform]
[taoensso.timbre :as log]
[clojure.string :as string]))
(defn contact-names
@ -54,12 +57,23 @@
(str "@" (or username ens-name)))
(or alias (gfycat/generate-gfy public-key)))))
(def photo-quality-thumbnail :thumbnail)
(def photo-quality-large :large)
(defn displayed-photo
"If a photo-path is set use it, otherwise fallback on identicon or generate"
[{:keys [photo-path identicon public-key]}]
(or photo-path
identicon
(identicon/identicon public-key)))
"If a photo, a image or an images array is set use it, otherwise fallback on identicon or generate"
[{:keys [images identicon public-key]}]
(cond
(pos? (count images))
(:uri (or (photo-quality-thumbnail images)
(photo-quality-large images)
(first images)))
(not (string/blank? identicon))
identicon
:else
(identicon/identicon public-key)))
(re-frame/reg-fx
::chaos-mode-changed
@ -145,3 +159,45 @@
(fx/merge cofx
{::switch-theme theme}
(multiaccounts.update/multiaccount-update :appearance theme {})))
(defn clean-path [path]
(if path
(string/replace-first path #"file://" "")
(log/warn "[nativ-module] Empty path was provided")))
(fx/defn save-profile-picture
{:events [::save-profile-picture]}
[cofx path ax ay bx by]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
(fx/merge cofx
{::json-rpc/call [{:method "multiaccounts_storeIdentityImage"
:params [key-uid (clean-path path) ax ay bx by]
;; NOTE: In case of an error we can show a toast error
:on-success #(re-frame/dispatch [::update-local-picture %])}]}
(multiaccounts.update/optimistic :images [{:url path
:type (name photo-quality-large)}])
(bottom-sheet/hide-bottom-sheet))))
(fx/defn delete-profile-picture
{:events [::delete-profile-picture]}
[cofx name]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
(fx/merge cofx
{::json-rpc/call [{:method "multiaccounts_deleteIdentityImage"
:params [key-uid]
;; NOTE: In case of an error we could fallback to previous image in UI with a toast error
:on-success #(log/info "[multiaccount] Delete profile image" %)}]}
(multiaccounts.update/optimistic :images nil)
(bottom-sheet/hide-bottom-sheet))))
(fx/defn get-profile-picture
[cofx]
(let [key-uid (get-in cofx [:db :multiaccount :key-uid])]
{::json-rpc/call [{:method "multiaccounts_getIdentityImages"
:params [key-uid]
:on-success #(re-frame/dispatch [::update-local-picture %])}]}))
(fx/defn store-profile-picture
{:events [::update-local-picture]}
[cofx pics]
(multiaccounts.update/optimistic cofx :images pics))

View File

@ -80,11 +80,11 @@
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
(status/gfycat-identicon-async
public-key
(fn [name photo-path]
(fn [name identicon]
(let [derived-whisper (derived-data constants/path-whisper-keyword)
derived-data-extended (assoc-in derived-data
[constants/path-whisper-keyword]
(merge derived-whisper {:name name :photo-path photo-path}))]
(merge derived-whisper {:name name :identicon identicon}))]
(re-frame/dispatch [::store-multiaccount-success
key-code derived-data-extended]))))))]
{::store-multiaccount [selected-id key-uid hashed-password callback]}))
@ -192,12 +192,12 @@
:wallet true
:path constants/path-default-wallet
:name (i18n/label :t/ethereum-account)})
(let [{:keys [public-key address name photo-path]}
(let [{:keys [public-key address name identicon]}
(get-in multiaccount [:derived constants/path-whisper-keyword])]
{:public-key public-key
:address (eip55/address->checksum address)
:name name
:photo-path photo-path
:identicon identicon
:path constants/path-whisper
:chat true})])
@ -221,10 +221,10 @@
:as multiaccount}
password
{:keys [save-mnemonic? login?] :or {login? true save-mnemonic? false}}]
(let [[wallet-account {:keys [public-key photo-path name]} :as accounts-data] (prepare-accounts-data multiaccount)
(let [[wallet-account {:keys [public-key identicon name]} :as accounts-data] (prepare-accounts-data multiaccount)
multiaccount-data {:name name
:address address
:photo-path photo-path
:identicon identicon
:key-uid key-uid
:keycard-pairing keycard-pairing}
keycard-multiaccount? (boolean keycard-pairing)
@ -243,7 +243,7 @@
constants/path-wallet-root-keyword
:address])
:name name
:photo-path photo-path
:identicon identicon
;; public key of the chat account
:public-key public-key
;; default address for Dapps
@ -269,7 +269,7 @@
db (assoc db
:multiaccounts/login {:key-uid key-uid
:name name
:photo-path photo-path
:identicon identicon
:password password
:creating? true
:processing true}

View File

@ -19,7 +19,6 @@
[status-im.ui.screens.mobile-network-settings.events :as mobile-network]
[status-im.navigation :as navigation]
[status-im.utils.fx :as fx]
[status-im.utils.identicon :as identicon]
[status-im.utils.keychain.core :as keychain]
[status-im.utils.logging.core :as logging]
[status-im.utils.security :as security]
@ -76,7 +75,7 @@
(fx/defn login
{:events [:multiaccounts.login.ui/password-input-submitted]}
[{:keys [db]}]
(let [{:keys [key-uid password name photo-path]} (:multiaccounts/login db)]
(let [{:keys [key-uid password name identicon]} (:multiaccounts/login db)]
{:db (-> db
(assoc-in [:multiaccounts/login :processing] true)
(dissoc :intro-wizard)
@ -84,7 +83,7 @@
::login [key-uid
(types/clj->json {:name name
:key-uid key-uid
:photo-path photo-path})
:identicon identicon})
(ethereum/sha3 (security/safe-unmask-data password))]}))
(fx/defn finish-keycard-setup
@ -227,6 +226,7 @@
(mobile-network/on-network-status-change)
(get-group-chat-invitations)
(logging/set-log-level (:log-level multiaccount))
(multiaccounts/get-profile-picture)
(multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist))))
@ -337,19 +337,12 @@
(navigation/navigate-to-cofx :tabs {:screen :chat-stack
:params {:screen :home}})))))
;; FIXME(Ferossgp): We should not copy keys as we denormalize the database,
;; this create desync between actual accounts and the one on login causing broken state
(fx/defn open-login
[{:keys [db] :as cofx} key-uid photo-path name public-key]
[{:keys [db] :as cofx} {:keys [key-uid] :as multiaccount}]
(fx/merge cofx
{:db (-> db
(update :multiaccounts/login assoc
:public-key public-key
:key-uid key-uid
:photo-path photo-path
:name name)
(assoc :profile/photo-added? (= (identicon/identicon public-key) photo-path))
(update :multiaccounts/login dissoc
:error
:password))}
{:db (assoc db :multiaccounts/login multiaccount)}
(keychain/get-auth-method key-uid)))
(fx/defn open-login-callback

View File

@ -5,14 +5,14 @@
:tags #{}
:address "2f88d65f3cb52605a54a833ae118fb1363acccd2"
:name "Darkviolet Lightgreen Halcyon"
:photo-path "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX///+M2KwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdPOdBAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5UBARL8TK8AAAAASUVORK5CYII="
:identicon "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX///+M2KwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdPOdBAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5UBARL8TK8AAAAASUVORK5CYII="
:system-tags #{:contact/added}
:last-online 0
:public-key "0x04d6e56a475cd35f512d6ce0bf76c2c2af435c85ff48c2b9bdefd129f620e051a436f50961eae5717b2a750e59c3f5b60647d927da46d0b8b11621640b5678fc24"}
{:last-updated 1547271764000
:address "b267ff8336ac10b3a1986c04a70ff91fb03d0b78"
:name "rv"
:photo-path "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////VjNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwYzy6AAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6IYA4bRtf+EAAAAASUVORK5CYII="
:identicon "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////VjNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwYzy6AAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6IYA4bRtf+EAAAAASUVORK5CYII="
:system-tags #{:contact/added}
:last-online 0
:public-key "0x043ae31038ff45a31b096a91d3f8290e079366fbbae76a00fbbd349cd0e5b8d7598965d206772ec4504f68908649a08383cdc51a52cdae5e9ccc744ace4d37020f"}])
@ -96,7 +96,7 @@
:poa #{}}
:preview-privacy? true
:fleet :eth.prod
:photo-path "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////YsYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPGFwxAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAloYA4a9rBHIAAAAASUVORK5CYII="
:identicon "data:image/png;base64iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAADAFBMVEX////YsYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPGFwxAAABAHRSTlP//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmfXxgAABnNJREFUeNoBaAaX+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEAAAAAAQEBAQAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAABAQEBAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAQEAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEAAAAAAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQAAAAABAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAAAAAAEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAloYA4a9rBHIAAAAASUVORK5CYII="
:wallet-set-up-passed? false
:public-key "0x04173f7cdea0076a7998abb674cc79fe61337c42db77043c01d5b0f3e3ac1e5a45bca0c93bb9f3c3d38b7cc9a7337cd64f9f9b2114fe4bbdfe1ae2633ba14d8c9c"
:keycard-key-uid nil

View File

@ -14,11 +14,11 @@
(let [cofx {:db {:multiaccounts/login {:key-uid "key-uid"
:password "password"
:name "user"
:photo-path "photo"}}}
:identicon "photo"}}}
efx (login.core/login cofx)]
(testing "Change multiaccount."
(is (= (::login.core/login efx)
["key-uid" "{\"name\":\"user\",\"key-uid\":\"key-uid\",\"photo-path\":\"photo\"}" (ethereum/sha3 "password")])))
["key-uid" "{\"name\":\"user\",\"key-uid\":\"key-uid\",\"identicon\":\"photo\"}" (ethereum/sha3 "password")])))
(testing "start activity indicator"
(is (= (get-in efx [:db :multiaccounts/login :processing]) true))))))

View File

@ -108,11 +108,11 @@
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
(status/gfycat-identicon-async
public-key
(fn [name photo-path]
(fn [name identicon]
(let [derived-data-extended
(update derived-data
constants/path-whisper-keyword
merge {:name name :photo-path photo-path})]
merge {:name name :identicon identicon})]
(re-frame/dispatch [::import-multiaccount-success
root-data derived-data-extended]))))))))))))

View File

@ -5,9 +5,9 @@
(fx/defn send-multiaccount-update [{:keys [db] :as cofx}]
(let [multiaccount (:multiaccount db)
{:keys [name preferred-name photo-path address]} multiaccount]
{:keys [name preferred-name address]} multiaccount]
{::json-rpc/call [{:method (json-rpc/call-ext-method "sendContactUpdates")
:params [(or preferred-name name) photo-path]
:params [(or preferred-name name) ""]
:on-success #(log/debug "sent contact update")}]}))
(fx/defn multiaccount-update
@ -30,7 +30,7 @@
:params [setting setting-value]
:on-success on-success}]}
(when (and (not dont-sync?)
(#{:name :photo-path :prefered-name} setting))
(#{:name :prefered-name} setting))
(send-multiaccount-update))))))
(fx/defn clean-seed-phrase

View File

@ -1,29 +0,0 @@
(ns status-im.multiaccounts.update.publisher
(:require [re-frame.core :as re-frame]
[status-im.ethereum.json-rpc :as json-rpc]
[taoensso.timbre :as log]))
;; Publish updates every 48 hours
(def publish-updates-interval (* 48 60 60 1000))
(defn publish-update! [{:keys [db now]}]
(let [peers-count (:peers-count db)
last-updated (get-in
db
[:multiaccount :last-updated])]
(when (and (pos? peers-count)
(pos? last-updated)
(< publish-updates-interval
(- now last-updated)))
(let [multiaccount (:multiaccount db)
{:keys [name preferred-name photo-path]} multiaccount]
(log/debug "sending contact updates")
(json-rpc/call {:method (json-rpc/call-ext-method "sendContactUpdates")
:params [(or preferred-name name) photo-path]
:on-failure #(do
(log/warn "failed to send contact updates")
(re-frame/dispatch [:multiaccounts.update.callback/failed-to-publish]))
:on-success #(do
(log/debug "sent contact updates")
(re-frame/dispatch [:multiaccounts.update.callback/published]))})))))

View File

@ -171,9 +171,9 @@
(defn send-installation-messages [{:keys [db]}]
(let [multiaccount (:multiaccount db)
{:keys [name preferred-name photo-path]} multiaccount]
{:keys [name preferred-name identicon]} multiaccount]
{::json-rpc/call [{:method (json-rpc/call-ext-method "syncDevices")
:params [(or preferred-name name) photo-path]
:params [(or preferred-name name) identicon]
:on-success #(log/debug "successfully synced devices")}]}))
(defn installation<-rpc [{:keys [metadata id enabled]}]

View File

@ -99,7 +99,6 @@
(reg-root-key-sub :my-profile/advanced? :my-profile/advanced?)
(reg-root-key-sub :my-profile/editing? :my-profile/editing?)
(reg-root-key-sub :my-profile/profile :my-profile/profile)
(reg-root-key-sub :profile/photo-added? :profile/photo-added?)
;;multiaccount
(reg-root-key-sub :multiaccounts/multiaccounts :multiaccounts/multiaccounts)
@ -275,9 +274,9 @@
:intro-wizard/recovery-success
:<- [:intro-wizard]
(fn [wizard-state]
{:pubkey (get-in wizard-state [:derived constants/path-whisper-keyword :public-key])
:name (get-in wizard-state [:derived constants/path-whisper-keyword :name])
:photo-path (get-in wizard-state [:derived constants/path-whisper-keyword :photo-path])
{:pubkey (get-in wizard-state [:derived constants/path-whisper-keyword :public-key])
:name (get-in wizard-state [:derived constants/path-whisper-keyword :name])
:identicon (get-in wizard-state [:derived constants/path-whisper-keyword :identicon])
:processing? (:processing? wizard-state)}))
(re-frame/reg-sub
@ -477,7 +476,7 @@
(fn [current-account]
(some->
current-account
(select-keys [:name :preferred-name :public-key :photo-path])
(select-keys [:name :preferred-name :public-key :identicon :image :images])
(clojure.set/rename-keys {:name :alias})
(multiaccounts/contact-with-names))))
@ -811,13 +810,16 @@
(re-frame/reg-sub
:chats/photo-path
:<- [:contacts/contacts]
:<- [::contacts]
:<- [:multiaccount]
(fn [[contacts multiaccount] [_ id]]
(multiaccounts/displayed-photo (or (get contacts id)
(when (= id (:public-key multiaccount))
multiaccount)
(contact.db/public-key->new-contact id)))))
(fn [[contacts multiaccount] [_ id identicon]]
(let [contact (or (get contacts id)
(when (= id (:public-key multiaccount)
multiaccount))
(if identicon
{:identicon identicon}
(contact.db/public-key->new-contact id)))]
(multiaccounts/displayed-photo contact))))
(re-frame/reg-sub
:chats/unread-messages-number
@ -935,10 +937,13 @@
:<- [:contacts/contacts]
(fn [contacts]
(reduce
(fn [acc [key {:keys [alias name identicon public-key nickname] :as contact}]]
(fn [acc [key {:keys [alias name added? blocked? identicon public-key nickname]}]]
(if (and alias
(not= alias "")
(not (contact.db/blocked? contact)))
(or name
nickname
added?)
(not blocked?))
(let [name (utils/safe-replace name ".stateofus.eth" "")]
(assoc acc public-key
(mentions/add-searchable-phrases
@ -957,14 +962,13 @@
:<- [:chats/mentionable-contacts]
:<- [:contacts/blocked-set]
:<- [:multiaccount]
(fn [[{:keys [users]} contacts blocked {:keys [name preferred-name photo-path public-key]}]]
(fn [[{:keys [users]} contacts blocked {:keys [name preferred-name public-key]}]]
(apply dissoc
(-> users
(merge contacts)
(assoc public-key (mentions/add-searchable-phrases
{:alias name
:name (or preferred-name name)
:identicon photo-path
:public-key public-key})))
blocked)))
@ -1844,8 +1848,11 @@
(re-frame/reg-sub
:contacts/contact-by-address
:<- [:contacts/contacts]
(fn [contacts [_ address]]
(contact.db/find-contact-by-address contacts address)))
:<- [:multiaccount/contact]
(fn [[contacts multiaccount] [_ address]]
(if (ethereum/address= address (:public-key multiaccount))
multiaccount
(contact.db/find-contact-by-address contacts address))))
(re-frame/reg-sub
:contacts/contacts-by-address
@ -2416,3 +2423,9 @@
(first (filter #(notifications/preference= % {:service "wallet"
:event "transaction"
:identifier "all"}) pref))))
(re-frame/reg-sub
:profile/has-picture
:<- [:multiaccount]
(fn [multiaccount]
(pos? (count (get multiaccount :images)))))

View File

@ -2,6 +2,7 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame.core]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.chat-icon.styles :as styles]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.react :as react]
@ -125,11 +126,9 @@
:default-chat-icon (styles/default-chat-icon-profile color size)
:default-chat-icon-text (styles/default-chat-icon-text size)} override-styles)]
[react/view (:container styles)
(when edit?
[react/view (styles/profile-icon-mask size)])
(when edit?
[react/view (styles/profile-icon-edit-text-containter size)
[react/i18n-text {:style styles/profile-icon-edit-text :key :edit}]])
(if (and photo-path (seq photo-path))
[photos/photo photo-path styles]
[default-chat-icon name styles])]))
[default-chat-icon name styles])
(when edit?
[react/view {:style (styles/chat-icon-profile-edit)}
[icons/tiny-icon :tiny-icons/tiny-edit {:color colors/white-persist}]])]))

View File

@ -121,23 +121,15 @@
{:width 36
:height 36})
(defn profile-icon-mask [size]
{:height size
:width size
(defn chat-icon-profile-edit []
{:width 24
:height 24
:border-radius 12
:border-width 1
:border-color colors/white-persist
:background-color colors/blue
:justify-content :center
:align-items :center
:position :absolute
:z-index 1
:background-color colors/black
:opacity 0.4
:border-radius 50})
(defn profile-icon-edit-text-containter [size]
{:height size
:width size
:position :absolute
:z-index 2
:align-items :center
:justify-content :center})
(def profile-icon-edit-text
{:color colors/white
:background-color :transparent})
:bottom -2
:right -2})

View File

@ -37,23 +37,27 @@
(when-not minimized
{:padding-top subtitle-margin})))
(defn extended-header [{:keys [title photo color subtitle subtitle-icon on-press monospace bottom-separator]
:or {bottom-separator true}}]
(defn extended-header [{:keys [title photo color subtitle subtitle-icon on-edit on-press monospace bottom-separator]
:or {bottom-separator true}}]
(fn [{:keys [animation minimized]}]
(let [wrapper (if on-press
[rn/touchable-opacity {:on-press on-press}]
[:<>])]
(let [wrapper (if on-press
[rn/touchable-opacity {:on-press on-press}]
[:<>])
editable (if (and (not minimized) on-edit)
[rn/touchable-opacity {:on-press on-edit}]
[:<>])]
(into
wrapper
[[animated/view {:pointer-events :box-none}
[animated/view {:style (container-style {:animation animation
:minimized minimized})
:pointer-events :box-none}
[animated/view {:pointer-events :box-none}
[chat-icon.screen/profile-icon-view
photo title color nil
(if minimized avatar-minimized-size avatar-extended-size)
nil]]
(into editable
[[animated/view {:pointer-events :box-none}
[chat-icon.screen/profile-icon-view
photo title color (and (not minimized) on-edit)
(if minimized avatar-minimized-size avatar-extended-size)
nil]]])
[animated/view {:style (header-text)
:pointer-events :box-none}
[quo/text {:animated? true

View File

@ -194,9 +194,12 @@
(defn show-image-picker
([images-fn]
(show-image-picker images-fn nil))
([images-fn {:keys [multiple media-type]}]
([images-fn {:keys [media-type]
:or {media-type "any"}
:as props}]
(-> ^js image-picker
(.openPicker (clj->js {:multiple multiple :mediaType (or media-type "any")}))
(.openPicker (clj->js (merge {:mediaType media-type}
props)))
(.then images-fn)
(.catch show-access-error))))

View File

@ -18,7 +18,7 @@
[status-im.chat.models.mentions :as mentions]
[status-im.ui.components.list.views :as list]
[quo.components.list.item :as list-item]
[status-im.ui.screens.chat.styles.photos :as photo-style]
[status-im.ui.screens.chat.photos :as photos]
[reagent.core :as reagent]))
(def panel->icons {:extensions :main-icons/commands
@ -199,18 +199,10 @@
input-with-mentions)]]))
(defn mention-item
[[_ {:keys [identicon alias name nickname] :as user}] _ _ text-input-ref]
[[public-key {:keys [alias name nickname] :as user}] _ _ text-input-ref]
(let [ens-name? (not= alias name)]
[list-item/list-item
(cond-> {:icon
[rn/view {:style {}}
[rn/image
{:source {:uri identicon}
:style (photo-style/photo-border
photo-style/default-size
nil)
:resize-mode :cover}]]
:icon-container-style {}
(cond-> {:icon [photos/member-photo public-key]
:size :small
:text-size :small
:title

View File

@ -211,7 +211,8 @@
(defn message-content-wrapper
"Author, userpic and delivery wrapper"
[{:keys [first-in-group? display-photo? identicon display-username?
[{:keys [first-in-group? display-photo? display-username?
identicon
from outgoing]
:as message} content {:keys [modal close-modal]}]
[react/view {:style (style/message-wrapper message)
@ -224,7 +225,7 @@
(when first-in-group?
[react/touchable-highlight {:on-press #(do (when modal (close-modal))
(re-frame/dispatch [:chat.ui/show-profile-without-adding-contact from]))}
[photos/member-identicon identicon]])])
[photos/member-photo from identicon]])])
[react/view {:style (style/message-author-wrapper outgoing display-photo?)}
(when display-username?
[react/touchable-opacity {:style style/message-author-touchable

View File

@ -1,9 +1,10 @@
(ns status-im.ui.screens.chat.photos
(:require [status-im.ui.components.react :as react]
(:require [re-frame.core :as re-frame]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.styles.photos :as style]
[status-im.ui.screens.profile.db :as profile.db]
[status-im.utils.image :as utils.image])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.image :as utils.image]))
(defn photo [photo-path {:keys [size accessibility-label]}]
(let [identicon? (when photo-path (profile.db/base64-png? photo-path))]
@ -15,11 +16,16 @@
(when identicon?
[react/view {:style (style/photo-border size)}])]))
(defview member-photo [from & [identicon size]]
(letsubs [photo-path [:chats/photo-path from]]
(photo (or photo-path identicon)
{:accessibility-label :member-photo
:size (or size style/default-size)})))
;; We optionally pass identicon for perfomance reason, so it does not have to be calculated for each message
(defn member-photo [pub-key identicon]
(let [path @(re-frame/subscribe [:chats/photo-path pub-key identicon])]
[photo path {:size style/default-size
:accessibility-label :member-photo}]))
(defn account-photo [account]
(let [path (multiaccounts/displayed-photo account)]
[photo path {:size style/default-size
:accessibility-label :own-account-photo}]))
(defn member-identicon [identicon]
(let [size style/default-size]
@ -28,4 +34,4 @@
:style (style/photo size)
:resize-mode :cover
:accessibility-label :member-photo}]
[react/view {:style (style/photo-border size)}]]))
[react/view {:style (style/photo-border size)}]]))

View File

@ -376,7 +376,7 @@
wizard-state)]]]))
(defview wizard-recovery-success []
(letsubs [{:keys [pubkey processing? name photo-path]} [:intro-wizard/recovery-success]
(letsubs [{:keys [pubkey processing? name identicon]} [:intro-wizard/recovery-success]
existing-account? [:intro-wizard/recover-existing-account?]]
[react/view {:style {:flex 1}}
[topbar/topbar
@ -386,7 +386,7 @@
[react/view {:style {:flex 1
:justify-content :space-between}}
[top-bar {:step :recovery-success}]
[recovery-success pubkey name photo-path]
[recovery-success pubkey name identicon]
[bottom-bar {:step :recovery-success
:forward-action :multiaccounts.recover/re-encrypt-pressed
:processing? processing?

View File

@ -166,8 +166,8 @@
{:should-component-update
(fn [_ [_ old-account] [_ new-account]]
(and (not (nil? new-account))
(and (not (:photo-path old-account))
(nil? (:photo-path new-account)))))
(and (not (:identicon old-account))
(nil? (:identicon new-account)))))
:reagent-render
(fn [account small-screen?]

View File

@ -24,14 +24,12 @@
(defn multiaccount-login-badge [{:keys [public-key name] :as multiaccount}]
[react/view styles/login-badge
[photos/photo
;;TODO this should be done in a subscription
(multiaccounts/displayed-photo multiaccount)
{:size styles/login-badge-image-size}]
[react/view
[react/text {:style styles/login-badge-name
:ellipsize-mode :middle
:numberOfLines 1}
;;TODO this should be done in a subscription
name]
[quo/text {:monospace true
:align :center

View File

@ -2,6 +2,7 @@
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame]
[status-im.ui.screens.chat.photos :as photos]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.multiaccounts.styles :as styles]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
@ -14,10 +15,10 @@
[status-im.react-native.resources :as resources]))
(defn multiaccount-view
[{:keys [key-uid photo-path name keycard-pairing]}]
[{:keys [key-uid name keycard-pairing] :as account}]
[quo/list-item {:on-press #(re-frame/dispatch
[:multiaccounts.login.ui/multiaccount-selected key-uid])
:icon [photos/photo photo-path {:size styles/multiaccount-image-size}]
:icon [photos/photo (multiaccounts/displayed-photo account) {:size styles/multiaccount-image-size}]
:title name
:accessory (when keycard-pairing
[react/view {:justify-content :center

View File

@ -1,48 +1,9 @@
(ns status-im.ui.screens.profile.events
(:require [re-frame.core :as re-frame]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.ui.screens.profile.models :as profile.models]
[status-im.ui.components.list-selection :as list-selection]
[status-im.utils.handlers :as handlers]
[status-im.utils.identicon :as identicon]
[status-im.utils.universal-links.utils :as universal-links]
[status-im.utils.fx :as fx]))
(handlers/register-handler-fx
:profile/send-transaction
(fn [cofx [_ chat-id]]
(profile.models/send-transaction chat-id cofx)))
(handlers/register-handler-fx
:my-profile/update-name
(fn [cofx [_ name]]
(profile.models/update-name name cofx)))
(handlers/register-handler-fx
:my-profile/remove-current-photo
(fn [{:keys [db] :as cofx}]
(fx/merge cofx
{:db (-> db
(assoc-in [:my-profile/profile :photo-path]
(identicon/identicon (multiaccounts.model/current-public-key cofx)))
(assoc :my-profile/editing? true
:profile/photo-added? false))}
(profile.models/save))))
(handlers/register-handler-fx
:my-profile/start-editing-profile
(fn [cofx _]
(profile.models/start-editing cofx)))
(handlers/register-handler-fx
:my-profile/save-profile
(fn [cofx _]
(profile.models/save cofx)))
(handlers/register-handler-fx
:group-chat-profile/start-editing
(fn [cofx _]
(profile.models/start-editing-group-chat-profile cofx)))
[status-im.utils.universal-links.utils :as universal-links]))
(handlers/register-handler-fx
:my-profile/enter-two-random-words

View File

@ -1,57 +1,11 @@
(ns status-im.ui.screens.profile.models
(:require [clojure.spec.alpha :as spec]
[clojure.string :as clojure.string]
(:require [clojure.string :as clojure.string]
[re-frame.core :as re-frame]
[status-im.ui.components.react :as react]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.chat.models :as chat-models]
[taoensso.timbre :as log]
[status-im.utils.fx :as fx]))
(defn send-transaction [chat-id cofx]
;;TODO start send transaction command flow
(chat-models/start-chat cofx chat-id))
(defn- valid-name? [name]
(spec/valid? :profile/name name))
(defn update-name [name {:keys [db]}]
{:db (-> db
(assoc-in [:my-profile/profile :valid-name?] (valid-name? name))
(assoc-in [:my-profile/profile :name] name))})
(defn- clean-name [db edit-view]
(let [name (get-in db [edit-view :name])]
(if (valid-name? name)
name
(get-in db [:multiaccount :name]))))
(fx/defn clear-profile
[{:keys [db]}]
{:db (dissoc db :my-profile/profile :my-profile/default-name :my-profile/editing?)})
(defn start-editing [{:keys [db]}]
(let [profile (select-keys (:multiaccount db) [:name :photo-path])]
{:db (assoc db
:my-profile/editing? true
:my-profile/profile profile)}))
(fx/defn save [{:keys [db now] :as cofx}]
(let [{:keys [photo-path]} (:my-profile/profile db)
cleaned-name (clean-name db :my-profile/profile)]
(fx/merge cofx
(clear-profile)
(multiaccounts.update/multiaccount-update :name cleaned-name {})
(multiaccounts.update/multiaccount-update :last-updated now {})
(when photo-path
(multiaccounts.update/multiaccount-update :photo-path photo-path {})))))
(defn start-editing-group-chat-profile [{:keys [db]}]
(let [current-chat-name (get-in db [:chats (:current-chat-id db) :name])]
{:db (-> db
(assoc :group-chat-profile/editing? true)
(assoc-in [:group-chat-profile/profile :name] current-chat-name))}))
(defn enter-two-random-words [{:keys [db]}]
(let [{:keys [mnemonic]} (:multiaccount db)
shuffled-mnemonic (shuffle (map-indexed vector (clojure.string/split mnemonic #" ")))]
@ -62,7 +16,7 @@
(defn set-step [step {:keys [db]}]
{:db (update db :my-profile/seed assoc :step step :error nil :word nil)})
(defn finish [{:keys [db] :as cofx}]
(fx/defn finish [{:keys [db] :as cofx}]
(fx/merge cofx
{:db (update db :my-profile/seed assoc :step :finish :error nil :word nil)}
(multiaccounts.update/clean-seed-phrase)))

View File

@ -0,0 +1,44 @@
(ns status-im.ui.screens.profile.user.edit-picture
(:require [quo.core :as quo]
[re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.utils.config :as config]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.react :as react]))
(def crop-size 1000)
(def crop-opts {:cropping true
:cropperCircleOverlay true
:width crop-size
:height crop-size})
(defn pick-pic []
(react/show-image-picker
#(re-frame/dispatch [::multiaccounts/save-profile-picture (.-path ^js %) 0 0 crop-size crop-size])
crop-opts))
(defn take-pic []
(react/show-image-picker-camera
#(re-frame/dispatch [::multiaccounts/save-profile-picture (.-path ^js %) 0 0 crop-size crop-size])
crop-opts))
(defn bottom-sheet [has-picture]
(fn []
[:<>
[quo/list-item {:accessibility-label :take-photo
:theme :accent
:icon :main-icons/camera
:title (i18n/label :t/profile-pic-take)
:on-press take-pic}]
[quo/list-item {:accessibility-label :pick-photo
:icon :main-icons/gallery
:theme :accent
:title (i18n/label :t/profile-pic-pick)
:on-press pick-pic}]
(when (and config/enable-remove-profile-picture?
has-picture)
[quo/list-item {:accessibility-label :remove-photo
:icon :main-icons/delete
:theme :accent
:title (i18n/label :t/profile-pic-remove)
:on-press #(re-frame/dispatch [::multiaccounts/delete-profile-picture nil])}])]))

View File

@ -16,6 +16,7 @@
[status-im.utils.gfycat.core :as gfy]
[status-im.utils.universal-links.utils :as universal-links]
[status-im.ui.components.profile-header.view :as profile-header]
[status-im.ui.screens.profile.user.edit-picture :as edit]
[status-im.utils.utils :as utils]
[status-im.ethereum.stateofus :as stateofus])
(:require-macros [status-im.utils.views :as views]))
@ -167,10 +168,11 @@
(fn []
(let [{:keys [public-key ens-verified preferred-name]
:as account} @(re-frame/subscribe [:multiaccount])
on-share #(re-frame/dispatch [:show-popover
{:view :share-chat-key
:address public-key
:ens-name preferred-name}])]
on-share #(re-frame/dispatch [:show-popover
{:view :share-chat-key
:address public-key
:ens-name preferred-name}])
has-picture @(re-frame/subscribe [:profile/has-picture])]
[react/view {:flex 1}
[quo/animated-header
{:right-accessories [{:accessibility-label :share-header-button
@ -178,11 +180,13 @@
:on-press on-share}]
:use-insets true
:extended-header (profile-header/extended-header
{:on-press on-share
:title (multiaccounts/displayed-name account)
:photo (multiaccounts/displayed-photo account)
:monospace (not ens-verified)
:subtitle (if (and ens-verified public-key)
(gfy/generate-gfy public-key)
(utils/get-shortened-address public-key))})}
{:on-press on-share
:on-edit #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content (edit/bottom-sheet has-picture)}])
:title (multiaccounts/displayed-name account)
:photo (multiaccounts/displayed-photo account)
:monospace (not ens-verified)
:subtitle (if (and ens-verified public-key)
(gfy/generate-gfy public-key)
(utils/get-shortened-address public-key))})}
[content]]])))

View File

@ -17,7 +17,6 @@
[status-im.ui.screens.chat.photos :as photos]
[status-im.ui.components.tabs :as tabs]
[status-im.utils.contenthash :as contenthash]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.chat.message.reactions :as reactions]
[status-im.chat.models.reactions :as models.reactions]
[status-im.ui.screens.chat.components.reply :as components.reply]
@ -101,7 +100,7 @@
[message-content-image (:image content) false]]])))
(defn message-item [account]
(fn [{:keys [content-type content from timestamp identicon outgoing] :as message}
(fn [{:keys [content-type content from timestamp outgoing] :as message}
{:keys [modal on-long-press close-modal]}]
[react/view (merge {:padding-vertical 8
:flex-direction :row
@ -114,8 +113,8 @@
(re-frame/dispatch [:chat.ui/show-profile-without-adding-contact from]))}
[react/view {:padding-top 2 :padding-right 8}
(if outgoing
[photos/member-identicon (multiaccounts/displayed-photo account)]
[photos/member-identicon identicon])]]
[photos/account-photo account]
[photos/member-photo from])]]
[react/view {:flex 1}
[react/view {:flex-direction :row
:justify-content :space-between}

View File

@ -55,6 +55,8 @@
(def pow-target (js/parseFloat (get-config :POW_TARGET "0.0001")))
(def pow-time (js/parseInt (get-config :POW_TIME "1")))
(def max-installations 2)
; currently not supported in status-go
(def enable-remove-profile-picture? false)
(def verify-transaction-chain-id (js/parseInt (get-config :VERIFY_TRANSACTION_CHAIN_ID "1")))
(def verify-transaction-url (if (= :mainnet (ethereum/chain-id->chain-keyword verify-transaction-chain-id))

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im",
"repo": "status-go",
"version": "v0.64.8",
"commit-sha1": "50b17308bde0008daf4c8365782575d4f22b1515",
"src-sha256": "140xbx3xlzgcbp3iv98if9gbjslmg94gpzzbwqa303fh6mg460fw"
"version": "v0.65.0",
"commit-sha1": "cdca42b90f7fd5f302a5eb31802b9ae526d566d7",
"src-sha256": "1qpq9y099bfa6x36afbimn2p5inzrsgbb8qzigmchl513mkhp5s1"
}

View File

@ -529,6 +529,9 @@
"image-source-gallery": "Select from gallery",
"image-source-make-photo": "Capture",
"image-source-title": "Edit picture",
"profile-pic-take": "Take photo",
"profile-pic-pick": "Select from gallery",
"profile-pic-remove": "Remove photo",
"in-contacts": "In contacts",
"incoming": "Incoming",
"incoming-transaction": "Incoming transaction",