Faster seen marking

Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
janherich 2018-06-05 18:38:51 +02:00 committed by Julien Eluard
parent 952b01e9e1
commit 4ba78de407
No known key found for this signature in database
GPG Key ID: 6FD7DB5437FCBEF6
15 changed files with 278 additions and 155 deletions

View File

@ -1,5 +1,5 @@
(ns status-im.chat.core
(:require [status-im.data-store.messages :as messages-store]))
(:require [status-im.data-store.user-statuses :as user-statuses-store]))
;; Seen messages
(defn receive-seen
@ -10,17 +10,16 @@
(when-let [seen-messages-ids (-> (get-in db [:chats chat-id :messages])
(select-keys message-ids)
keys)]
(let [new-db (reduce
(fn [new-db message-id]
(assoc-in new-db
[:chats chat-id
:messages message-id
:user-statuses sender]
:seen))
db
seen-messages-ids)]
{:db new-db
:data-store/tx [(messages-store/update-messages-tx
(map #(select-keys (get-in db [:chats chat-id :messages %])
[:message-id :user-statuses])
seen-messages-ids))]}))))
(let [statuses (map (fn [message-id]
{:chat-id chat-id
:message-id message-id
:whisper-identity sender
:status :seen})
seen-messages-ids)]
{:db (reduce (fn [acc {:keys [message-id] :as status}]
(assoc-in acc [:chats chat-id :message-statuses
message-id sender]
status))
db
statuses)
:data-store/tx [(user-statuses-store/save-statuses-tx statuses)]}))))

View File

@ -19,6 +19,7 @@
[status-im.transport.message.v1.group-chat :as group-chat]
[status-im.data-store.chats :as chats-store]
[status-im.data-store.messages :as messages-store]
[status-im.data-store.user-statuses :as user-statuses-store]
[status-im.data-store.contacts :as contacts-store]
[status-im.chat.events.commands :as events.commands]
status-im.chat.events.requests
@ -65,17 +66,22 @@
(handlers/register-handler-fx
:load-more-messages
[(re-frame/inject-cofx :data-store/get-messages)]
(fn [{{:keys [current-chat-id] :as db} :db get-stored-messages :get-stored-messages :as cofx} _]
[(re-frame/inject-cofx :data-store/get-messages)
(re-frame/inject-cofx :data-store/get-user-statuses)]
(fn [{{:keys [current-chat-id] :as db} :db
get-stored-messages :get-stored-messages
get-stored-user-statuses :get-stored-user-statuses :as cofx} _]
(when-not (get-in db [:chats current-chat-id :all-loaded?])
(let [loaded-count (count (get-in db [:chats current-chat-id :messages]))
new-messages (get-stored-messages current-chat-id loaded-count)
indexed-messages (index-messages new-messages)
new-message-ids (keys indexed-messages)]
new-message-ids (keys indexed-messages)
new-statuses (get-stored-user-statuses current-chat-id new-message-ids)]
(handlers-macro/merge-fx
cofx
{:db (-> db
(update-in [:chats current-chat-id :messages] merge indexed-messages)
(update-in [:chats current-chat-id :message-statuses] merge new-statuses)
(update-in [:chats current-chat-id :not-loaded-message-ids]
#(apply disj % new-message-ids))
(update-in [:chats current-chat-id :unviewed-messages]
@ -94,33 +100,37 @@
:update-message-status
[re-frame/trim-v]
(fn [{:keys [db]} [chat-id message-id user-id status]]
(let [msg-path [:chats chat-id :messages message-id]
new-db (update-in db (conj msg-path :user-statuses) assoc user-id status)]
{:db new-db
:data-store/tx [(messages-store/update-message-tx
(-> (get-in new-db msg-path)
(select-keys [:message-id :user-statuses])))]})))
(let [new-status {:chat-id chat-id
:message-id message-id
:whisper-identity user-id
:status status}]
{:db (assoc-in db
[:chats chat-id :message-statuses message-id user-id]
new-status)
:data-store/tx [(user-statuses-store/save-status-tx new-status)]})))
;; Change status of messages which are still in "sending" status to "not-sent"
;; Change status of own messages which are still in "sending" status to "not-sent"
;; (If signal from status-go has not been received)
(handlers/register-handler-fx
:process-pending-messages
[re-frame/trim-v]
(fn [{:keys [db]} []]
(let [pending-messages (->> db
:chats
vals
(mapcat (comp vals :messages))
(filter (fn [{:keys [from user-statuses]}] (= :sending (get user-statuses from)))))
updated-messages (map (fn [{:keys [from] :as message}]
(assoc-in message [:user-statuses from] :not-sent))
pending-messages)]
{:data-store/tx [(messages-store/update-messages-tx updated-messages)]
:db (reduce (fn [m {:keys [chat-id message-id from]}]
(assoc-in m [:chats chat-id :messages message-id
:user-statuses from] :not-sent))
db
pending-messages)})))
(let [me (:current-public-key db)
pending-statuses (->> (vals (:chats db))
(mapcat :message-statuses)
(mapcat (fn [[_ user-id->status]]
(filter (comp (partial = :sending) :status)
(get user-id->status me)))))
updated-statuses (map #(assoc % :status :not-sent) pending-statuses)]
{:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]
:db (reduce
(fn [acc {:keys [chat-id message-id status whisper-identity]}]
(assoc-in acc
[:chats chat-id :message-status message-id
whisper-identity :status]
status))
db
updated-statuses)})))
(defn init-console-chat
[{:keys [db]}]
@ -171,6 +181,7 @@
(re-frame/inject-cofx :get-default-dapps)
(re-frame/inject-cofx :data-store/all-chats)
(re-frame/inject-cofx :data-store/get-messages)
(re-frame/inject-cofx :data-store/get-user-statuses)
(re-frame/inject-cofx :data-store/unviewed-messages)
(re-frame/inject-cofx :data-store/message-ids)
(re-frame/inject-cofx :data-store/get-unanswered-requests)
@ -180,6 +191,7 @@
all-stored-chats
stored-unanswered-requests
get-stored-messages
get-stored-user-statuses
stored-unviewed-messages
stored-message-ids] :as cofx} _]
(let [chat->message-id->request (reduce (fn [acc {:keys [chat-id message-id] :as request}]
@ -187,14 +199,17 @@
{}
stored-unanswered-requests)
chats (reduce (fn [acc {:keys [chat-id] :as chat}]
(let [chat-messages (index-messages (get-stored-messages chat-id))]
(let [chat-messages (index-messages (get-stored-messages chat-id))
message-ids (keys chat-messages)
unviewed-ids (get stored-unviewed-messages chat-id)]
(assoc acc chat-id
(assoc chat
:unviewed-messages (get stored-unviewed-messages chat-id)
:unviewed-messages unviewed-ids
:requests (get chat->message-id->request chat-id)
:messages chat-messages
:message-statuses (get-stored-user-statuses chat-id message-ids)
:not-loaded-message-ids (set/difference (get stored-message-ids chat-id)
(-> chat-messages keys set))))))
(set message-ids))))))
{}
all-stored-chats)]
(handlers-macro/merge-fx cofx
@ -210,48 +225,36 @@
(fn [_ [_ link]]
{:browse link}))
(defn- persist-seen-messages
[chat-id unseen-messages-ids {:keys [db]}]
{:data-store/tx [(messages-store/update-messages-tx
(map (fn [message-id]
(-> (get-in db [:chats chat-id :messages message-id])
(select-keys [:message-id :user-statuses])))
unseen-messages-ids))]})
(defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}]
(when (and (not (get-in db [:chats chat-id :public?]))
(seq message-ids)
(not (models/bot-only-chat? db chat-id)))
(transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
;;TODO (yenda) find a more elegant solution for system messages
;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future
(defn- mark-messages-seen
[chat-id {:keys [db] :as cofx}]
(let [me (:current-public-key db)
messages-path [:chats chat-id :messages]
unseen-messages-ids (into #{}
(comp (filter (fn [[_ {:keys [from user-statuses outgoing]}]]
(and (not outgoing)
(not= constants/system from)
(not= (get user-statuses me) :seen))))
(map first))
(get-in db messages-path))
unseen-system-messages-ids (into #{}
(comp (filter (fn [[_ {:keys [from user-statuses]}]]
(and (= constants/system from)
(not= (get user-statuses me) :seen))))
(map first))
(get-in db messages-path))]
(when (or (seq unseen-messages-ids)
(seq unseen-system-messages-ids))
(handlers-macro/merge-fx cofx
{:db (-> (reduce (fn [new-db message-id]
(assoc-in new-db (into messages-path [message-id :user-statuses me]) :seen))
db
(into unseen-messages-ids unseen-system-messages-ids))
(update-in [:chats chat-id :unviewed-messages] set/difference unseen-messages-ids unseen-system-messages-ids))}
(persist-seen-messages chat-id (into unseen-messages-ids unseen-system-messages-ids))
(send-messages-seen chat-id unseen-messages-ids)))))
(when-let [all-unviewed-ids (seq (get-in db [:chats chat-id :unviewed-messages]))]
(let [me (:current-public-key db)
updated-statuses (keep (fn [message-id]
(some-> db
(get-in [:chats chat-id :message-statuses
message-id me])
(assoc :status :seen)))
all-unviewed-ids)
loaded-unviewed-ids (map :message-id updated-statuses)]
(when (seq loaded-unviewed-ids)
(handlers-macro/merge-fx
cofx
{:db (-> (reduce (fn [acc {:keys [message-id status]}]
(assoc-in acc [:chats chat-id :message-statuses
message-id me :status]
status))
db
updated-statuses)
(update-in [:chats chat-id :unviewed-messages]
#(apply disj % loaded-unviewed-ids)))
:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]}
(send-messages-seen chat-id loaded-unviewed-ids))))))
(defn- fire-off-chat-loaded-event
[chat-id {:keys [db]}]

View File

@ -44,8 +44,21 @@
;; regular non command message, we can add it right away
(message-model/receive message cofx))))
(defn- filter-messages [messages cofx]
(:accumulated (reduce (fn [{:keys [seen-ids] :as acc}
{:keys [message-id] :as message}]
(if (and (message-model/add-to-chat? cofx message)
(not (seen-ids message-id)))
(-> acc
(update :seen-ids conj message-id)
(update :accumulated conj message))
acc))
{:seen-ids #{}
:accumulated []}
messages)))
(defn add-messages [messages {:keys [db] :as cofx}]
(let [messages-to-add (filter (partial message-model/add-to-chat? cofx) messages)
(let [messages-to-add (filter-messages messages cofx)
plain-messages (remove (comp :command :content) messages-to-add)
command-messages (filter (comp :command :content) messages-to-add)]
(handlers-macro/merge-effects (message-model/receive-many plain-messages cofx)

View File

@ -13,7 +13,8 @@
[status-im.transport.utils :as transport.utils]
[status-im.transport.message.core :as transport]
[status-im.transport.message.v1.protocol :as protocol]
[status-im.data-store.messages :as messages-store]))
[status-im.data-store.messages :as messages-store]
[status-im.data-store.user-statuses :as user-statuses-store]))
(def receive-interceptors
[(re-frame/inject-cofx :random-id)
@ -85,6 +86,18 @@
(group-by (comp time/day-relative :timestamp)
(filter :show? messages)))})
(defn- add-own-status
[chat-id message-id status {:keys [db]}]
(let [me (:current-public-key db)
status {:chat-id chat-id
:message-id message-id
:whisper-identity me
:status status}]
{:db (assoc-in db
[:chats chat-id :message-statuses message-id me]
status)
:data-store/tx [(user-statuses-store/save-status-tx status)]}))
(defn- add-message
[batch? {:keys [chat-id message-id clock-value content] :as message} current-chat? {:keys [db] :as cofx}]
(let [prepared-message (prepare-message message chat-id current-chat?)]
@ -114,25 +127,20 @@
[batch?
{:keys [from message-id chat-id content content-type timestamp clock-value to-clock-value js-obj] :as message}
{:keys [db now] :as cofx}]
(let [{:keys [web3
current-chat-id
view-id
access-scope->commands-responses]
:contacts/keys [contacts]} db
{:keys [public-key] :as current-account} (:account/account db)
current-chat? (and (= :chat view-id) (= current-chat-id chat-id))
(let [{:keys [web3 current-chat-id view-id access-scope->commands-responses]
:contacts/keys [contacts]} db
current-account (:account/account db)
current-chat? (and (= :chat view-id) (= current-chat-id chat-id))
{:keys [last-clock-value
public?] :as chat} (get-in db [:chats chat-id])
request-command (:request-command content)
command-request? (and (= content-type constants/content-type-command-request)
request-command)
add-message-fn (if batch? add-batch-message add-single-message)]
public?] :as chat} (get-in db [:chats chat-id])
request-command (:request-command content)
command-request? (and (= content-type constants/content-type-command-request)
request-command)
add-message-fn (if batch? add-batch-message add-single-message)]
(handlers-macro/merge-fx cofx
{:confirm-messages-processed [{:web3 web3
:js-obj js-obj}]}
(add-message-fn (cond-> message
public-key
(assoc :user-statuses {public-key (if current-chat? :seen :received)})
(not clock-value)
(assoc :clock-value (utils.clocks/send last-clock-value)) ; TODO (cammeelos): for backward compatibility, we use received time to be removed when not an issue anymore
command-request?
@ -140,9 +148,9 @@
(lookup-response-ref access-scope->commands-responses
current-account chat contacts request-command)))
current-chat?)
(add-own-status chat-id message-id (if current-chat? :seen :received))
(requests-events/add-request chat-id message-id)
(send-message-seen chat-id message-id (and public-key
(not public?)
(send-message-seen chat-id message-id (and (not public?)
current-chat?
(not (chat-model/bot-only-chat? db chat-id))
(not (= constants/system from)))))))
@ -206,9 +214,6 @@
(get not-loaded-message-ids message-id)
(>= deleted-at-clock-value clock-value))))))
(defn message-seen-by? [message user-pk]
(= :seen (get-in message [:user-statuses user-pk])))
;;;; Send message
(def send-interceptors
@ -278,8 +283,7 @@
:outgoing true
:timestamp now
:clock-value (utils.clocks/send last-clock-value)
:show? true
:user-statuses {identity :sending}}
:show? true}
chat))
(def ^:private transport-keys [:content :content-type :message-type :clock-value :timestamp])
@ -292,6 +296,7 @@
(chat-model/upsert-chat {:chat-id chat-id
:timestamp now})
(add-single-message message-with-id true)
(add-own-status chat-id message-id :sending)
(send chat-id message-id send-record))))
(defn send-push-notification [fcm-token status cofx]
@ -300,10 +305,14 @@
:payload {:title "Status" :body "You have a new message"}
:tokens [fcm-token]}}))
(defn update-message-status [{:keys [chat-id message-id from] :as message} status {:keys [db]}]
(let [updated-message (assoc-in message [:user-statuses from] status)]
{:db (assoc-in db [:chats chat-id :messages message-id] updated-message)
:data-store/tx [(messages-store/update-message-tx updated-message)]}))
(defn update-message-status [{:keys [chat-id message-id from]} status {:keys [db]}]
(let [updated-status (-> db
(get-in [:chats chat-id :message-statuses message-id from])
(assoc :status status))]
{:db (assoc-in db
[:chats chat-id :message-statuses message-id from]
updated-status)
:data-store/tx [(user-statuses-store/save-status-tx updated-status)]}))
(defn resend-message [chat-id message-id cofx]
(let [message (get-in cofx [:db :chats chat-id :messages message-id])

View File

@ -16,6 +16,7 @@
(s/def :chat/public-group-topic-error (s/nilable string?))
(s/def :chat/messages (s/nilable map?)) ; messages indexed by message-id
(s/def :chat/message-groups (s/nilable map?)) ; grouped/sorted messages
(s/def :chat/message-statuses (s/nilable map?)) ; message/user statuses indexed by two level index
(s/def :chat/not-loaded-message-ids (s/nilable set?)) ; set of message-ids not yet fully loaded from persisted state
(s/def :chat/last-clock-value (s/nilable number?)) ; last logical clock value of messages in chat
(s/def :chat/loaded-chats (s/nilable seq?))

View File

@ -124,6 +124,12 @@
(fn [{:keys [message-groups]}]
(or message-groups {})))
(reg-sub
:get-current-chat-message-statuses
:<- [:get-current-chat]
(fn [{:keys [message-statuses]}]
(or message-statuses {})))
(defn sort-message-groups
"Sorts message groups according to timestamp of first message in group "
[message-groups messages]
@ -131,16 +137,18 @@
(comp unchecked-negate :timestamp (partial get messages) :message-id first second)
message-groups))
(defn messages-with-datemarks
"Converts message groups into sequence of messages interspersed with datemarks"
[message-groups messages]
(defn messages-with-datemarks-and-statuses
"Converts message groups into sequence of messages interspersed with datemarks,
with correct user statuses associated into message"
[message-groups messages message-statuses]
(mapcat (fn [[datemark message-references]]
(into (list {:value datemark
:type :datemark})
(map (fn [{:keys [message-id timestamp-str]}]
(assoc (get messages message-id)
:datemark datemark
:timestamp-str timestamp-str)))
:timestamp-str timestamp-str
:user-statuses (get message-statuses message-id))))
message-references))
message-groups))
@ -213,9 +221,10 @@
:get-current-chat-messages-stream
:<- [:get-current-chat-messages]
:<- [:get-current-chat-message-groups]
(fn [[messages message-groups]]
:<- [:get-current-chat-message-statuses]
(fn [[messages message-groups message-statuses]]
(-> (sort-message-groups message-groups messages)
(messages-with-datemarks messages)
(messages-with-datemarks-and-statuses messages message-statuses)
messages-stream)))
(reg-sub
@ -391,4 +400,4 @@
:get-chats-unread-messages-number
:<- [:get-active-chats]
(fn [chats _]
(apply + (map #(count (:unviewed-messages %)) (vals chats)))))
(apply + (map (comp count :unviewed-messages) (vals chats)))))

View File

@ -264,11 +264,11 @@
(defview group-message-delivery-status [{:keys [message-id current-public-key user-statuses] :as msg}]
(letsubs [{participants :contacts} [:get-current-chat]
contacts [:get-contacts]]
(let [outgoing-status (or (get user-statuses current-public-key) :sending)
(let [outgoing-status (or (get-in user-statuses [current-public-key :status]) :sending)
delivery-statuses (dissoc user-statuses current-public-key)
delivery-statuses-count (count delivery-statuses)
seen-by-everyone (and (= delivery-statuses-count (count participants))
(every? (comp (partial = :seen) second) delivery-statuses)
(every? (comp (partial = :seen) :status second) delivery-statuses)
:seen-by-everyone)]
(if (or seen-by-everyone (zero? delivery-statuses-count))
[text-status (or seen-by-everyone outgoing-status)]
@ -321,8 +321,8 @@
(defn message-delivery-status
[{:keys [chat-id message-id current-public-key user-statuses content last-outgoing? outgoing message-type] :as message}]
(let [outgoing-status (or (get user-statuses current-public-key) :not-sent)
delivery-status (get user-statuses chat-id)
(let [outgoing-status (or (get-in user-statuses [current-public-key :status]) :not-sent)
delivery-status (get-in user-statuses [chat-id :status])
status (cond (and (= constants/console-chat-id chat-id)
(not (console/commands-with-delivery-status (:command content))))
:seen

View File

@ -12,11 +12,7 @@
type))
(defn- transform-message [{:keys [content-type] :as message}]
(cond-> (-> message
(update :message-type keyword)
(update :user-statuses (partial into {}
(map (fn [[_ {:keys [whisper-identity status]}]]
[whisper-identity (keyword status)])))))
(cond-> (update message :message-type keyword)
(command-type? content-type)
(update :content reader/read-string)))
@ -84,20 +80,8 @@
;; option for command params instead
(update content :params dissoc :password :password-confirmation))))
(defn- prepare-statuses [{:keys [chat-id message-id] :as message}]
(utils/update-if-present message
:user-statuses
(partial map (fn [[whisper-identity status]]
{:status-id (str message-id "-" whisper-identity)
:whisper-identity whisper-identity
:status status
:chat-id chat-id
:message-id message-id}))))
(defn- prepare-message [message]
(-> message
prepare-statuses
(utils/update-if-present :content prepare-content)))
(utils/update-if-present message :content prepare-content))
(defn save-message-tx
"Returns tx function for saving message"
@ -114,19 +98,16 @@
"Returns tx function for deleting message"
[message-id]
(fn [realm]
(when-let [message (core/single
(core/get-by-field realm :message :message-id message-id))]
(core/delete realm message))))
(when-let [message (core/get-by-field realm :message :message-id message-id)]
(core/delete realm message)
(core/delete realm (core/get-by-field realm :user-status :message-id message-id)))))
(defn update-message-tx
"Returns tx function for updating message"
[{:keys [message-id] :as message}]
(fn [realm]
(when-let [{:keys [chat-id] :as loaded}
(some-> (core/get-by-field realm :message :message-id message-id)
(core/single-clj :message))]
(core/create realm :message
(prepare-message (assoc message :chat-id chat-id)) true))))
(when (core/exists? realm :message :message-id message-id)
(core/create realm :message (prepare-message message) true))))
(defn update-messages-tx
"Returns tx function for updating messages"

View File

@ -5,7 +5,8 @@
[status-im.data-store.realm.schemas.account.v3.core :as v3]
[status-im.data-store.realm.schemas.account.v4.core :as v4]
[status-im.data-store.realm.schemas.account.v5.core :as v5]
[status-im.data-store.realm.schemas.account.v6.core :as v6]))
[status-im.data-store.realm.schemas.account.v6.core :as v6]
[status-im.data-store.realm.schemas.account.v7.core :as v7]))
;; TODO(oskarth): Add failing test if directory vXX exists but isn't in schemas.
@ -27,4 +28,7 @@
:migration v5/migration}
{:schema v6/schema
:schemaVersion 6
:migration v6/migration}])
:migration v6/migration}
{:schema v7/schema
:schemaVersion 7
:migration v7/migration}])

View File

@ -0,0 +1,25 @@
(ns status-im.data-store.realm.schemas.account.v7.core
(:require [status-im.data-store.realm.schemas.account.v5.chat :as chat]
[status-im.data-store.realm.schemas.account.v6.transport :as transport]
[status-im.data-store.realm.schemas.account.v1.contact :as contact]
[status-im.data-store.realm.schemas.account.v7.message :as message]
[status-im.data-store.realm.schemas.account.v1.request :as request]
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
[status-im.data-store.realm.schemas.account.v1.local-storage :as local-storage]
[status-im.data-store.realm.schemas.account.v2.mailserver :as mailserver]
[status-im.data-store.realm.schemas.account.v1.browser :as browser]
[taoensso.timbre :as log]))
(def schema [chat/schema
transport/schema
contact/schema
message/schema
request/schema
mailserver/schema
user-status/schema
local-storage/schema
browser/schema])
(defn migration [old-realm new-realm]
(log/debug "migrating v7 account database: " old-realm new-realm)
(message/migration old-realm new-realm))

View File

@ -0,0 +1,33 @@
(ns status-im.data-store.realm.schemas.account.v7.message
(:require [taoensso.timbre :as log]))
(def schema {:name :message
:primaryKey :message-id
:properties {:message-id :string
:from :string
:to {:type :string
:optional true}
:content :string ; TODO make it ArrayBuffer
:content-type :string
:username {:type :string
:optional true}
:timestamp :int
:chat-id {:type :string
:indexed true}
:outgoing :bool
:retry-count {:type :int
:default 0}
:message-type {:type :string
:optional true}
:message-status {:type :string
:optional true}
:clock-value {:type :int
:default 0}
:show? {:type :bool
:default true}}})
(defn migration [old-realm new-realm]
(log/debug "migrating messages schema v7")
(let [messages (.objects new-realm "message")]
(dotimes [i (.-length messages)]
(js-delete (aget messages i) "user-statuses"))))

View File

@ -0,0 +1,50 @@
(ns status-im.data-store.user-statuses
(:require [clojure.string :as string]
[cljs.reader :as reader]
[re-frame.core :as re-frame]
[status-im.data-store.realm.core :as core]))
(defn- in-query [message-ids]
(string/join " or " (map #(str "message-id=\"" % "\"") message-ids)))
(defn- prepare-statuses [statuses]
(reduce (fn [acc {:keys [message-id whisper-identity] :as user-status}]
(assoc-in acc
[message-id whisper-identity]
(-> user-status
(update :status keyword)
(dissoc :status-id))))
{}
statuses))
(defn- get-by-chat-and-messages-ids
[chat-id message-ids]
(-> @core/account-realm
(.objects "user-status")
(.filtered (str "chat-id=\"" chat-id "\""
(when (seq message-ids)
(str " and (" (in-query message-ids) ")"))))
(core/all-clj :user-status)
prepare-statuses))
(re-frame/reg-cofx
:data-store/get-user-statuses
(fn [cofx _]
(assoc cofx :get-stored-user-statuses get-by-chat-and-messages-ids)))
(defn- compute-status-id [{:keys [message-id whisper-identity]}]
(str message-id "-" whisper-identity))
(defn save-status-tx
"Returns tx function for saving message user status"
[user-status]
(fn [realm]
(let [status-id (compute-status-id user-status)]
(core/create realm :user-status (assoc user-status :status-id status-id) true))))
(defn save-statuses-tx
"Returns tx function for saving message user statuses"
[user-statuses]
(fn [realm]
(doseq [user-status user-statuses]
((save-status-tx user-status) realm))))

View File

@ -231,12 +231,12 @@
(remove-hash envelope-hash)
(update-resend-contact-message chat-id)))
(let [message (get-in db [:chats chat-id :messages message-id])
{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])]
(handlers-macro/merge-fx cofx
(remove-hash envelope-hash)
(models.message/update-message-status message status)
(models.message/send-push-notification fcm-token status)))))))
(when-let [message (get-in db [:chats chat-id :messages message-id])]
(let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])]
(handlers-macro/merge-fx cofx
(remove-hash envelope-hash)
(models.message/update-message-status message status)
(models.message/send-push-notification fcm-token status))))))))
(defn- own-info [db]
(let [{:keys [name photo-path address]} (:account/account db)

View File

@ -229,6 +229,7 @@
:chat/public-group-topic-error
:chat/messages
:chat/message-groups
:chat/message-statuses
:chat/not-loaded-message-ids
:chat/last-clock-value
:chat/loaded-chats

View File

@ -78,12 +78,7 @@
(is (nil? (extract-seen
(message/receive
message
(assoc-in db [:db :view-id] :home))))))
(testing "it does not send any when no public key is in account"
(is (nil? (extract-seen
(message/receive
message
(assoc-in db [:db :account/account :public-key] nil))))))))
(assoc-in db [:db :view-id] :home))))))))
(deftest group-messages
(let [cofx {:db {:chats {"chat-id" {:messages {0 {:message-id 0