Keep username/photo-path synced across devices
We add syncing of account fields in pairing messages (only photo-path & name for now). Also a sync message is sent each time we send a contact-update, to keep other devices in sync. The change is compatible with previous clients as it's just an accretion of transit. Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
6cf9e6136b
commit
08291a8396
|
@ -47,6 +47,13 @@
|
|||
|
||||
(def merge-contacts (partial merge-with merge-contact))
|
||||
|
||||
(def account-mergeable-keys [:name :photo-path :last-updated])
|
||||
|
||||
(defn merge-account [local remote]
|
||||
(if (> (:last-updated remote) (:last-updated local))
|
||||
(merge local (select-keys remote account-mergeable-keys))
|
||||
local))
|
||||
|
||||
(fx/defn upsert-installation [{:keys [db]} {:keys [installation-id] :as new-installation}]
|
||||
(let [old-installation (get-in db [:pairing/installations installation-id])
|
||||
updated-installation (merge old-installation new-installation)]
|
||||
|
@ -68,18 +75,26 @@
|
|||
(not (get-in db [:pairing/installations installation-id])))
|
||||
(upsert-installation cofx new-installation))))))
|
||||
|
||||
(defn sync-installation-messages [{:keys [db]}]
|
||||
(let [contacts (:contacts/contacts db)]
|
||||
(map
|
||||
(fn [batch]
|
||||
(let [contacts-to-sync (reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(assoc acc public-key (dissoc contact :photo-path)))
|
||||
{}
|
||||
batch)]
|
||||
(transport.pairing/SyncInstallation. contacts-to-sync)))
|
||||
(partition-all contact-batch-n (->> contacts
|
||||
vals
|
||||
(remove :dapp?))))))
|
||||
(defn sync-installation-account-message [{:keys [db]}]
|
||||
(let [account (-> db
|
||||
:account/account
|
||||
(select-keys account-mergeable-keys))]
|
||||
(transport.pairing/SyncInstallation. {} account)))
|
||||
|
||||
(defn- contact-batch->sync-installation-message [batch]
|
||||
(let [contacts-to-sync (reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(assoc acc public-key (dissoc contact :photo-path)))
|
||||
{}
|
||||
batch)]
|
||||
(transport.pairing/SyncInstallation. contacts-to-sync nil)))
|
||||
|
||||
(defn sync-installation-messages [{:keys [db] :as cofx}]
|
||||
(let [contacts (:contacts/contacts db)
|
||||
contact-batches (partition-all contact-batch-n (->> contacts
|
||||
vals
|
||||
(remove :dapp?)))]
|
||||
(conj (mapv contact-batch->sync-installation-message contact-batches)
|
||||
(sync-installation-account-message cofx))))
|
||||
|
||||
(defn enable [{:keys [db]} installation-id]
|
||||
{:db (assoc-in db
|
||||
|
@ -167,12 +182,15 @@
|
|||
{}
|
||||
contacts))
|
||||
|
||||
(defn handle-sync-installation [{:keys [db] :as cofx} {:keys [contacts]} sender]
|
||||
(defn handle-sync-installation [{:keys [db] :as cofx} {:keys [contacts account]} sender]
|
||||
(let [dev-mode? (get-in db [:account/account :dev-mode?])]
|
||||
(when (and (config/pairing-enabled? dev-mode?)
|
||||
(= sender (accounts.db/current-public-key cofx)))
|
||||
(let [new-contacts (merge-contacts (:contacts/contacts db) (ensure-photo-path contacts))]
|
||||
{:db (assoc db :contacts/contacts new-contacts)
|
||||
(let [new-contacts (merge-contacts (:contacts/contacts db) (ensure-photo-path contacts))
|
||||
new-account (merge-account (:account/account db) account)]
|
||||
{:db (assoc db
|
||||
:contacts/contacts new-contacts
|
||||
:account/account new-account)
|
||||
:data-store/tx [(data-store.contacts/save-contacts-tx (vals new-contacts))]}))))
|
||||
|
||||
(defn handle-pair-installation [{:keys [db] :as cofx} {:keys [installation-id device-type]} timestamp sender]
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
(let [sync-message (transport.pairing/SyncInstallation.
|
||||
(select-keys
|
||||
(get-in cofx [:db :contacts/contacts])
|
||||
[chat-id]))]
|
||||
[chat-id])
|
||||
nil)]
|
||||
(fx/merge cofx
|
||||
(protocol/init-chat {:chat-id chat-id
|
||||
:resend? "contact-request"})
|
||||
|
@ -45,7 +46,8 @@
|
|||
(let [sync-message (transport.pairing/SyncInstallation.
|
||||
(select-keys
|
||||
(get-in cofx [:db :contacts/contacts])
|
||||
[chat-id]))
|
||||
[chat-id])
|
||||
nil)
|
||||
success-event [:transport/contact-message-sent chat-id]
|
||||
chat (get-in db [:transport/chats chat-id])
|
||||
updated-chat (if chat
|
||||
|
@ -60,3 +62,35 @@
|
|||
:payload this
|
||||
:success-event success-event})
|
||||
(pairing/send-installation-message-fx sync-message)))))
|
||||
|
||||
(fx/defn send-contact-update
|
||||
[{:keys [db] :as cofx} chat-id payload]
|
||||
(when-let [chat (get-in cofx [:db :transport/chats chat-id])]
|
||||
(let [updated-chat (assoc chat :resend? "contact-update")
|
||||
tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]
|
||||
success-event [:transport/contact-message-sent chat-id]]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id :resend?]
|
||||
"contact-update")
|
||||
:data-store/tx tx}
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload payload
|
||||
:success-event success-event})))))
|
||||
(extend-type transport.contact/ContactUpdate
|
||||
protocol/StatusMessage
|
||||
(send [this _ {:keys [db] :as cofx}]
|
||||
(let [contact-public-keys (reduce (fn [acc [_ {:keys [public-key dapp? pending?]}]]
|
||||
(if (and (not dapp?)
|
||||
(not pending?))
|
||||
(conj acc public-key)
|
||||
acc))
|
||||
#{}
|
||||
(:contacts/contacts db))
|
||||
;;NOTE: chats with contacts use public-key as chat-id
|
||||
send-contact-update-fxs (map #(send-contact-update % this) contact-public-keys)
|
||||
sync-message (pairing/sync-installation-account-message cofx)
|
||||
fxs (conj send-contact-update-fxs
|
||||
(pairing/send-installation-message-fx sync-message))]
|
||||
(apply fx/merge cofx fxs))))
|
||||
|
|
|
@ -18,35 +18,8 @@
|
|||
(when (spec/valid? :message/contact-request-confirmed this)
|
||||
this)))
|
||||
|
||||
(fx/defn send-contact-update
|
||||
[{:keys [db] :as cofx} chat-id payload]
|
||||
(when-let [chat (get-in cofx [:db :transport/chats chat-id])]
|
||||
(let [updated-chat (assoc chat :resend? "contact-update")
|
||||
tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]
|
||||
success-event [:transport/contact-message-sent chat-id]]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:transport/chats chat-id :resend?]
|
||||
"contact-update")
|
||||
:data-store/tx tx}
|
||||
(protocol/send-with-pubkey {:chat-id chat-id
|
||||
:payload payload
|
||||
:success-event success-event})))))
|
||||
|
||||
(defrecord ContactUpdate [name profile-image address fcm-token]
|
||||
protocol/StatusMessage
|
||||
(send [this _ {:keys [db] :as cofx}]
|
||||
(let [contact-public-keys (reduce (fn [acc [_ {:keys [public-key dapp? pending?]}]]
|
||||
(if (and (not dapp?)
|
||||
(not pending?))
|
||||
(conj acc public-key)
|
||||
acc))
|
||||
#{}
|
||||
(:contacts/contacts db))
|
||||
;;NOTE: chats with contacts use public-key as chat-id
|
||||
send-contact-update-fxs (map #(send-contact-update % this) contact-public-keys)]
|
||||
(apply fx/merge cofx send-contact-update-fxs)))
|
||||
(validate [this]
|
||||
(when (spec/valid? :message/contact-update this)
|
||||
this)))
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
(log/warn "failed sync installation validation" (spec/explain :message/pair-installation this)))))
|
||||
|
||||
(defrecord SyncInstallation
|
||||
[contacts]
|
||||
[contacts account]
|
||||
protocol/StatusMessage
|
||||
(validate [this]
|
||||
(if (spec/valid? :message/sync-installation this)
|
||||
|
|
|
@ -86,8 +86,8 @@
|
|||
(deftype SyncInstallationHandler []
|
||||
Object
|
||||
(tag [this v] "p1")
|
||||
(rep [this {:keys [contacts]}]
|
||||
#js [contacts]))
|
||||
(rep [this {:keys [contacts account]}]
|
||||
#js [contacts account]))
|
||||
|
||||
(deftype PairInstallationHandler []
|
||||
Object
|
||||
|
@ -154,8 +154,8 @@
|
|||
(contact/ContactUpdate. name profile-image address fcm-token))
|
||||
"g5" (fn [[chat-id membership-updates message]]
|
||||
(group-chat/GroupMembershipUpdate. chat-id membership-updates message))
|
||||
"p1" (fn [[contacts]]
|
||||
(pairing/SyncInstallation. contacts))
|
||||
"p1" (fn [[contacts account]]
|
||||
(pairing/SyncInstallation. contacts account))
|
||||
"p2" (fn [[installation-id device-type]]
|
||||
(pairing/PairInstallation. installation-id device-type))}}))
|
||||
|
||||
|
|
|
@ -75,64 +75,85 @@
|
|||
(deftest handle-sync-installation-test
|
||||
(with-redefs [config/pairing-enabled? (constantly true)
|
||||
identicon/identicon (constantly "generated")]
|
||||
(let [old-contact-1 {:name "old-contact-one"
|
||||
:public-key "contact-1"
|
||||
:last-updated 0
|
||||
:photo-path "old-contact-1"
|
||||
:pending? true}
|
||||
new-contact-1 {:name "new-contact-one"
|
||||
:public-key "contact-1"
|
||||
:last-updated 1
|
||||
:photo-path "new-contact-1"
|
||||
:pending? false}
|
||||
old-contact-2 {:name "old-contact-2"
|
||||
:public-key "contact-2"
|
||||
:last-updated 0
|
||||
:photo-path "old-contact-2"
|
||||
:pending? false}
|
||||
new-contact-2 {:name "new-contact-2"
|
||||
:public-key "contact-2"
|
||||
:last-updated 1
|
||||
:photo-path "new-contact-2"
|
||||
:pending? false}
|
||||
contact-3 {:name "contact-3"
|
||||
:public-key "contact-3"
|
||||
:photo-path "contact-3"
|
||||
:pending? false}
|
||||
contact-4 {:name "contact-4"
|
||||
:public-key "contact-4"
|
||||
:pending? true}
|
||||
local-contact-5 {:name "contact-5"
|
||||
:photo-path "local"
|
||||
:public-key "contact-5"
|
||||
:pending? true
|
||||
:last-updated 1}
|
||||
remote-contact-5 {:name "contact-5"
|
||||
:public-key "contact-5"
|
||||
:photo-path "remote"
|
||||
:pending? true
|
||||
:last-updated 1}
|
||||
cofx {:db {:account/account {:public-key "us"}
|
||||
:contacts/contacts {"contact-1" old-contact-1
|
||||
"contact-2" new-contact-2
|
||||
"contact-3" contact-3
|
||||
"contact-5" local-contact-5}}}
|
||||
sync-message {:contacts {"contact-1" new-contact-1
|
||||
"contact-2" old-contact-2
|
||||
"contact-4" contact-4
|
||||
"contact-5" remote-contact-5}}
|
||||
expected {"contact-1" new-contact-1
|
||||
"contact-2" new-contact-2
|
||||
"contact-3" contact-3
|
||||
"contact-4" (assoc contact-4
|
||||
:photo-path "generated")
|
||||
"contact-5" local-contact-5}]
|
||||
(testing "not coming from us"
|
||||
(is (not (pairing/handle-sync-installation cofx sync-message "not-us"))))
|
||||
(testing "coming from us"
|
||||
(is (= expected (get-in
|
||||
(pairing/handle-sync-installation cofx sync-message "us")
|
||||
[:db :contacts/contacts])))))))
|
||||
|
||||
(testing "syncing contacts"
|
||||
(let [old-contact-1 {:name "old-contact-one"
|
||||
:public-key "contact-1"
|
||||
:last-updated 0
|
||||
:photo-path "old-contact-1"
|
||||
:pending? true}
|
||||
new-contact-1 {:name "new-contact-one"
|
||||
:public-key "contact-1"
|
||||
:last-updated 1
|
||||
:photo-path "new-contact-1"
|
||||
:pending? false}
|
||||
old-contact-2 {:name "old-contact-2"
|
||||
:public-key "contact-2"
|
||||
:last-updated 0
|
||||
:photo-path "old-contact-2"
|
||||
:pending? false}
|
||||
new-contact-2 {:name "new-contact-2"
|
||||
:public-key "contact-2"
|
||||
:last-updated 1
|
||||
:photo-path "new-contact-2"
|
||||
:pending? false}
|
||||
contact-3 {:name "contact-3"
|
||||
:public-key "contact-3"
|
||||
:photo-path "contact-3"
|
||||
:pending? false}
|
||||
contact-4 {:name "contact-4"
|
||||
:public-key "contact-4"
|
||||
:pending? true}
|
||||
local-contact-5 {:name "contact-5"
|
||||
:photo-path "local"
|
||||
:public-key "contact-5"
|
||||
:pending? true
|
||||
:last-updated 1}
|
||||
remote-contact-5 {:name "contact-5"
|
||||
:public-key "contact-5"
|
||||
:photo-path "remote"
|
||||
:pending? true
|
||||
:last-updated 1}
|
||||
cofx {:db {:account/account {:public-key "us"}
|
||||
:contacts/contacts {"contact-1" old-contact-1
|
||||
"contact-2" new-contact-2
|
||||
"contact-3" contact-3
|
||||
"contact-5" local-contact-5}}}
|
||||
sync-message {:contacts {"contact-1" new-contact-1
|
||||
"contact-2" old-contact-2
|
||||
"contact-4" contact-4
|
||||
"contact-5" remote-contact-5}}
|
||||
expected {"contact-1" new-contact-1
|
||||
"contact-2" new-contact-2
|
||||
"contact-3" contact-3
|
||||
"contact-4" (assoc contact-4
|
||||
:photo-path "generated")
|
||||
"contact-5" local-contact-5}]
|
||||
(testing "not coming from us"
|
||||
(is (not (pairing/handle-sync-installation cofx sync-message "not-us"))))
|
||||
(testing "coming from us"
|
||||
(is (= expected (get-in
|
||||
(pairing/handle-sync-installation cofx sync-message "us")
|
||||
[:db :contacts/contacts]))))))
|
||||
(testing "syncing account"
|
||||
(let [old-account {:name "old-name"
|
||||
:public-key "us"
|
||||
:photo-path "old-photo-path"
|
||||
:last-updated 0}
|
||||
new-account {:name "new-name"
|
||||
:public-key "us"
|
||||
:photo-path "new-photo-path"
|
||||
:last-updated 1}]
|
||||
(testing "newer update"
|
||||
(let [cofx {:db {:account/account old-account}}
|
||||
sync-message {:account new-account}]
|
||||
(is (= new-account (get-in (pairing/handle-sync-installation cofx sync-message "us")
|
||||
[:db :account/account])))))
|
||||
(testing "older update"
|
||||
(let [cofx {:db {:account/account new-account}}
|
||||
sync-message {:account old-account}]
|
||||
(is (= new-account (get-in (pairing/handle-sync-installation cofx sync-message "us")
|
||||
[:db :account/account])))))))))
|
||||
|
||||
(deftest handle-pair-installation-test
|
||||
(with-redefs [config/pairing-enabled? (constantly true)]
|
||||
|
@ -158,7 +179,10 @@
|
|||
|
||||
(deftest sync-installation-messages-test
|
||||
(testing "it creates a sync installation message"
|
||||
(let [cofx {:db {:account/account {:public-key "us"}
|
||||
(let [cofx {:db {:account/account {:public-key "us"
|
||||
:name "name"
|
||||
:photo-path "photo-path"
|
||||
:last-updated 1}
|
||||
:contacts/contacts {"contact-1" {:name "contact-1"
|
||||
:public-key "contact-1"}
|
||||
"contact-2" {:name "contact-2"
|
||||
|
@ -176,9 +200,13 @@
|
|||
"contact-3" {:name "contact-3"
|
||||
:public-key "contact-3"}
|
||||
"contact-4" {:name "contact-4"
|
||||
:public-key "contact-4"}})
|
||||
:public-key "contact-4"}}
|
||||
nil)
|
||||
(transport.pairing/SyncInstallation. {"contact-5" {:name "contact-5"
|
||||
:public-key "contact-5"}})]]
|
||||
:public-key "contact-5"}} nil)
|
||||
(transport.pairing/SyncInstallation. {} {:photo-path "photo-path"
|
||||
:name "name"
|
||||
:last-updated 1})]]
|
||||
(is (= expected (pairing/sync-installation-messages cofx))))))
|
||||
|
||||
(deftest handle-bundles-added-test
|
||||
|
|
Loading…
Reference in New Issue