Faster seen marking
Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
parent
952b01e9e1
commit
4ba78de407
|
@ -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)]}))))
|
||||
|
|
|
@ -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]}]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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?))
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}])
|
||||
|
|
|
@ -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))
|
|
@ -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"))))
|
|
@ -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))))
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue