Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features/keep contacts in sync #6697

Merged
merged 1 commit into from
Nov 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions resources/icons/desktop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions resources/icons/mobile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 8 additions & 4 deletions src/status_im/chat/models/message.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
(and (= constants/content-type-text content-type) (not emoji?))
(update :content message-content/enrich-content))))

(defn system-message? [{:keys [message-type]}]
(= :system-message message-type))

(fx/defn re-index-message-groups
"Relative datemarks of message groups can get obsolete with passing time,
this function re-indexes them for given chat"
Expand Down Expand Up @@ -83,9 +86,9 @@
status)
:data-store/tx [(user-statuses-store/save-status-tx status)]}))

(defn add-outgoing-status [{:keys [from message-type] :as message} current-public-key]
(defn add-outgoing-status [{:keys [from] :as message} current-public-key]
(assoc message :outgoing (and (= from current-public-key)
(not= :system-message message-type))))
(not (system-message? message)))))

(fx/defn add-message
[{:keys [db] :as cofx} batch? {:keys [chat-id message-id clock-value timestamp content from] :as message} current-chat?]
Expand All @@ -105,11 +108,12 @@
;; this will increase last-clock-value twice when sending our own messages
(update-in [:chats chat-id :last-clock-value] (partial utils.clocks/receive clock-value)))
(and (not current-chat?)
(not= from (:current-public-key db)))
(not= from current-public-key))
(update-in [:chats chat-id :unviewed-messages] (fnil conj #{}) message-id))
:data-store/tx [(messages-store/save-message-tx prepared-message)]}
(when (and platform/desktop?
(not batch?))
(not batch?)
(not (system-message? prepared-message)))
(chat-model/update-dock-badge-label))
(when-not batch?
(re-index-message-groups chat-id))
Expand Down
18 changes: 17 additions & 1 deletion src/status_im/data_store/realm/schemas/account/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,19 @@
browser/v8
dapp-permissions/v9])

(def v24 [chat/v8
transport/v7
contact/v3
message/v7
mailserver/v11
mailserver-topic/v1
user-status/v2
membership-update/v1
installation/v2
local-storage/v1
browser/v8
dapp-permissions/v9])

;; put schemas ordered by version
(def schemas [{:schema v1
:schemaVersion 1
Expand Down Expand Up @@ -308,4 +321,7 @@
:migration migrations/v22}
{:schema v23
:schemaVersion 23
:migration migrations/v23}])
:migration migrations/v23}
{:schema v24
:schemaVersion 24
:migration migrations/v24}])
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,6 @@
new-user-status (aget new-user-statuses i)
whisper-identity (aget old-user-status "whisper-identity")]
(aset new-user-status "public-key" whisper-identity)))))

(defn v24 [old-realm new-realm]
(log/debug "migrating v24 account database"))
2 changes: 1 addition & 1 deletion src/status_im/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@
(handlers/register-handler-fx
:pairing.ui/synchronize-installation-pressed
(fn [cofx _]
(pairing/send-installation-message cofx)))
(pairing/send-installation-messages cofx)))

(handlers/register-handler-fx
:pairing.ui/enable-installation-pressed
Expand Down
73 changes: 55 additions & 18 deletions src/status_im/pairing/core.cljs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
(ns status-im.pairing.core
(:require [re-frame.core :as re-frame]
[clojure.string :as string]
[status-im.utils.fx :as fx]
[status-im.utils.config :as config]
[status-im.utils.platform :as utils.platform]
[status-im.accounts.db :as accounts.db]
[status-im.transport.message.protocol :as protocol]
[status-im.data-store.installations :as data-store.installations]
[status-im.native-module.core :as native-module]
[status-im.accounts.db :as accounts.db]
[status-im.utils.identicon :as identicon]
[status-im.data-store.contacts :as data-store.contacts]
[status-im.transport.message.pairing :as transport.pairing]))

(def contact-batch-n 4)

(defn- parse-response [response-js]
(-> response-js
js/JSON.parse
Expand All @@ -21,6 +24,12 @@
device-type utils.platform/os]
(protocol/send (transport.pairing/PairInstallation. installation-id device-type) nil cofx)))

(defn has-paired-installations? [cofx]
(->>
(get-in cofx [:db :pairing/installations])
vals
(some :enabled?)))

(defn send-pair-installation [cofx payload]
(let [{:keys [web3]} (:db cofx)
current-public-key (accounts.db/current-public-key cofx)]
Expand All @@ -29,13 +38,9 @@
:payload payload}}))

(defn merge-contact [local remote]
(let [[old-contact new-contact] (sort-by :last-updated [local remote])]
(let [[old-contact new-contact] (sort-by :last-updated [remote local])]
(-> local
(merge new-contact)
(assoc :photo-path
(or (:photo-path new-contact)
(:photo-path old-contact)
(identicon/identicon (:public-key local))))
(assoc :pending? (boolean
(and (:pending? local true)
(:pending? remote true)))))))
Expand Down Expand Up @@ -66,8 +71,15 @@
(defn sync-installation-messages [{:keys [db]}]
(let [contacts (:contacts/contacts db)]
(map
(fn [[k v]] (transport.pairing/SyncInstallation. {k (dissoc v :photo-path)}))
contacts)))
(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 enable [{:keys [db]} installation-id]
{:db (assoc-in db
Expand Down Expand Up @@ -119,29 +131,54 @@
:pairing/disable-installation
disable-installation!)

(defn send-installation-message [cofx]
;; The message needs to be broken up in chunks as we hit the whisper size limit
(fx/defn send-sync-installation [cofx payload]
(let [{:keys [web3]} (:db cofx)
current-public-key (accounts.db/current-public-key cofx)
sync-messages (sync-installation-messages cofx)]
current-public-key (accounts.db/current-public-key cofx)]

{:shh/send-direct-message
(map #(hash-map :web3 web3
:src current-public-key
:dst current-public-key
:payload %) sync-messages)}))
[{:web3 web3
:src current-public-key
:dst current-public-key
:payload payload}]}))

(fx/defn send-installation-message-fx [cofx payload]
(let [dev-mode? (get-in cofx [:db :account/account :dev-mode?])]
(when (and (config/pairing-enabled? dev-mode?)
(has-paired-installations? cofx))
(protocol/send payload nil cofx))))

(defn send-installation-messages [cofx]
;; The message needs to be broken up in chunks as we hit the whisper size limit
(let [sync-messages (sync-installation-messages cofx)
sync-messages-fx (map send-installation-message-fx sync-messages)]
(apply fx/merge cofx sync-messages-fx)))

(defn ensure-photo-path
"Make sure a photo path is there, generate otherwise"
[contacts]
(reduce-kv (fn [acc k {:keys [public-key photo-path] :as v}]
(assoc acc k
(assoc
v
:photo-path
(if (string/blank? photo-path)
(identicon/identicon public-key)
photo-path))))
{}
contacts))

(defn handle-sync-installation [{:keys [db] :as cofx} {:keys [contacts]} 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) contacts)]
(let [new-contacts (merge-contacts (:contacts/contacts db) (ensure-photo-path contacts))]
{:db (assoc db :contacts/contacts new-contacts)
: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]
(let [dev-mode? (get-in db [:account/account :dev-mode?])]
(when (and (config/pairing-enabled? dev-mode?)
(= sender (get-in cofx [:db :current-public-key]))
(= sender (accounts.db/current-public-key cofx))
(not= (get-in db [:account/account :installation-id]) installation-id))
(let [installation {:installation-id installation-id
:device-type device-type
Expand Down
46 changes: 46 additions & 0 deletions src/status_im/transport/impl/send.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
(ns status-im.transport.impl.send
(:require [status-im.group-chats.core :as group-chats]
[status-im.utils.fx :as fx]
[status-im.pairing.core :as pairing]
[status-im.data-store.transport :as transport-store]
[status-im.transport.db :as transport.db]
[status-im.transport.message.pairing :as transport.pairing]
[status-im.transport.message.contact :as transport.contact]
[status-im.transport.message.group-chat :as transport.group-chat]
[status-im.transport.message.protocol :as protocol]))

Expand All @@ -14,3 +18,45 @@
protocol/StatusMessage
(send [this _ cofx]
(pairing/send-pair-installation cofx this)))

(extend-type transport.pairing/SyncInstallation
protocol/StatusMessage
(send [this _ cofx]
(pairing/send-sync-installation cofx this)))

(extend-type transport.contact/ContactRequest
protocol/StatusMessage
(send [this chat-id cofx]
(let [sync-message (transport.pairing/SyncInstallation.
(select-keys
(get-in cofx [:db :contacts/contacts])
[chat-id]))]
(fx/merge cofx
(protocol/init-chat {:chat-id chat-id
:resend? "contact-request"})
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event [:transport/contact-message-sent chat-id]})
(pairing/send-installation-message-fx sync-message)))))

(extend-type transport.contact/ContactRequestConfirmed
protocol/StatusMessage
(send [this chat-id {:keys [db] :as cofx}]
(let [sync-message (transport.pairing/SyncInstallation.
(select-keys
(get-in cofx [:db :contacts/contacts])
[chat-id]))
success-event [:transport/contact-message-sent chat-id]
chat (get-in db [:transport/chats chat-id])
updated-chat (if chat
(assoc chat :resend? "contact-request-confirmation")
(transport.db/create-chat {:resend? "contact-request-confirmation"}))]
(fx/merge cofx
{:db (assoc-in db
[:transport/chats chat-id] updated-chat)
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]}
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event success-event})
(pairing/send-installation-message-fx sync-message)))))
33 changes: 0 additions & 33 deletions src/status_im/transport/message/contact.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,12 @@

(defrecord ContactRequest [name profile-image address fcm-token]
protocol/StatusMessage
(send [this chat-id {:keys [db random-id-generator] :as cofx}]
(fx/merge cofx
(protocol/init-chat {:chat-id chat-id
:resend? "contact-request"})
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event [:transport/contact-message-sent chat-id]})))
(validate [this]
(when (spec/valid? :message/contact-request this)
this)))

(defrecord ContactRequestConfirmed [name profile-image address fcm-token]
protocol/StatusMessage
(send [this chat-id {:keys [db] :as cofx}]
(let [success-event [:transport/contact-message-sent chat-id]
chat (get-in db [:transport/chats chat-id])
updated-chat (if chat
(assoc chat :resend? "contact-request-confirmation")
(transport.db/create-chat {:resend? "contact-request-confirmation"}))]
(fx/merge cofx
{:db (assoc-in db
[:transport/chats chat-id] updated-chat)
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
:chat updated-chat})]}
(protocol/send-with-pubkey {:chat-id chat-id
:payload this
:success-event success-event}))))
(validate [this]
(when (spec/valid? :message/contact-request-confirmed this)
this)))
Expand Down Expand Up @@ -79,15 +58,3 @@
{:shh/remove-filter {:chat-id chat-id
:filter filter}}))

(defrecord NewContactKey [sym-key topic message]
protocol/StatusMessage
(send
;; no-op, we don't send NewContactKey anymore
[this chat-id cofx])
(receive
;;for compatibility with old clients, we only care about the message within
[this chat-id _ timestamp {:keys [db] :as cofx}]
(protocol/receive message chat-id chat-id timestamp cofx))
(validate [this]
(when (spec/valid? :message/new-contact-key this)
this)))
2 changes: 1 addition & 1 deletion src/status_im/transport/message/protocol.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
StatusMessage
(send [this chat-id cofx]
(let [dev-mode? (get-in cofx [:db :account/account :dev-mode?])
current-public-key (get-in cofx [:db :current-public-key])
current-public-key (accounts.db/current-public-key cofx)
params {:chat-id chat-id
:payload this
:success-event [:transport/message-sent
Expand Down
12 changes: 2 additions & 10 deletions src/status_im/transport/message/transit.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@
;; The tag will determine which reader is used to recreate the clojure record
;; When migrating a particular record, it is important to use a different type and still handle the previous
;; gracefully for compatibility
(deftype NewContactKeyHandler []
Object
(tag [this v] "c1")
(rep [this {:keys [sym-key topic message]}]
#js [sym-key topic message]))

(deftype ContactRequestHandler []
Object
Expand Down Expand Up @@ -102,8 +97,7 @@

(def writer (transit/writer :json
{:handlers
{contact/NewContactKey (NewContactKeyHandler.)
contact/ContactRequest (ContactRequestHandler.)
{contact/ContactRequest (ContactRequestHandler.)
contact/ContactRequestConfirmed (ContactRequestConfirmedHandler.)
contact/ContactUpdate (ContactUpdateHandler.)
protocol/Message (MessageHandler.)
Expand Down Expand Up @@ -145,9 +139,7 @@
;; Here we only need to call the record with the arguments parsed from the clojure datastructures
(def reader (transit/reader :json
{:handlers
{"c1" (fn [[sym-key topic message]]
(contact/NewContactKey. sym-key topic message))
"c2" (fn [[name profile-image address fcm-token]]
{"c2" (fn [[name profile-image address fcm-token]]
(contact/ContactRequest. name profile-image address fcm-token))
"c3" (fn [[name profile-image address fcm-token]]
(contact/ContactRequestConfirmed. name profile-image address fcm-token))
Expand Down
5 changes: 4 additions & 1 deletion src/status_im/ui/components/button/styles.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
{:font-weight :normal
:color colors/white
:padding-horizontal 16
:desktop {:font-size 14
:padding-vertical 10
:letter-spacing 0.5}
:android {:font-size 14
:padding-vertical 10
:letter-spacing 0.5}
Expand Down Expand Up @@ -99,4 +102,4 @@
:flex 0.1
:padding-right 5
:align-items :center
:justify-content :center})
:justify-content :center})
2 changes: 1 addition & 1 deletion src/status_im/ui/components/contact/contact.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
[react/view styles/more-btn
[vector-icons/icon :icons/options {:accessibility-label :options}]]]]))]])

(views/defview toogle-contact-view [{:keys [public-key] :as contact} selected-key on-toggle-handler]
(views/defview toggle-contact-view [{:keys [public-key] :as contact} selected-key on-toggle-handler]
(views/letsubs [checked [selected-key public-key]]
[react/view {:accessibility-label :contact-item}
[list/list-item-with-checkbox
Expand Down
Loading