2016-10-04 11:49:59 +00:00
|
|
|
(ns status-im.data-store.messages
|
2018-12-24 12:12:26 +00:00
|
|
|
(:require [re-frame.core :as re-frame]
|
2018-12-17 07:44:19 +00:00
|
|
|
[clojure.set :as clojure.set]
|
|
|
|
[clojure.string :as string]
|
2017-10-19 13:58:21 +00:00
|
|
|
[status-im.constants :as constants]
|
2018-04-02 16:17:15 +00:00
|
|
|
[status-im.data-store.realm.core :as core]
|
2018-10-23 12:27:24 +00:00
|
|
|
[status-im.utils.core :as utils]
|
2019-05-22 05:50:49 +00:00
|
|
|
[status-im.js-dependencies :as dependencies]
|
|
|
|
[taoensso.timbre :as log]))
|
2018-04-02 16:17:15 +00:00
|
|
|
|
2018-12-24 12:12:26 +00:00
|
|
|
(defn- transform-message [{:keys [content] :as message}]
|
|
|
|
(when-let [parsed-content (utils/safe-read-message-content content)]
|
2018-12-13 08:27:34 +00:00
|
|
|
(-> message
|
|
|
|
(update :message-type keyword)
|
2018-12-24 12:12:26 +00:00
|
|
|
(assoc :content parsed-content))))
|
2016-10-04 11:49:59 +00:00
|
|
|
|
2018-12-17 07:44:19 +00:00
|
|
|
(defn- exclude-messages [query message-ids]
|
|
|
|
(let [string-queries (map #(str "message-id != \"" % "\"") message-ids)]
|
|
|
|
(core/filtered query (string/join " AND " string-queries))))
|
|
|
|
|
2018-05-02 16:44:58 +00:00
|
|
|
(defn- get-by-chat-id
|
2016-10-04 11:49:59 +00:00
|
|
|
([chat-id]
|
2018-12-17 07:44:19 +00:00
|
|
|
(get-by-chat-id chat-id nil))
|
|
|
|
([chat-id {:keys [last-clock-value message-ids]}]
|
|
|
|
(let [messages (cond-> (core/get-by-field @core/account-realm :message :chat-id chat-id)
|
|
|
|
:always (core/multi-field-sorted [["clock-value" true] ["message-id" true]])
|
|
|
|
last-clock-value (core/filtered (str "clock-value <= \"" last-clock-value "\""))
|
|
|
|
(seq message-ids) (exclude-messages message-ids)
|
|
|
|
:always (core/page 0 constants/default-number-of-messages)
|
|
|
|
:always (core/all-clj :message))
|
|
|
|
clock-value (-> messages last :clock-value)
|
|
|
|
new-message-ids (->> messages
|
|
|
|
(filter #(= clock-value (:clock-value %)))
|
|
|
|
(map :message-id)
|
|
|
|
(into #{}))]
|
2018-12-13 08:27:34 +00:00
|
|
|
{:all-loaded? (> constants/default-number-of-messages (count messages))
|
2018-12-17 07:44:19 +00:00
|
|
|
;; We paginate using clock-value + message-id to break ties, we need
|
|
|
|
;; to exclude previously loaded messages with identical clock value
|
|
|
|
;; otherwise we might fetch exactly the same page if all the messages
|
|
|
|
;; in a page have the same clock-value. The initial idea was to use a
|
|
|
|
;; cursor clock-value-message-id but realm does not support </> operators
|
|
|
|
;; on strings
|
|
|
|
:pagination-info {:last-clock-value clock-value
|
|
|
|
:message-ids (if (= clock-value last-clock-value)
|
|
|
|
(clojure.set/union message-ids new-message-ids)
|
|
|
|
new-message-ids)}
|
2018-12-13 08:27:34 +00:00
|
|
|
:messages (keep transform-message messages)})))
|
2018-05-02 16:44:58 +00:00
|
|
|
|
2018-12-01 17:02:15 +00:00
|
|
|
(defn get-message-id-by-old [old-message-id]
|
|
|
|
(when-let
|
|
|
|
[js-message (core/single
|
|
|
|
(core/get-by-field
|
|
|
|
@core/account-realm
|
|
|
|
:message :old-message-id old-message-id))]
|
|
|
|
(aget js-message "message-id")))
|
|
|
|
|
|
|
|
(defn- get-references-by-ids
|
2018-11-21 07:44:31 +00:00
|
|
|
[message-ids]
|
2018-10-09 13:21:25 +00:00
|
|
|
(when (seq message-ids)
|
2018-12-01 17:02:15 +00:00
|
|
|
(keep (fn [{:keys [response-to response-to-v2]}]
|
|
|
|
(when-let [js-message
|
|
|
|
(if response-to-v2
|
|
|
|
(.objectForPrimaryKey @core/account-realm "message" response-to-v2)
|
|
|
|
(core/single (core/get-by-field
|
|
|
|
@core/account-realm
|
|
|
|
:message :old-message-id response-to)))]
|
2018-12-13 08:27:34 +00:00
|
|
|
(when-let [deserialized-message (-> js-message
|
|
|
|
(core/realm-obj->clj :message)
|
|
|
|
transform-message)]
|
|
|
|
[(or response-to-v2 response-to) deserialized-message])))
|
2018-11-21 07:44:31 +00:00
|
|
|
message-ids)))
|
2018-10-09 13:21:25 +00:00
|
|
|
|
2018-05-02 16:44:58 +00:00
|
|
|
(def default-values
|
2018-12-01 17:02:15 +00:00
|
|
|
{:to nil})
|
2016-10-04 11:49:59 +00:00
|
|
|
|
2018-04-02 16:17:15 +00:00
|
|
|
(re-frame/reg-cofx
|
2018-05-07 14:09:06 +00:00
|
|
|
:data-store/get-messages
|
|
|
|
(fn [cofx _]
|
|
|
|
(assoc cofx :get-stored-messages get-by-chat-id)))
|
2018-01-28 11:23:51 +00:00
|
|
|
|
2018-10-23 12:27:24 +00:00
|
|
|
(defn- sha3 [s]
|
2019-05-22 05:50:49 +00:00
|
|
|
(.sha3 (dependencies/web3-prototype) s))
|
2018-10-23 12:27:24 +00:00
|
|
|
|
2018-10-09 13:21:25 +00:00
|
|
|
(re-frame/reg-cofx
|
|
|
|
:data-store/get-referenced-messages
|
|
|
|
(fn [cofx _]
|
2018-12-01 17:02:15 +00:00
|
|
|
(assoc cofx :get-referenced-messages get-references-by-ids)))
|
2016-10-04 11:49:59 +00:00
|
|
|
|
2018-12-20 14:50:02 +00:00
|
|
|
(defn get-user-messages
|
|
|
|
[public-key]
|
|
|
|
(.reduce (core/get-by-field @core/account-realm
|
|
|
|
:message :from public-key)
|
|
|
|
(fn [acc message-object _ _]
|
|
|
|
(conj acc
|
|
|
|
{:message-id (aget message-object "message-id")
|
|
|
|
:chat-id (aget message-object "chat-id")}))
|
|
|
|
[]))
|
|
|
|
|
|
|
|
(re-frame/reg-cofx
|
|
|
|
:data-store/get-user-messages
|
|
|
|
(fn [cofx _]
|
|
|
|
(assoc cofx :get-user-messages get-user-messages)))
|
|
|
|
|
2018-12-09 15:55:28 +00:00
|
|
|
(defn prepare-content [content]
|
2017-12-05 13:03:25 +00:00
|
|
|
(if (string? content)
|
|
|
|
content
|
2018-09-24 16:27:04 +00:00
|
|
|
(pr-str content)))
|
2017-10-27 13:22:53 +00:00
|
|
|
|
2017-12-23 20:27:04 +00:00
|
|
|
(defn- prepare-message [message]
|
2018-06-05 16:38:51 +00:00
|
|
|
(utils/update-if-present message :content prepare-content))
|
2017-12-23 20:27:04 +00:00
|
|
|
|
2018-05-02 16:44:58 +00:00
|
|
|
(defn save-message-tx
|
|
|
|
"Returns tx function for saving message"
|
|
|
|
[{:keys [message-id from] :as message}]
|
|
|
|
(fn [realm]
|
2018-06-19 11:39:59 +00:00
|
|
|
(core/create realm
|
|
|
|
:message
|
|
|
|
(prepare-message (merge default-values
|
|
|
|
message
|
|
|
|
{:from (or from "anonymous")}))
|
|
|
|
true)))
|
2018-05-02 16:44:58 +00:00
|
|
|
|
|
|
|
(defn delete-message-tx
|
|
|
|
"Returns tx function for deleting message"
|
2018-04-23 09:58:56 +00:00
|
|
|
[message-id]
|
2018-05-02 16:44:58 +00:00
|
|
|
(fn [realm]
|
2018-06-05 16:38:51 +00:00
|
|
|
(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)))))
|
2018-04-23 09:58:56 +00:00
|
|
|
|
2018-12-20 14:50:02 +00:00
|
|
|
(defn delete-chat-messages-tx
|
2018-05-02 16:44:58 +00:00
|
|
|
"Returns tx function for deleting messages with user statuses for given chat-id"
|
|
|
|
[chat-id]
|
|
|
|
(fn [realm]
|
|
|
|
(core/delete realm (core/get-by-field realm :message :chat-id chat-id))
|
|
|
|
(core/delete realm (core/get-by-field realm :user-status :chat-id chat-id))))
|
2018-11-14 20:49:18 +00:00
|
|
|
|
|
|
|
(defn message-exists? [message-id]
|
|
|
|
(if @core/account-realm
|
|
|
|
(not (nil? (.objectForPrimaryKey @core/account-realm "message" message-id)))
|
|
|
|
false))
|