mirror of
https://github.com/status-im/status-react.git
synced 2025-01-15 05:24:37 +00:00
Improve chat loading performance
This commit does a few things: Move collections top level Move `messages`,`message-lists`,`pagination-info` from nested in `chats` to top level at the db. The reason for this change is that if any of the `messages` fields change, any `sub` that relies on `chat` will be recomputed, which is unnecessary. Move chat-name to events `chat-name` was computed dynamically, while it is now only calculated when loading chat the first time around. Remove `enrich-chats` Enrich chats was doing a lot of work, and many subscriptions were relying on it. Not all the computations were necessary, for example it would always calculate the name of who invited the user to a group chat, regardless of whether it was actually used in the view. This commit changes that behavior so that we use smaller subscriptions to calculate such fields. In general we should move computations to events, if that's not desirable (there are some cases where we might not want to do that), we should have "bottom/leaf heavy" subscriptions as opposed to "top heavy", especially if they are to be shared, so only when (and if) we load that particular view, the subscription is triggered, while others can be re-used. I have compared performance with current release, and there's a noticeable difference. Opening a chat is faster (messages are loaded faster), and clicking on the home view on a chat is more responsing (the animation on-press is much quicker).
This commit is contained in:
parent
5f7c795567
commit
f69ae44d50
@ -1,69 +1,11 @@
|
|||||||
(ns status-im.chat.db
|
(ns status-im.chat.db
|
||||||
(:require [clojure.set :as clojure.set]
|
(:require [clojure.string :as clojure.string]
|
||||||
[clojure.string :as clojure.string]
|
[status-im.mailserver.constants :as mailserver.constants]))
|
||||||
[status-im.group-chats.db :as group-chats.db]
|
|
||||||
[status-im.mailserver.constants :as mailserver.constants]
|
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im.utils.identicon :as identicon]
|
|
||||||
[status-im.utils.gfycat.core :as gfycat]))
|
|
||||||
|
|
||||||
(defn group-chat-name
|
(defn group-chat-name
|
||||||
[{:keys [public? name]}]
|
[{:keys [public? name]}]
|
||||||
(str (when public? "#") name))
|
(str (when public? "#") name))
|
||||||
|
|
||||||
(defn enrich-active-chat
|
|
||||||
[contacts {:keys [chat-id
|
|
||||||
identicon
|
|
||||||
alias
|
|
||||||
group-chat] :as chat} current-public-key]
|
|
||||||
(if group-chat
|
|
||||||
(let [pending-invite-inviter-name
|
|
||||||
(group-chats.db/get-pending-invite-inviter-name contacts
|
|
||||||
chat
|
|
||||||
current-public-key)
|
|
||||||
inviter-name
|
|
||||||
(group-chats.db/get-inviter-name contacts
|
|
||||||
chat
|
|
||||||
current-public-key)]
|
|
||||||
(cond-> chat
|
|
||||||
pending-invite-inviter-name
|
|
||||||
(assoc :pending-invite-inviter-name pending-invite-inviter-name)
|
|
||||||
inviter-name
|
|
||||||
(assoc :inviter-name inviter-name)
|
|
||||||
:always
|
|
||||||
(assoc :chat-name (group-chat-name chat))))
|
|
||||||
(let [photo (if (seq identicon)
|
|
||||||
identicon
|
|
||||||
(identicon/identicon chat-id))
|
|
||||||
alias (if (seq alias)
|
|
||||||
alias
|
|
||||||
(gfycat/generate-gfy chat-id))
|
|
||||||
{contact-name :name :as contact}
|
|
||||||
(get contacts chat-id
|
|
||||||
{:public-key chat-id
|
|
||||||
:identicon photo
|
|
||||||
:alias alias
|
|
||||||
:name alias
|
|
||||||
:system-tags #{}})]
|
|
||||||
(-> chat
|
|
||||||
(assoc :contact contact
|
|
||||||
:chat-name (multiaccounts/displayed-name contact)
|
|
||||||
:name contact-name
|
|
||||||
:identicon photo
|
|
||||||
:alias alias)
|
|
||||||
(update :tags clojure.set/union (:tags contact))))))
|
|
||||||
|
|
||||||
(defn active-chats
|
|
||||||
[contacts chats {:keys [public-key]}]
|
|
||||||
(reduce-kv (fn [acc chat-id {:keys [is-active] :as chat}]
|
|
||||||
(if is-active
|
|
||||||
(assoc acc
|
|
||||||
chat-id
|
|
||||||
(enrich-active-chat contacts chat public-key))
|
|
||||||
acc))
|
|
||||||
{}
|
|
||||||
chats))
|
|
||||||
|
|
||||||
(defn datemark? [{:keys [type]}]
|
(defn datemark? [{:keys [type]}]
|
||||||
(= type :datemark))
|
(= type :datemark))
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
(ns status-im.chat.db-test
|
(ns status-im.chat.db-test
|
||||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||||
[status-im.utils.gfycat.core :as gfycat]
|
|
||||||
[status-im.utils.identicon :as identicon]
|
|
||||||
[status-im.chat.db :as db]))
|
[status-im.chat.db :as db]))
|
||||||
|
|
||||||
(deftest group-chat-name
|
(deftest group-chat-name
|
||||||
@ -41,18 +39,6 @@
|
|||||||
(is (= {:type :datemark
|
(is (= {:type :datemark
|
||||||
:value "Dec 31, 1999"} d2)))))
|
:value "Dec 31, 1999"} d2)))))
|
||||||
|
|
||||||
(deftest active-chats-test
|
|
||||||
(with-redefs [gfycat/generate-gfy (constantly "generated")
|
|
||||||
identicon/identicon (constantly "generated")]
|
|
||||||
(let [active-chat-1 {:is-active true :chat-id "1"}
|
|
||||||
active-chat-2 {:is-active true :chat-id "2"}
|
|
||||||
chats {"1" active-chat-1
|
|
||||||
"2" active-chat-2
|
|
||||||
"3" {:is-active false :chat-id "3"}}]
|
|
||||||
(testing "it returns only chats with is-active"
|
|
||||||
(is (= #{"1" "2"}
|
|
||||||
(set (keys (db/active-chats {} chats {})))))))))
|
|
||||||
|
|
||||||
(deftest add-gaps
|
(deftest add-gaps
|
||||||
(testing "empty state"
|
(testing "empty state"
|
||||||
(is (empty?
|
(is (empty?
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
[status-im.transport.filters.core :as transport.filters]
|
[status-im.transport.filters.core :as transport.filters]
|
||||||
[status-im.contact.core :as contact.core]
|
[status-im.contact.core :as contact.core]
|
||||||
[status-im.waku.core :as waku]
|
[status-im.waku.core :as waku]
|
||||||
[status-im.contact.db :as contact.db]
|
|
||||||
[status-im.data-store.chats :as chats-store]
|
[status-im.data-store.chats :as chats-store]
|
||||||
[status-im.data-store.messages :as messages-store]
|
[status-im.data-store.messages :as messages-store]
|
||||||
[status-im.ethereum.json-rpc :as json-rpc]
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
@ -92,8 +91,7 @@
|
|||||||
:is-active true
|
:is-active true
|
||||||
:timestamp now
|
:timestamp now
|
||||||
:contacts #{chat-id}
|
:contacts #{chat-id}
|
||||||
:last-clock-value 0
|
:last-clock-value 0}))
|
||||||
:messages {}}))
|
|
||||||
|
|
||||||
(fx/defn ensure-chat
|
(fx/defn ensure-chat
|
||||||
"Add chat to db and update"
|
"Add chat to db and update"
|
||||||
@ -165,6 +163,7 @@
|
|||||||
{:chat-id topic
|
{:chat-id topic
|
||||||
:is-active true
|
:is-active true
|
||||||
:name topic
|
:name topic
|
||||||
|
:chat-name (str "#" topic)
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:contacts #{}
|
:contacts #{}
|
||||||
:public? true
|
:public? true
|
||||||
@ -175,20 +174,20 @@
|
|||||||
(fx/defn clear-history
|
(fx/defn clear-history
|
||||||
"Clears history of the particular chat"
|
"Clears history of the particular chat"
|
||||||
[{:keys [db] :as cofx} chat-id]
|
[{:keys [db] :as cofx} chat-id]
|
||||||
(let [{:keys [messages
|
(let [{:keys [last-message
|
||||||
last-message
|
|
||||||
deleted-at-clock-value]} (get-in db [:chats chat-id])
|
deleted-at-clock-value]} (get-in db [:chats chat-id])
|
||||||
last-message-clock-value (or (:clock-value last-message)
|
last-message-clock-value (or (:clock-value last-message)
|
||||||
deleted-at-clock-value
|
deleted-at-clock-value
|
||||||
(utils.clocks/send 0))]
|
(utils.clocks/send 0))]
|
||||||
(fx/merge
|
(fx/merge
|
||||||
cofx
|
cofx
|
||||||
{:db (update-in db [:chats chat-id] merge
|
{:db (-> db
|
||||||
{:messages {}
|
(assoc-in [:messages chat-id] {})
|
||||||
:message-list nil
|
(update-in [:message-lists] dissoc chat-id)
|
||||||
:last-message nil
|
(update-in [:chats chat-id] merge
|
||||||
|
{:last-message nil
|
||||||
:unviewed-messages-count 0
|
:unviewed-messages-count 0
|
||||||
:deleted-at-clock-value last-message-clock-value})}
|
:deleted-at-clock-value last-message-clock-value}))}
|
||||||
(messages-store/delete-messages-by-chat-id chat-id)
|
(messages-store/delete-messages-by-chat-id chat-id)
|
||||||
#(chats-store/save-chat % (get-in % [:db :chats chat-id])))))
|
#(chats-store/save-chat % (get-in % [:db :chats chat-id])))))
|
||||||
|
|
||||||
@ -218,13 +217,9 @@
|
|||||||
{:db
|
{:db
|
||||||
(-> db
|
(-> db
|
||||||
(dissoc :loaded-chat-id)
|
(dissoc :loaded-chat-id)
|
||||||
(update-in [:chats current-chat-id]
|
(update :messages dissoc current-chat-id)
|
||||||
assoc
|
(update :message-lists dissoc current-chat-id)
|
||||||
:all-loaded? false
|
(update :pagination-info dissoc current-chat-id))}))
|
||||||
:cursor nil
|
|
||||||
:messages-initialized? false
|
|
||||||
:messages {}
|
|
||||||
:message-list nil))}))
|
|
||||||
|
|
||||||
(fx/defn preload-chat-data
|
(fx/defn preload-chat-data
|
||||||
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
|
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
|
||||||
@ -241,8 +236,6 @@
|
|||||||
(transport.filters/load-chat chat-id))
|
(transport.filters/load-chat chat-id))
|
||||||
(when platform/desktop?
|
(when platform/desktop?
|
||||||
(message-seen/mark-messages-seen chat-id))
|
(message-seen/mark-messages-seen chat-id))
|
||||||
(when (and (one-to-one-chat? cofx chat-id) (not (contact.db/contact-exists? db chat-id)))
|
|
||||||
(contact.core/create-contact chat-id))
|
|
||||||
(loading/load-messages))))
|
(loading/load-messages))))
|
||||||
|
|
||||||
(fx/defn navigate-to-chat
|
(fx/defn navigate-to-chat
|
||||||
|
@ -24,10 +24,7 @@
|
|||||||
[{:keys [db] :as cofx} new-chats]
|
[{:keys [db] :as cofx} new-chats]
|
||||||
(let [old-chats (:chats db)
|
(let [old-chats (:chats db)
|
||||||
chats (reduce (fn [acc {:keys [chat-id] :as chat}]
|
chats (reduce (fn [acc {:keys [chat-id] :as chat}]
|
||||||
(assoc acc chat-id
|
(assoc acc chat-id chat))
|
||||||
(assoc chat
|
|
||||||
:messages-initialized? false
|
|
||||||
:messages {})))
|
|
||||||
{}
|
{}
|
||||||
new-chats)
|
new-chats)
|
||||||
chats (merge old-chats chats)]
|
chats (merge old-chats chats)]
|
||||||
@ -52,12 +49,11 @@
|
|||||||
acc))
|
acc))
|
||||||
{}
|
{}
|
||||||
(get-in db [:chats chat-id :messages]))]
|
(get-in db [:chats chat-id :messages]))]
|
||||||
{:db (update-in db [:chats chat-id]
|
{:db (-> db
|
||||||
assoc
|
(assoc-in [:messages chat-id] new-messages)
|
||||||
:messages new-messages
|
(assoc-in [:pagination-info chat-id] {:all-loaded? false
|
||||||
:all-loaded? false
|
:cursor (clock-value->cursor last-element-clock-value)})
|
||||||
:message-list (message-list/add-many nil (vals new-messages))
|
(assoc-in [:message-lists chat-id] (message-list/add-many nil (vals new-messages))))}))))))
|
||||||
:cursor (clock-value->cursor last-element-clock-value))}))))))
|
|
||||||
|
|
||||||
(fx/defn initialize-chats
|
(fx/defn initialize-chats
|
||||||
"Initialize persisted chats on startup"
|
"Initialize persisted chats on startup"
|
||||||
@ -70,7 +66,7 @@
|
|||||||
[{:keys [db]} current-chat-id _ err]
|
[{:keys [db]} current-chat-id _ err]
|
||||||
(log/error "failed loading messages" current-chat-id err)
|
(log/error "failed loading messages" current-chat-id err)
|
||||||
(when current-chat-id
|
(when current-chat-id
|
||||||
{:db (assoc-in db [:chats current-chat-id :loading-messages?] false)}))
|
{:db (assoc-in db [:pagination-info current-chat-id :loading-messages?] false)}))
|
||||||
|
|
||||||
(fx/defn messages-loaded
|
(fx/defn messages-loaded
|
||||||
"Loads more messages for current chat"
|
"Loads more messages for current chat"
|
||||||
@ -81,10 +77,10 @@
|
|||||||
{:keys [cursor messages]}]
|
{:keys [cursor messages]}]
|
||||||
(when-not (or (nil? current-chat-id)
|
(when-not (or (nil? current-chat-id)
|
||||||
(not= chat-id current-chat-id)
|
(not= chat-id current-chat-id)
|
||||||
(and (get-in db [:chats current-chat-id :messages-initialized?])
|
(and (get-in db [:pagination-info current-chat-id :messages-initialized?])
|
||||||
(not= session-id
|
(not= session-id
|
||||||
(get-in db [:chats current-chat-id :messages-initialized?]))))
|
(get-in db [:pagination-info current-chat-id :messages-initialized?]))))
|
||||||
(let [already-loaded-messages (get-in db [:chats current-chat-id :messages])
|
(let [already-loaded-messages (get-in db [:messages current-chat-id])
|
||||||
loaded-unviewed-messages-ids (get-in db [:chats current-chat-id :loaded-unviewed-messages-ids] #{})
|
loaded-unviewed-messages-ids (get-in db [:chats current-chat-id :loaded-unviewed-messages-ids] #{})
|
||||||
;; We remove those messages that are already loaded, as we might get some duplicates
|
;; We remove those messages that are already loaded, as we might get some duplicates
|
||||||
{:keys [all-messages
|
{:keys [all-messages
|
||||||
@ -111,23 +107,23 @@
|
|||||||
messages)]
|
messages)]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc-in [:chats current-chat-id :cursor-clock-value] (when (seq cursor) (cursor->clock-value cursor)))
|
(assoc-in [:pagination-info current-chat-id :cursor-clock-value] (when (seq cursor) (cursor->clock-value cursor)))
|
||||||
(assoc-in [:chats current-chat-id :loaded-unviewed-messages-ids] unviewed-message-ids)
|
(assoc-in [:chats current-chat-id :loaded-unviewed-messages-ids] unviewed-message-ids)
|
||||||
(assoc-in [:chats current-chat-id :loading-messages?] false)
|
(assoc-in [:pagination-info current-chat-id :loading-messages?] false)
|
||||||
(assoc-in [:chats current-chat-id :messages] all-messages)
|
(assoc-in [:messages current-chat-id] all-messages)
|
||||||
(update-in [:chats current-chat-id :message-list] message-list/add-many new-messages)
|
(update-in [:message-lists current-chat-id] message-list/add-many new-messages)
|
||||||
(assoc-in [:chats current-chat-id :cursor] cursor)
|
(assoc-in [:pagination-info current-chat-id :cursor] cursor)
|
||||||
(assoc-in [:chats current-chat-id :all-loaded?]
|
(assoc-in [:pagination-info current-chat-id :all-loaded?]
|
||||||
(empty? cursor)))}
|
(empty? cursor)))}
|
||||||
(message-seen/mark-messages-seen current-chat-id)))))
|
(message-seen/mark-messages-seen current-chat-id)))))
|
||||||
|
|
||||||
(fx/defn load-more-messages
|
(fx/defn load-more-messages
|
||||||
[{:keys [db] :as cofx}]
|
[{:keys [db] :as cofx}]
|
||||||
(when-let [current-chat-id (:current-chat-id db)]
|
(when-let [current-chat-id (:current-chat-id db)]
|
||||||
(when-let [session-id (get-in db [:chats current-chat-id :messages-initialized?])]
|
(when-let [session-id (get-in db [:pagination-info current-chat-id :messages-initialized?])]
|
||||||
(when-not (or (get-in db [:chats current-chat-id :all-loaded?])
|
(when-not (or (get-in db [:pagination-info current-chat-id :all-loaded?])
|
||||||
(get-in db [:chats current-chat-id :loading-messages?]))
|
(get-in db [:pagination-info current-chat-id :loading-messages?]))
|
||||||
(let [cursor (get-in db [:chats current-chat-id :cursor])
|
(let [cursor (get-in db [:pagination-info current-chat-id :cursor])
|
||||||
load-messages-fx (data-store.messages/messages-by-chat-id-rpc
|
load-messages-fx (data-store.messages/messages-by-chat-id-rpc
|
||||||
(waku/enabled? cofx)
|
(waku/enabled? cofx)
|
||||||
current-chat-id
|
current-chat-id
|
||||||
@ -142,7 +138,7 @@
|
|||||||
(fx/defn load-messages
|
(fx/defn load-messages
|
||||||
[{:keys [db now] :as cofx}]
|
[{:keys [db now] :as cofx}]
|
||||||
(when-let [current-chat-id (:current-chat-id db)]
|
(when-let [current-chat-id (:current-chat-id db)]
|
||||||
(if-not (get-in db [:chats current-chat-id :messages-initialized?])
|
(if-not (get-in db [:pagination-info current-chat-id :messages-initialized?])
|
||||||
(do
|
(do
|
||||||
; reset chat first-not-visible-items state
|
; reset chat first-not-visible-items state
|
||||||
(chat.state/reset)
|
(chat.state/reset)
|
||||||
@ -151,7 +147,7 @@
|
|||||||
;; We keep track of whether there's a loaded chat
|
;; We keep track of whether there's a loaded chat
|
||||||
;; which will be reset only if we hit home
|
;; which will be reset only if we hit home
|
||||||
(assoc :loaded-chat-id current-chat-id)
|
(assoc :loaded-chat-id current-chat-id)
|
||||||
(assoc-in [:chats current-chat-id :messages-initialized?] now))}
|
(assoc-in [:pagination-info current-chat-id :messages-initialized?] now))}
|
||||||
(message-seen/mark-messages-seen current-chat-id)
|
(message-seen/mark-messages-seen current-chat-id)
|
||||||
(load-more-messages)))
|
(load-more-messages)))
|
||||||
;; We mark messages as seen in case we received them while on a different tab
|
;; We mark messages as seen in case we received them while on a different tab
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
(fx/defn rebuild-message-list
|
(fx/defn rebuild-message-list
|
||||||
[{:keys [db]} chat-id]
|
[{:keys [db]} chat-id]
|
||||||
{:db (assoc-in db [:chats chat-id :message-list]
|
{:db (assoc-in db [:message-lists chat-id]
|
||||||
(message-list/add-many nil (vals (get-in db [:chats chat-id :messages]))))})
|
(message-list/add-many nil (vals (get-in db [:messages chat-id]))))})
|
||||||
|
|
||||||
(fx/defn hidden-message-marked-as-seen
|
(fx/defn hidden-message-marked-as-seen
|
||||||
{:events [::hidden-message-marked-as-seen]}
|
{:events [::hidden-message-marked-as-seen]}
|
||||||
@ -42,7 +42,7 @@
|
|||||||
"Hide chat message, rebuild message-list"
|
"Hide chat message, rebuild message-list"
|
||||||
[{:keys [db] :as cofx} chat-id {:keys [seen message-id]}]
|
[{:keys [db] :as cofx} chat-id {:keys [seen message-id]}]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (update-in db [:chats chat-id :messages] dissoc message-id)}
|
{:db (update-in db [:messages chat-id] dissoc message-id)}
|
||||||
(data-store.messages/mark-messages-seen chat-id [message-id] #(re-frame/dispatch [::hidden-message-marked-as-seen %1 %2 %3]))
|
(data-store.messages/mark-messages-seen chat-id [message-id] #(re-frame/dispatch [::hidden-message-marked-as-seen %1 %2 %3]))
|
||||||
(rebuild-message-list chat-id)))
|
(rebuild-message-list chat-id)))
|
||||||
|
|
||||||
@ -52,7 +52,7 @@
|
|||||||
:keys [seen-by-user?]}]
|
:keys [seen-by-user?]}]
|
||||||
(let [current-public-key (multiaccounts.model/current-public-key cofx)
|
(let [current-public-key (multiaccounts.model/current-public-key cofx)
|
||||||
message-to-be-removed (when replace
|
message-to-be-removed (when replace
|
||||||
(get-in db [:chats chat-id :messages replace]))
|
(get-in db [:messages chat-id replace]))
|
||||||
prepared-message (prepare-message message seen-by-user?)]
|
prepared-message (prepare-message message seen-by-user?)]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
(when message-to-be-removed
|
(when message-to-be-removed
|
||||||
@ -62,8 +62,8 @@
|
|||||||
;; We should not be always adding to the list, as it does not make sense
|
;; We should not be always adding to the list, as it does not make sense
|
||||||
;; if the chat has not been initialized, but run into
|
;; if the chat has not been initialized, but run into
|
||||||
;; some troubles disabling it, so next time
|
;; some troubles disabling it, so next time
|
||||||
(update-in [:chats chat-id :messages] assoc message-id prepared-message)
|
(update-in [:messages chat-id] assoc message-id prepared-message)
|
||||||
(update-in [:chats chat-id :message-list] message-list/add prepared-message))
|
(update-in [:message-lists chat-id] message-list/add prepared-message))
|
||||||
(and (not seen-by-user?)
|
(and (not seen-by-user?)
|
||||||
(not= from current-public-key))
|
(not= from current-public-key))
|
||||||
(update-in [:chats chat-id :loaded-unviewed-messages-ids]
|
(update-in [:chats chat-id :loaded-unviewed-messages-ids]
|
||||||
@ -94,7 +94,7 @@
|
|||||||
|
|
||||||
(defn- message-loaded?
|
(defn- message-loaded?
|
||||||
[{:keys [db]} {:keys [chat-id message-id]}]
|
[{:keys [db]} {:keys [chat-id message-id]}]
|
||||||
(get-in db [:chats chat-id :messages message-id]))
|
(get-in db [:messages chat-id message-id]))
|
||||||
|
|
||||||
(defn- earlier-than-deleted-at?
|
(defn- earlier-than-deleted-at?
|
||||||
[{:keys [db]} {:keys [chat-id clock-value]}]
|
[{:keys [db]} {:keys [chat-id clock-value]}]
|
||||||
@ -145,7 +145,7 @@
|
|||||||
;; If the message is already loaded, it means it's an update, that
|
;; If the message is already loaded, it means it's an update, that
|
||||||
;; happens when a message that was missing a reply had the reply
|
;; happens when a message that was missing a reply had the reply
|
||||||
;; coming through, in which case we just insert the new message
|
;; coming through, in which case we just insert the new message
|
||||||
{:db (assoc-in db [:chats chat-id :messages message-id] message-with-chat-id)}
|
{:db (assoc-in db [:messages chat-id message-id] message-with-chat-id)}
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
(add-received-message message-with-chat-id)
|
(add-received-message message-with-chat-id)
|
||||||
(update-unviewed-count message-with-chat-id)
|
(update-unviewed-count message-with-chat-id)
|
||||||
@ -202,7 +202,7 @@
|
|||||||
[{:keys [db] :as cofx} chat-id message-id status]
|
[{:keys [db] :as cofx} chat-id message-id status]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (assoc-in db
|
{:db (assoc-in db
|
||||||
[:chats chat-id :messages message-id :outgoing-status]
|
[:messages chat-id message-id :outgoing-status]
|
||||||
status)}
|
status)}
|
||||||
(data-store.messages/update-outgoing-status message-id status)))
|
(data-store.messages/update-outgoing-status message-id status)))
|
||||||
|
|
||||||
@ -219,7 +219,7 @@
|
|||||||
"Deletes chat message, rebuild message-list"
|
"Deletes chat message, rebuild message-list"
|
||||||
[{:keys [db] :as cofx} chat-id message-id]
|
[{:keys [db] :as cofx} chat-id message-id]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (update-in db [:chats chat-id :messages] dissoc message-id)}
|
{:db (update-in db [:messages chat-id] dissoc message-id)}
|
||||||
(data-store.messages/delete-message message-id)
|
(data-store.messages/delete-message message-id)
|
||||||
(rebuild-message-list chat-id)))
|
(rebuild-message-list chat-id)))
|
||||||
|
|
||||||
@ -229,4 +229,4 @@
|
|||||||
|
|
||||||
(fx/defn toggle-expand-message
|
(fx/defn toggle-expand-message
|
||||||
[{:keys [db]} chat-id message-id]
|
[{:keys [db]} chat-id message-id]
|
||||||
{:db (update-in db [:chats chat-id :messages message-id :expanded?] not)})
|
{:db (update-in db [:messages chat-id message-id :expanded?] not)})
|
||||||
|
@ -41,8 +41,7 @@
|
|||||||
(when (seq loaded-unviewed-ids)
|
(when (seq loaded-unviewed-ids)
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (reduce (fn [acc message-id]
|
{:db (reduce (fn [acc message-id]
|
||||||
(assoc-in acc [:chats chat-id :messages
|
(assoc-in acc [:messages chat-id message-id :seen]
|
||||||
message-id :seen]
|
|
||||||
true))
|
true))
|
||||||
db
|
db
|
||||||
loaded-unviewed-ids)}
|
loaded-unviewed-ids)}
|
||||||
|
@ -94,7 +94,8 @@
|
|||||||
:clock-value 1
|
:clock-value 1
|
||||||
:chat-id "a"}))))
|
:chat-id "a"}))))
|
||||||
(testing "it returns true when it's already in the loaded message"
|
(testing "it returns true when it's already in the loaded message"
|
||||||
(is (#'status-im.chat.models.message/message-loaded? {:db {:chats {"a" {:messages {"message-id" {}}}}}}
|
(is (#'status-im.chat.models.message/message-loaded? {:db
|
||||||
|
{:messages {"a" {"message-id" {}}}}}
|
||||||
{:message-id "message-id"
|
{:message-id "message-id"
|
||||||
:from "a"
|
:from "a"
|
||||||
:clock-value 1
|
:clock-value 1
|
||||||
@ -124,7 +125,8 @@
|
|||||||
:view-id :chat
|
:view-id :chat
|
||||||
:loaded-chat-id "chat-id"
|
:loaded-chat-id "chat-id"
|
||||||
:current-chat-id "chat-id"
|
:current-chat-id "chat-id"
|
||||||
:chats {"chat-id" {:messages {}}}}]
|
:messages {"chat-id" {}}
|
||||||
|
:chats {"chat-id" {}}}]
|
||||||
(testing "a message coming from you!"
|
(testing "a message coming from you!"
|
||||||
(let [actual (message/receive-one {:db db}
|
(let [actual (message/receive-one {:db db}
|
||||||
{:from "me"
|
{:from "me"
|
||||||
@ -136,7 +138,7 @@
|
|||||||
:outgoing true
|
:outgoing true
|
||||||
:content "b"
|
:content "b"
|
||||||
:clock-value 1})
|
:clock-value 1})
|
||||||
message (get-in actual [:db :chats "chat-id" :messages "id"])]
|
message (get-in actual [:db :messages "chat-id" "id"])]
|
||||||
(testing "it adds the message"
|
(testing "it adds the message"
|
||||||
(is message))))))
|
(is message))))))
|
||||||
|
|
||||||
@ -170,7 +172,7 @@
|
|||||||
:whisper-timestamp 0
|
:whisper-timestamp 0
|
||||||
:timestamp 0}]
|
:timestamp 0}]
|
||||||
(testing "a valid message"
|
(testing "a valid message"
|
||||||
(is (get-in (message/receive-one cofx valid-message) [:db :chats "chat-id" :messages "1"])))
|
(is (get-in (message/receive-one cofx valid-message) [:db :messages "chat-id" "1"])))
|
||||||
(testing "a message from someone not in the list of participants"
|
(testing "a message from someone not in the list of participants"
|
||||||
(is (not (message/receive-one cofx bad-from-message))))
|
(is (not (message/receive-one cofx bad-from-message))))
|
||||||
(testing "a message with non existing chat-id"
|
(testing "a message with non existing chat-id"
|
||||||
@ -199,7 +201,7 @@
|
|||||||
:whisper-timestamp 0
|
:whisper-timestamp 0
|
||||||
:timestamp 0}]
|
:timestamp 0}]
|
||||||
(testing "a valid message"
|
(testing "a valid message"
|
||||||
(is (get-in (message/receive-one cofx valid-message) [:db :chats "chat-id" :messages "1"])))
|
(is (get-in (message/receive-one cofx valid-message) [:db :messages "chat-id" "1"])))
|
||||||
(testing "a message with non existing chat-id"
|
(testing "a message with non existing chat-id"
|
||||||
(is (not (message/receive-one cofx bad-chat-id-message))))))
|
(is (not (message/receive-one cofx bad-chat-id-message))))))
|
||||||
|
|
||||||
@ -235,16 +237,16 @@
|
|||||||
:whisper-timestamp 0
|
:whisper-timestamp 0
|
||||||
:timestamp 0}]
|
:timestamp 0}]
|
||||||
(testing "a valid message"
|
(testing "a valid message"
|
||||||
(is (get-in (message/receive-one cofx valid-message) [:db :chats "matching" :messages "1"])))
|
(is (get-in (message/receive-one cofx valid-message) [:db :messages "matching" "1"])))
|
||||||
(testing "our own message"
|
(testing "our own message"
|
||||||
(is (get-in (message/receive-one cofx own-message) [:db :chats "matching" :messages "1"])))
|
(is (get-in (message/receive-one cofx own-message) [:db :messages "matching" "1"])))
|
||||||
(testing "a message with non matching chat-id"
|
(testing "a message with non matching chat-id"
|
||||||
(is (not (get-in (message/receive-one cofx bad-chat-id-message) [:db :chats "not-matching" :messages "1"])))))))
|
(is (not (get-in (message/receive-one cofx bad-chat-id-message) [:db :messages "not-matching" "1"])))))))
|
||||||
|
|
||||||
(deftest delete-message
|
(deftest delete-message
|
||||||
(with-redefs [time/day-relative (constantly "day-relative")
|
(with-redefs [time/day-relative (constantly "day-relative")
|
||||||
time/timestamp->time (constantly "timestamp")]
|
time/timestamp->time (constantly "timestamp")]
|
||||||
(let [cofx1 {:db {:chats {"chat-id" {:messages {0 {:message-id 0
|
(let [cofx1 {:db {:messages {"chat-id" {0 {:message-id 0
|
||||||
:content "a"
|
:content "a"
|
||||||
:clock-value 0
|
:clock-value 0
|
||||||
:whisper-timestamp 0
|
:whisper-timestamp 0
|
||||||
@ -253,19 +255,21 @@
|
|||||||
:content "b"
|
:content "b"
|
||||||
:clock-value 1
|
:clock-value 1
|
||||||
:whisper-timestamp 1
|
:whisper-timestamp 1
|
||||||
:timestamp 1}}
|
:timestamp 1}}}
|
||||||
:message-list [{:something :something}]}}}}
|
:message-lists {"chat-id" [{:something :something}]}
|
||||||
cofx2 {:db {:chats {"chat-id" {:messages {0 {:message-id 0
|
:chats {"chat-id" {}}}}
|
||||||
|
cofx2 {:db {:messages {"chat-id" {0 {:message-id 0
|
||||||
:content "a"
|
:content "a"
|
||||||
:clock-value 0
|
:clock-value 0
|
||||||
:whisper-timestamp 1
|
:whisper-timestamp 1
|
||||||
:timestamp 1}}
|
:timestamp 1}}}
|
||||||
:message-list [{:something :something}]}}}}
|
:message-list {"chat-id" [{:something :something}]}
|
||||||
|
:chats {"chat-id" {}}}}
|
||||||
fx1 (message/delete-message cofx1 "chat-id" 1)
|
fx1 (message/delete-message cofx1 "chat-id" 1)
|
||||||
fx2 (message/delete-message cofx2 "chat-id" 0)]
|
fx2 (message/delete-message cofx2 "chat-id" 0)]
|
||||||
(testing "Deleting message deletes it along with all references"
|
(testing "Deleting message deletes it along with all references"
|
||||||
(is (= '(0)
|
(is (= '(0)
|
||||||
(keys (get-in fx1 [:db :chats "chat-id" :messages]))))
|
(keys (get-in fx1 [:db :messages "chat-id"]))))
|
||||||
(is (= [{:one-to-one? false
|
(is (= [{:one-to-one? false
|
||||||
:message-id 0
|
:message-id 0
|
||||||
:whisper-timestamp 0
|
:whisper-timestamp 0
|
||||||
@ -284,8 +288,8 @@
|
|||||||
:display-username? true
|
:display-username? true
|
||||||
:outgoing false}]
|
:outgoing false}]
|
||||||
(models.message-list/->seq
|
(models.message-list/->seq
|
||||||
(get-in fx1 [:db :chats "chat-id" :message-list]))))
|
(get-in fx1 [:db :message-lists "chat-id"]))))
|
||||||
(is (= {}
|
(is (= {}
|
||||||
(get-in fx2 [:db :chats "chat-id" :messages])))
|
(get-in fx2 [:db :messages "chat-id"])))
|
||||||
(is (= nil
|
(is (= nil
|
||||||
(get-in fx2 [:db :chats "chat-id" :message-list])))))))
|
(get-in fx2 [:db :message-lists "chat-id"])))))))
|
||||||
|
@ -65,15 +65,15 @@
|
|||||||
|
|
||||||
(deftest clear-history-test
|
(deftest clear-history-test
|
||||||
(let [chat-id "1"
|
(let [chat-id "1"
|
||||||
cofx {:db {:chats {chat-id {:message-list [{:something "a"}]
|
cofx {:db {:message-lists {chat-id [{:something "a"}]}
|
||||||
:last-message {:clock-value 10}
|
:chats {chat-id {:last-message {:clock-value 10}
|
||||||
:unviewed-messages-count 1}}}}]
|
:unviewed-messages-count 1}}}}]
|
||||||
(testing "it deletes all the messages"
|
(testing "it deletes all the messages"
|
||||||
(let [actual (chat/clear-history cofx chat-id)]
|
(let [actual (chat/clear-history cofx chat-id)]
|
||||||
(is (= {} (get-in actual [:db :chats chat-id :messages])))))
|
(is (= {} (get-in actual [:db :messages chat-id])))))
|
||||||
(testing "it deletes all the message groups"
|
(testing "it deletes all the message groups"
|
||||||
(let [actual (chat/clear-history cofx chat-id)]
|
(let [actual (chat/clear-history cofx chat-id)]
|
||||||
(is (= nil (get-in actual [:db :chats chat-id :message-list])))))
|
(is (= nil (get-in actual [:db :message-lists chat-id])))))
|
||||||
(testing "it deletes unviewed messages set"
|
(testing "it deletes unviewed messages set"
|
||||||
(let [actual (chat/clear-history cofx chat-id)]
|
(let [actual (chat/clear-history cofx chat-id)]
|
||||||
(is (= 0 (get-in actual [:db :chats chat-id :unviewed-messages-count])))))
|
(is (= 0 (get-in actual [:db :chats chat-id :unviewed-messages-count])))))
|
||||||
@ -103,13 +103,13 @@
|
|||||||
|
|
||||||
(deftest remove-chat-test
|
(deftest remove-chat-test
|
||||||
(let [chat-id "1"
|
(let [chat-id "1"
|
||||||
cofx {:db {:chats {chat-id {:last-message {:clock-value 10}
|
cofx {:db {:messages {chat-id {"1" {:clock-value 1}
|
||||||
:messages {"1" {:clock-value 1}
|
|
||||||
"2" {:clock-value 10}
|
"2" {:clock-value 10}
|
||||||
"3" {:clock-value 2}}}}}}]
|
"3" {:clock-value 2}}}
|
||||||
|
:chats {chat-id {:last-message {:clock-value 10}}}}}]
|
||||||
(testing "it deletes all the messages"
|
(testing "it deletes all the messages"
|
||||||
(let [actual (chat/remove-chat cofx chat-id)]
|
(let [actual (chat/remove-chat cofx chat-id)]
|
||||||
(is (= {} (get-in actual [:db :chats chat-id :messages])))))
|
(is (= {} (get-in actual [:db :messages chat-id])))))
|
||||||
(testing "it sets a deleted-at-clock-value equal to the last message clock-value"
|
(testing "it sets a deleted-at-clock-value equal to the last message clock-value"
|
||||||
(let [actual (chat/remove-chat cofx chat-id)]
|
(let [actual (chat/remove-chat cofx chat-id)]
|
||||||
(is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))
|
(is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value])))))
|
||||||
@ -147,9 +147,10 @@
|
|||||||
|
|
||||||
(def test-db
|
(def test-db
|
||||||
{:multiaccount {:public-key "me"}
|
{:multiaccount {:public-key "me"}
|
||||||
|
|
||||||
|
:messages {"status" {"4" {} "5" {} "6" {}}}
|
||||||
:chats {"status" {:public? true
|
:chats {"status" {:public? true
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:messages {"4" {} "5" {} "6" {}}
|
|
||||||
:loaded-unviewed-messages-ids #{"6" "5" "4"}}
|
:loaded-unviewed-messages-ids #{"6" "5" "4"}}
|
||||||
"opened" {:loaded-unviewed-messages-ids #{}}
|
"opened" {:loaded-unviewed-messages-ids #{}}
|
||||||
"1-1" {:loaded-unviewed-messages-ids #{"6" "5" "4"}}}})
|
"1-1" {:loaded-unviewed-messages-ids #{"6" "5" "4"}}}})
|
||||||
|
@ -16,10 +16,16 @@
|
|||||||
group-chat private-group-chat-type
|
group-chat private-group-chat-type
|
||||||
:else one-to-one-chat-type)))
|
:else one-to-one-chat-type)))
|
||||||
|
|
||||||
(defn rpc->type [{:keys [chatType] :as chat}]
|
(defn rpc->type [{:keys [chatType name] :as chat}]
|
||||||
(cond
|
(cond
|
||||||
(= public-chat-type chatType) (assoc chat :public? true :group-chat true)
|
(= public-chat-type chatType) (assoc chat
|
||||||
(= private-group-chat-type chatType) (assoc chat :public? false :group-chat true)
|
:chat-name (str "#" name)
|
||||||
|
:public? true
|
||||||
|
:group-chat true)
|
||||||
|
(= private-group-chat-type chatType) (assoc chat
|
||||||
|
:chat-name name
|
||||||
|
:public? false
|
||||||
|
:group-chat true)
|
||||||
:else (assoc chat :public? false :group-chat false)))
|
:else (assoc chat :public? false :group-chat false)))
|
||||||
|
|
||||||
(defn- marshal-members [{:keys [admins contacts members-joined chatType] :as chat}]
|
(defn- marshal-members [{:keys [admins contacts members-joined chatType] :as chat}]
|
||||||
@ -68,11 +74,10 @@
|
|||||||
:deleted-at-clock-value :deletedAtClockValue
|
:deleted-at-clock-value :deletedAtClockValue
|
||||||
:is-active :active
|
:is-active :active
|
||||||
:last-clock-value :lastClockValue})
|
:last-clock-value :lastClockValue})
|
||||||
(dissoc :message-list :gaps-loaded? :pagination-info
|
(dissoc :public? :group-chat :messages
|
||||||
:public? :group-chat :messages
|
|
||||||
:might-have-join-time-messages?
|
:might-have-join-time-messages?
|
||||||
:loaded-unviewed-messages-ids
|
:loaded-unviewed-messages-ids
|
||||||
:messages-initialized? :contacts :admins :members-joined)))
|
:contacts :admins :members-joined)))
|
||||||
|
|
||||||
(defn <-rpc [chat]
|
(defn <-rpc [chat]
|
||||||
(-> chat
|
(-> chat
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
(deftest ->to-rpc
|
(deftest ->to-rpc
|
||||||
(let [chat {:public? false
|
(let [chat {:public? false
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:message-list []
|
|
||||||
:color "color"
|
:color "color"
|
||||||
:contacts #{"a" "b" "c" "d"}
|
:contacts #{"a" "b" "c" "d"}
|
||||||
:last-clock-value 10
|
:last-clock-value 10
|
||||||
@ -13,15 +12,11 @@
|
|||||||
:members-joined #{"a" "c"}
|
:members-joined #{"a" "c"}
|
||||||
:name "name"
|
:name "name"
|
||||||
:membership-update-events :events
|
:membership-update-events :events
|
||||||
:gaps-loaded? true
|
|
||||||
:unviewed-messages-count 2
|
:unviewed-messages-count 2
|
||||||
:is-active true
|
:is-active true
|
||||||
:messages {}
|
|
||||||
:pagination-info {}
|
|
||||||
:chat-id "chat-id"
|
:chat-id "chat-id"
|
||||||
:loaded-unviewed-messages-ids []
|
:loaded-unviewed-messages-ids []
|
||||||
:timestamp 2
|
:timestamp 2}
|
||||||
:messages-initialized? true}
|
|
||||||
expected-chat {:id "chat-id"
|
expected-chat {:id "chat-id"
|
||||||
:color "color"
|
:color "color"
|
||||||
:name "name"
|
:name "name"
|
||||||
@ -73,6 +68,7 @@
|
|||||||
expected-chat {:public? false
|
expected-chat {:public? false
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:color "color"
|
:color "color"
|
||||||
|
:chat-name "name"
|
||||||
:contacts #{"a" "b" "c" "d"}
|
:contacts #{"a" "b" "c" "d"}
|
||||||
:last-clock-value 10
|
:last-clock-value 10
|
||||||
:last-message nil
|
:last-message nil
|
||||||
|
@ -519,7 +519,7 @@
|
|||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:chat.ui/resend-message
|
:chat.ui/resend-message
|
||||||
(fn [{:keys [db] :as cofx} [_ chat-id message-id]]
|
(fn [{:keys [db] :as cofx} [_ chat-id message-id]]
|
||||||
(let [message (get-in db [:chats chat-id :messages message-id])]
|
(let [message (get-in db [:messages chat-id message-id])]
|
||||||
(fx/merge
|
(fx/merge
|
||||||
cofx
|
cofx
|
||||||
(transport.message/set-message-envelope-hash chat-id message-id (:message-type message) 1)
|
(transport.message/set-message-envelope-hash chat-id message-id (:message-type message) 1)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
(ns status-im.group-chats.db
|
(ns status-im.group-chats.db)
|
||||||
(:require [status-im.multiaccounts.core :as multiaccounts]))
|
|
||||||
|
|
||||||
(def members-added-type 3)
|
(def members-added-type 3)
|
||||||
|
|
||||||
@ -23,21 +22,3 @@
|
|||||||
|
|
||||||
(defn group-chat? [chat]
|
(defn group-chat? [chat]
|
||||||
(and (:group-chat chat) (not (:public? chat))))
|
(and (:group-chat chat) (not (:public? chat))))
|
||||||
|
|
||||||
(defn get-pending-invite-inviter-name
|
|
||||||
"when the chat is a private group chat in which the user has been
|
|
||||||
invited and didn't accept the invitation yet, return inviter-name"
|
|
||||||
[contacts chat my-public-key]
|
|
||||||
(when (and (group-chat? chat)
|
|
||||||
(invited? my-public-key chat)
|
|
||||||
(not (joined? my-public-key chat)))
|
|
||||||
(let [inviter-pk (get-inviter-pk my-public-key chat)]
|
|
||||||
(multiaccounts/displayed-name (or (get contacts inviter-pk) {:public-key inviter-pk})))))
|
|
||||||
|
|
||||||
(defn get-inviter-name
|
|
||||||
"when the chat is a private group chat in which the user has been
|
|
||||||
invited and didn't accept the invitation yet, return inviter-name"
|
|
||||||
[contacts chat my-public-key]
|
|
||||||
(when (group-chat? chat)
|
|
||||||
(let [inviter-pk (get-inviter-pk my-public-key chat)]
|
|
||||||
(multiaccounts/displayed-name (or (get contacts inviter-pk) {:public-key inviter-pk})))))
|
|
||||||
|
@ -1171,7 +1171,7 @@
|
|||||||
{})))
|
{})))
|
||||||
|
|
||||||
(fx/defn load-gaps-fx [{:keys [db] :as cofx} chat-id]
|
(fx/defn load-gaps-fx [{:keys [db] :as cofx} chat-id]
|
||||||
(when-not (get-in db [:chats chat-id :gaps-loaded?])
|
(when-not (get-in db [:gaps-loaded? chat-id])
|
||||||
(let [success-fn #(re-frame/dispatch [::gaps-loaded %1 %2])]
|
(let [success-fn #(re-frame/dispatch [::gaps-loaded %1 %2])]
|
||||||
(data-store.mailservers/load-gaps cofx chat-id success-fn))))
|
(data-store.mailservers/load-gaps cofx chat-id success-fn))))
|
||||||
|
|
||||||
@ -1190,7 +1190,7 @@
|
|||||||
cofx
|
cofx
|
||||||
{:db
|
{:db
|
||||||
(-> db
|
(-> db
|
||||||
(assoc-in [:chats chat-id :gaps-loaded?] true)
|
(assoc-in [:gaps-loaded? chat-id] true)
|
||||||
(assoc-in [:mailserver/gaps chat-id] gaps))}
|
(assoc-in [:mailserver/gaps chat-id] gaps))}
|
||||||
|
|
||||||
(data-store.mailservers/delete-gaps outdated-gaps))))
|
(data-store.mailservers/delete-gaps outdated-gaps))))
|
||||||
|
@ -389,13 +389,11 @@
|
|||||||
{:multiaccount {:public-key "me"}
|
{:multiaccount {:public-key "me"}
|
||||||
:chats
|
:chats
|
||||||
{"chat-id-1" {:is-active true
|
{"chat-id-1" {:is-active true
|
||||||
:messages {}
|
|
||||||
:might-have-join-time-messages? true
|
:might-have-join-time-messages? true
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-1"}
|
:chat-id "chat-id-1"}
|
||||||
"chat-id-2" {:is-active true
|
"chat-id-2" {:is-active true
|
||||||
:messages {}
|
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-2"}}}})
|
:chat-id "chat-id-2"}}}})
|
||||||
@ -405,14 +403,12 @@
|
|||||||
{:multiaccount {:public-key "me"}
|
{:multiaccount {:public-key "me"}
|
||||||
:chats
|
:chats
|
||||||
{"chat-id-1" {:is-active true
|
{"chat-id-1" {:is-active true
|
||||||
:messages {}
|
|
||||||
:join-time-mail-request-id "a"
|
:join-time-mail-request-id "a"
|
||||||
:might-have-join-time-messages? true
|
:might-have-join-time-messages? true
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-1"}
|
:chat-id "chat-id-1"}
|
||||||
"chat-id-2" {:is-active true
|
"chat-id-2" {:is-active true
|
||||||
:messages {}
|
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-2"}}}})
|
:chat-id "chat-id-2"}}}})
|
||||||
@ -422,26 +418,22 @@
|
|||||||
{:multiaccount {:public-key "me"}
|
{:multiaccount {:public-key "me"}
|
||||||
:chats
|
:chats
|
||||||
{"chat-id-1" {:is-active true
|
{"chat-id-1" {:is-active true
|
||||||
:messages {}
|
|
||||||
:join-time-mail-request-id "a"
|
:join-time-mail-request-id "a"
|
||||||
:might-have-join-time-messages? true
|
:might-have-join-time-messages? true
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-1"}
|
:chat-id "chat-id-1"}
|
||||||
"chat-id-2" {:is-active true
|
"chat-id-2" {:is-active true
|
||||||
:messages {}
|
|
||||||
:join-time-mail-request-id "a"
|
:join-time-mail-request-id "a"
|
||||||
:might-have-join-time-messages? true
|
:might-have-join-time-messages? true
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-2"}
|
:chat-id "chat-id-2"}
|
||||||
"chat-id-3" {:is-active true
|
"chat-id-3" {:is-active true
|
||||||
:messages {}
|
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:public? true
|
:public? true
|
||||||
:chat-id "chat-id-3"}
|
:chat-id "chat-id-3"}
|
||||||
"chat-id-4" {:is-active true
|
"chat-id-4" {:is-active true
|
||||||
:messages {}
|
|
||||||
:join-time-mail-request-id "a"
|
:join-time-mail-request-id "a"
|
||||||
:might-have-join-time-messages? true
|
:might-have-join-time-messages? true
|
||||||
:group-chat true
|
:group-chat true
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
[status-im.utils.money :as money]
|
[status-im.utils.money :as money]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.utils.security :as security]
|
[status-im.utils.security :as security]
|
||||||
[status-im.utils.universal-links.core :as links]
|
|
||||||
[status-im.wallet.db :as wallet.db]
|
[status-im.wallet.db :as wallet.db]
|
||||||
[status-im.wallet.utils :as wallet.utils]
|
[status-im.wallet.utils :as wallet.utils]
|
||||||
status-im.ui.screens.keycard.subs
|
status-im.ui.screens.keycard.subs
|
||||||
@ -185,6 +184,10 @@
|
|||||||
|
|
||||||
(reg-root-key-sub :multiaccounts/loading :multiaccounts/loading)
|
(reg-root-key-sub :multiaccounts/loading :multiaccounts/loading)
|
||||||
|
|
||||||
|
(reg-root-key-sub ::messages :messages)
|
||||||
|
(reg-root-key-sub ::message-lists :message-lists)
|
||||||
|
(reg-root-key-sub ::pagination-info :pagination-info)
|
||||||
|
|
||||||
;;GENERAL ==============================================================================================================
|
;;GENERAL ==============================================================================================================
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
@ -450,6 +453,21 @@
|
|||||||
(fn [{:keys [public-key]}]
|
(fn [{:keys [public-key]}]
|
||||||
public-key))
|
public-key))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:multiaccount/preferred-name
|
||||||
|
:<- [:multiaccount]
|
||||||
|
(fn [{:keys [preferred-name]}]
|
||||||
|
preferred-name))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:multiaccount/my-name
|
||||||
|
:<- [:multiaccount/public-key]
|
||||||
|
:<- [:multiaccount/preferred-name]
|
||||||
|
(fn [[identity preferred-name]]
|
||||||
|
(if preferred-name
|
||||||
|
(stateofus/username (str "@" preferred-name))
|
||||||
|
(gfycat/generate-gfy identity))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:multiaccount/default-account
|
:multiaccount/default-account
|
||||||
:<- [:multiaccount/accounts]
|
:<- [:multiaccount/accounts]
|
||||||
@ -608,77 +626,24 @@
|
|||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/active-chats
|
:chats/active-chats
|
||||||
:<- [:contacts/contacts]
|
|
||||||
:<- [::chats]
|
:<- [::chats]
|
||||||
:<- [:multiaccount]
|
(fn [chats]
|
||||||
(fn [[contacts chats multiaccount]]
|
(reduce-kv (fn [acc id {:keys [is-active] :as chat}]
|
||||||
(chat.db/active-chats contacts chats multiaccount)))
|
(if is-active
|
||||||
|
(assoc acc id chat)
|
||||||
|
acc))
|
||||||
|
{}
|
||||||
|
chats)))
|
||||||
|
|
||||||
;; TODO: this is no useful without tribute to talk
|
(re-frame/reg-sub
|
||||||
#_(defn enrich-current-one-to-one-chat
|
::chat
|
||||||
[{:keys [contact] :as current-chat} my-public-key ttt-settings
|
:<- [::chats]
|
||||||
chain-keyword prices currency]
|
(fn [chats [_ chat-id]]
|
||||||
(let [{:keys [tribute-to-talk]} contact
|
(get chats chat-id)))
|
||||||
{:keys [disabled? snt-amount message]} tribute-to-talk
|
|
||||||
whitelisted-by? (whitelist/whitelisted-by? contact)
|
|
||||||
loading? (and (not whitelisted-by?)
|
|
||||||
(not tribute-to-talk))
|
|
||||||
show-input? (or whitelisted-by?
|
|
||||||
disabled?)
|
|
||||||
token (case chain-keyword
|
|
||||||
:mainnet :SNT
|
|
||||||
:STT)
|
|
||||||
tribute-status (if loading?
|
|
||||||
:loading
|
|
||||||
(tribute-to-talk.db/tribute-status contact))
|
|
||||||
tribute-label (tribute-to-talk.db/status-label tribute-status snt-amount)]
|
|
||||||
|
|
||||||
(cond-> (assoc current-chat
|
|
||||||
:tribute-to-talk/tribute-status tribute-status
|
|
||||||
:tribute-to-talk/tribute-label tribute-label)
|
|
||||||
|
|
||||||
(#{:required :pending :paid} tribute-status)
|
|
||||||
(assoc :tribute-to-talk/snt-amount
|
|
||||||
(tribute-to-talk.db/from-wei snt-amount)
|
|
||||||
:tribute-to-talk/message
|
|
||||||
message
|
|
||||||
:tribute-to-talk/fiat-amount (if snt-amount
|
|
||||||
(money/fiat-amount-value
|
|
||||||
snt-amount
|
|
||||||
token
|
|
||||||
(-> currency :code keyword)
|
|
||||||
prices)
|
|
||||||
"0")
|
|
||||||
:tribute-to-talk/fiat-currency (:code currency)
|
|
||||||
:tribute-to-talk/token (str " " (name token)))
|
|
||||||
|
|
||||||
(tribute-to-talk.db/enabled? ttt-settings)
|
|
||||||
(assoc :tribute-to-talk/received? (tribute-to-talk.db/tribute-received?
|
|
||||||
contact))
|
|
||||||
|
|
||||||
(= tribute-status :required)
|
|
||||||
(assoc :tribute-to-talk/on-share-my-profile
|
|
||||||
#(re-frame/dispatch
|
|
||||||
[:profile/share-profile-link my-public-key]))
|
|
||||||
|
|
||||||
show-input?
|
|
||||||
(assoc :show-input? true))))
|
|
||||||
|
|
||||||
(defn enrich-current-chat
|
|
||||||
[{:keys [messages chat-id might-have-join-time-messages?] :as chat} ranges]
|
|
||||||
(assoc chat
|
|
||||||
:range
|
|
||||||
(get ranges chat-id)
|
|
||||||
:intro-status
|
|
||||||
(if might-have-join-time-messages?
|
|
||||||
:loading
|
|
||||||
(if (empty? messages)
|
|
||||||
:empty
|
|
||||||
:messages))))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/current-raw-chat
|
:chats/current-raw-chat
|
||||||
:<- [:chats/active-chats]
|
:<- [::chats]
|
||||||
:<- [:chats/current-chat-id]
|
:<- [:chats/current-chat-id]
|
||||||
(fn [[chats current-chat-id]]
|
(fn [[chats current-chat-id]]
|
||||||
(get chats current-chat-id)))
|
(get chats current-chat-id)))
|
||||||
@ -694,15 +659,10 @@
|
|||||||
:chats/current-chat
|
:chats/current-chat
|
||||||
:<- [:chats/current-raw-chat]
|
:<- [:chats/current-raw-chat]
|
||||||
:<- [:multiaccount/public-key]
|
:<- [:multiaccount/public-key]
|
||||||
:<- [:mailserver/ranges]
|
(fn [[{:keys [group-chat] :as current-chat}
|
||||||
(fn [[{:keys [group-chat chat-id messages] :as current-chat}
|
my-public-key]]
|
||||||
my-public-key ranges]]
|
|
||||||
(when current-chat
|
(when current-chat
|
||||||
(cond-> (enrich-current-chat current-chat ranges)
|
(cond-> current-chat
|
||||||
(empty? messages)
|
|
||||||
(assoc :universal-link
|
|
||||||
(links/generate-link :public-chat :external chat-id))
|
|
||||||
|
|
||||||
(chat.models/public-chat? current-chat)
|
(chat.models/public-chat? current-chat)
|
||||||
(assoc :show-input? true)
|
(assoc :show-input? true)
|
||||||
|
|
||||||
@ -727,17 +687,12 @@
|
|||||||
(fn [current-chat]
|
(fn [current-chat]
|
||||||
(chat.models/public-chat? current-chat)))
|
(chat.models/public-chat? current-chat)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
:chats/current-chat-message
|
|
||||||
:<- [:chats/current-chat]
|
|
||||||
(fn [{:keys [messages]} [_ message-id]]
|
|
||||||
(get messages message-id)))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/current-chat-messages
|
:chats/current-chat-messages
|
||||||
:<- [:chats/current-chat]
|
:<- [::messages]
|
||||||
(fn [{:keys [messages]}]
|
:<- [:chats/current-chat-id]
|
||||||
(or messages {})))
|
(fn [[messages chat-id]]
|
||||||
|
(get messages chat-id {})))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/messages-gaps
|
:chats/messages-gaps
|
||||||
@ -746,6 +701,12 @@
|
|||||||
(fn [[gaps chat-id]]
|
(fn [[gaps chat-id]]
|
||||||
(sort-by :from (vals (get gaps chat-id)))))
|
(sort-by :from (vals (get gaps chat-id)))))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:mailserver/ranges-by-chat-id
|
||||||
|
:<- [:mailserver/ranges]
|
||||||
|
(fn [ranges [_ chat-id]]
|
||||||
|
(get ranges chat-id)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/range
|
:chats/range
|
||||||
:<- [:mailserver/ranges]
|
:<- [:mailserver/ranges]
|
||||||
@ -755,27 +716,23 @@
|
|||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/all-loaded?
|
:chats/all-loaded?
|
||||||
:<- [:chats/current-chat]
|
:<- [::pagination-info]
|
||||||
(fn [chat]
|
:<- [:chats/current-chat-id]
|
||||||
(:all-loaded? chat)))
|
(fn [[pagination-info chat-id]]
|
||||||
|
(get-in pagination-info [chat-id :all-loaded?])))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/public?
|
:chats/public?
|
||||||
:<- [:chats/current-chat]
|
:<- [:chats/current-raw-chat]
|
||||||
(fn [chat]
|
(fn [chat]
|
||||||
(:public? chat)))
|
(:public? chat)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/message-list
|
:chats/message-list
|
||||||
:<- [:chats/current-chat]
|
:<- [::message-lists]
|
||||||
(fn [chat]
|
:<- [:chats/current-chat-id]
|
||||||
(:message-list chat)))
|
(fn [[message-lists chat-id]]
|
||||||
|
(get message-lists chat-id)))
|
||||||
(re-frame/reg-sub
|
|
||||||
:chats/messages
|
|
||||||
:<- [:chats/current-chat]
|
|
||||||
(fn [chat]
|
|
||||||
(:messages chat)))
|
|
||||||
|
|
||||||
(defn hydrate-messages
|
(defn hydrate-messages
|
||||||
"Pull data from messages and add it to the sorted list"
|
"Pull data from messages and add it to the sorted list"
|
||||||
@ -786,10 +743,16 @@
|
|||||||
%)
|
%)
|
||||||
message-list))
|
message-list))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:chats/current-chat-no-messages?
|
||||||
|
:<- [:chats/current-chat-messages]
|
||||||
|
(fn [messages]
|
||||||
|
(empty? messages)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/current-chat-messages-stream
|
:chats/current-chat-messages-stream
|
||||||
:<- [:chats/message-list]
|
:<- [:chats/message-list]
|
||||||
:<- [:chats/messages]
|
:<- [:chats/current-chat-messages]
|
||||||
:<- [:chats/messages-gaps]
|
:<- [:chats/messages-gaps]
|
||||||
:<- [:chats/range]
|
:<- [:chats/range]
|
||||||
:<- [:chats/all-loaded?]
|
:<- [:chats/all-loaded?]
|
||||||
@ -801,17 +764,6 @@
|
|||||||
(hydrate-messages messages)
|
(hydrate-messages messages)
|
||||||
(chat.db/add-gaps messages-gaps range all-loaded? public?))))
|
(chat.db/add-gaps messages-gaps range all-loaded? public?))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
:chats/current-chat-intro-status
|
|
||||||
:<- [:chats/current-chat]
|
|
||||||
:<- [:chats/current-chat-messages]
|
|
||||||
(fn [[{:keys [might-have-join-time-messages?]} messages]]
|
|
||||||
(if might-have-join-time-messages?
|
|
||||||
:loading
|
|
||||||
(if (empty? messages)
|
|
||||||
:empty
|
|
||||||
:messages))))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/photo-path
|
:chats/photo-path
|
||||||
:<- [:contacts/contacts]
|
:<- [:contacts/contacts]
|
||||||
@ -826,9 +778,15 @@
|
|||||||
:chats/unread-messages-number
|
:chats/unread-messages-number
|
||||||
:<- [:chats/active-chats]
|
:<- [:chats/active-chats]
|
||||||
(fn [chats _]
|
(fn [chats _]
|
||||||
(let [grouped-chats (group-by :public? (vals chats))]
|
(reduce-kv (fn [{:keys [public other]} _ {:keys [unviewed-messages-count public?]}]
|
||||||
{:public (apply + (map :unviewed-messages-count (get grouped-chats true)))
|
(if public?
|
||||||
:other (apply + (map :unviewed-messages-count (get grouped-chats false)))})))
|
{:public (+ public unviewed-messages-count)
|
||||||
|
:other other}
|
||||||
|
{:other (+ other unviewed-messages-count)
|
||||||
|
:public public}))
|
||||||
|
{:public 0
|
||||||
|
:other 0}
|
||||||
|
chats)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/cooldown-enabled?
|
:chats/cooldown-enabled?
|
||||||
@ -886,13 +844,13 @@
|
|||||||
(filter-contacts selected-contacts active-contacts)))
|
(filter-contacts selected-contacts active-contacts)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:group-chat/chat-joined?
|
:group-chat/inviter-info
|
||||||
:<- [:multiaccount/public-key]
|
(fn [[_ chat-id] _]
|
||||||
:<- [:chats/active-chats]
|
[(re-frame/subscribe [::chat chat-id])
|
||||||
(fn [[my-public-key chats] [_ chat-id]]
|
(re-frame/subscribe [:multiaccount/public-key])])
|
||||||
(let [current-chat (get chats chat-id)]
|
(fn [[chat my-public-key]]
|
||||||
(and (chat.models/group-chat? current-chat)
|
{:joined? (group-chats.db/joined? my-public-key chat)
|
||||||
(group-chats.db/joined? my-public-key current-chat)))))
|
:inviter-pk (group-chats.db/get-inviter-pk my-public-key chat)}))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/transaction-status
|
:chats/transaction-status
|
||||||
@ -1631,21 +1589,40 @@
|
|||||||
contact.db/public-key->new-contact
|
contact.db/public-key->new-contact
|
||||||
contact.db/enrich-contact))))
|
contact.db/enrich-contact))))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:contacts/contact-by-identity
|
||||||
|
:<- [::contacts]
|
||||||
|
(fn [contacts [_ identity]]
|
||||||
|
(get contacts identity)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:contacts/contact-added?
|
||||||
|
(fn [[_ identity] _]
|
||||||
|
[(re-frame/subscribe [:contacts/contact-by-identity identity])])
|
||||||
|
(fn [[contact] _]
|
||||||
|
(contact.db/added? contact)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:contacts/raw-contact-name-by-identity
|
||||||
|
(fn [[_ identity] _]
|
||||||
|
[(re-frame/subscribe [:contacts/contact-by-identity identity])])
|
||||||
|
(fn [[db-contact] _]
|
||||||
|
(if (and (:ens-verified db-contact) (seq (:name db-contact)))
|
||||||
|
(stateofus/username (str "@" (:name db-contact)))
|
||||||
|
(:alias db-contact))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:contacts/contact-name-by-identity
|
:contacts/contact-name-by-identity
|
||||||
:<- [:contacts/contacts]
|
(fn [[_ identity] _]
|
||||||
:<- [:multiaccount]
|
[(re-frame/subscribe [:contacts/raw-contact-name-by-identity identity])
|
||||||
(fn [[contacts current-multiaccount] [_ identity]]
|
(re-frame/subscribe [:multiaccount])])
|
||||||
|
(fn [[contact-name current-multiaccount] [_ identity]]
|
||||||
(let [me? (= (:public-key current-multiaccount) identity)]
|
(let [me? (= (:public-key current-multiaccount) identity)]
|
||||||
(if me?
|
(if me?
|
||||||
{:ens-name (:preferred-name current-multiaccount)
|
(or (:preferred-name current-multiaccount)
|
||||||
:alias (gfycat/generate-gfy identity)}
|
(gfycat/generate-gfy identity))
|
||||||
(let [contact (or (contacts identity)
|
(or contact-name
|
||||||
(contact.db/public-key->new-contact identity))]
|
(gfycat/generate-gfy identity))))))
|
||||||
{:ens-name (when (:ens-verified contact)
|
|
||||||
(:name contact))
|
|
||||||
:alias (or (:alias contact)
|
|
||||||
(gfycat/generate-gfy identity))})))))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:messages/quote-info
|
:messages/quote-info
|
||||||
@ -1694,17 +1671,6 @@
|
|||||||
(fn [[chat all-contacts] [_ query-fn]]
|
(fn [[chat all-contacts] [_ query-fn]]
|
||||||
(contact.db/query-chat-contacts chat all-contacts query-fn)))
|
(contact.db/query-chat-contacts chat all-contacts query-fn)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
:contacts/chat-photo
|
|
||||||
(fn [[_ chat-id] _]
|
|
||||||
[(re-frame/subscribe [:chats/chat chat-id])
|
|
||||||
(re-frame/subscribe [:contacts/contacts-by-chat filter chat-id])])
|
|
||||||
(fn [[chat contacts] [_ _]]
|
|
||||||
(when (and chat (not (:group-chat chat)))
|
|
||||||
(if (pos? (count contacts))
|
|
||||||
(multiaccounts/displayed-photo (first contacts))
|
|
||||||
(multiaccounts/displayed-photo chat)))))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:contacts/contact-by-address
|
:contacts/contact-by-address
|
||||||
:<- [:contacts/contacts]
|
:<- [:contacts/contacts]
|
||||||
|
@ -60,7 +60,8 @@
|
|||||||
(let [chat-id "chat-id"
|
(let [chat-id "chat-id"
|
||||||
from "from"
|
from "from"
|
||||||
message-id "message-id"
|
message-id "message-id"
|
||||||
initial-cofx {:db {:chats {chat-id {:messages {message-id {:from from}}}}}}]
|
initial-cofx {:db {:messages {chat-id {message-id {:from from}}}
|
||||||
|
:chats {chat-id {}}}}]
|
||||||
|
|
||||||
(testing "a single envelope message"
|
(testing "a single envelope message"
|
||||||
(let [cofx (message/set-message-envelope-hash initial-cofx chat-id message-id :message-type 1)]
|
(let [cofx (message/set-message-envelope-hash initial-cofx chat-id message-id :message-type 1)]
|
||||||
@ -72,12 +73,12 @@
|
|||||||
(is (= :sent
|
(is (= :sent
|
||||||
(get-in
|
(get-in
|
||||||
(message/update-envelope-status cofx message-id :sent)
|
(message/update-envelope-status cofx message-id :sent)
|
||||||
[:db :chats chat-id :messages message-id :outgoing-status]))))
|
[:db :messages chat-id message-id :outgoing-status]))))
|
||||||
(testing "the message is not sent"
|
(testing "the message is not sent"
|
||||||
(is (= :not-sent
|
(is (= :not-sent
|
||||||
(get-in
|
(get-in
|
||||||
(message/update-envelope-status cofx message-id :not-sent)
|
(message/update-envelope-status cofx message-id :not-sent)
|
||||||
[:db :chats chat-id :messages message-id :outgoing-status]))))))
|
[:db :messages chat-id message-id :outgoing-status]))))))
|
||||||
(testing "multi envelope message"
|
(testing "multi envelope message"
|
||||||
(testing "only inserts"
|
(testing "only inserts"
|
||||||
(let [cofx (fx/merge
|
(let [cofx (fx/merge
|
||||||
@ -103,7 +104,7 @@
|
|||||||
(is (= :sent
|
(is (= :sent
|
||||||
(get-in
|
(get-in
|
||||||
cofx
|
cofx
|
||||||
[:db :chats chat-id :messages message-id :outgoing-status]))))))
|
[:db :messages chat-id message-id :outgoing-status]))))))
|
||||||
(testing "order of events is reversed"
|
(testing "order of events is reversed"
|
||||||
(let [cofx (fx/merge
|
(let [cofx (fx/merge
|
||||||
initial-cofx
|
initial-cofx
|
||||||
@ -119,7 +120,7 @@
|
|||||||
(is (= :sent
|
(is (= :sent
|
||||||
(get-in
|
(get-in
|
||||||
cofx
|
cofx
|
||||||
[:db :chats chat-id :messages message-id :outgoing-status]))))))
|
[:db :messages chat-id message-id :outgoing-status]))))))
|
||||||
(testing "message not sent"
|
(testing "message not sent"
|
||||||
(let [cofx (fx/merge
|
(let [cofx (fx/merge
|
||||||
initial-cofx
|
initial-cofx
|
||||||
@ -135,4 +136,4 @@
|
|||||||
(is (= :not-sent
|
(is (= :not-sent
|
||||||
(get-in
|
(get-in
|
||||||
cofx
|
cofx
|
||||||
[:db :chats chat-id :messages message-id :outgoing-status])))))))))
|
[:db :messages chat-id message-id :outgoing-status])))))))))
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
[{:keys [db] :as cofx} message-id status]
|
[{:keys [db] :as cofx} message-id status]
|
||||||
(if-let [{:keys [chat-id]}
|
(if-let [{:keys [chat-id]}
|
||||||
(get-in db [:transport/message-envelopes message-id])]
|
(get-in db [:transport/message-envelopes message-id])]
|
||||||
(when-let [{:keys [from]} (get-in db [:chats chat-id :messages message-id])]
|
(when-let [{:keys [from]} (get-in db [:messages chat-id message-id])]
|
||||||
(check-confirmations cofx status chat-id message-id))
|
(check-confirmations cofx status chat-id message-id))
|
||||||
;; We don't have a message-envelope for this, might be that the confirmation
|
;; We don't have a message-envelope for this, might be that the confirmation
|
||||||
;; came too early
|
;; came too early
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.screens.chat.photos :as photos]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
;;TODO REWORK THIS NAMESPACE
|
|
||||||
|
|
||||||
(defn default-chat-icon [name styles]
|
(defn default-chat-icon [name styles]
|
||||||
(when-not (string/blank? name)
|
(when-not (string/blank? name)
|
||||||
[react/view (:default-chat-icon styles)
|
[react/view (:default-chat-icon styles)
|
||||||
@ -32,15 +30,16 @@
|
|||||||
[react/view online-dot-right]]]])
|
[react/view online-dot-right]]]])
|
||||||
|
|
||||||
(defn chat-icon-view
|
(defn chat-icon-view
|
||||||
[contact group-chat name _online styles]
|
[chat-id group-chat name styles]
|
||||||
[react/view (:container styles)
|
[react/view (:container styles)
|
||||||
(if-not group-chat
|
(if group-chat
|
||||||
[photos/photo (multiaccounts/displayed-photo contact) styles]
|
[default-chat-icon name styles]
|
||||||
[default-chat-icon name styles])])
|
(let [photo-path @(re-frame.core/subscribe [:chats/photo-path chat-id])]
|
||||||
|
[photos/photo photo-path styles]))])
|
||||||
|
|
||||||
(defn chat-icon-view-toolbar
|
(defn chat-icon-view-toolbar
|
||||||
[contact group-chat name color online]
|
[chat-id group-chat name color]
|
||||||
[chat-icon-view contact group-chat name online
|
[chat-icon-view chat-id group-chat name
|
||||||
{:container styles/container-chat-toolbar
|
{:container styles/container-chat-toolbar
|
||||||
:online-view-wrapper styles/online-view-wrapper
|
:online-view-wrapper styles/online-view-wrapper
|
||||||
:online-view styles/online-view
|
:online-view styles/online-view
|
||||||
@ -52,8 +51,8 @@
|
|||||||
:default-chat-icon-text (styles/default-chat-icon-text 36)}])
|
:default-chat-icon-text (styles/default-chat-icon-text 36)}])
|
||||||
|
|
||||||
(defn chat-icon-view-chat-list
|
(defn chat-icon-view-chat-list
|
||||||
[contact group-chat name color online]
|
[chat-id group-chat name color]
|
||||||
[chat-icon-view contact group-chat name online
|
[chat-icon-view chat-id group-chat name
|
||||||
{:container styles/container-chat-list
|
{:container styles/container-chat-list
|
||||||
:online-view-wrapper styles/online-view-wrapper
|
:online-view-wrapper styles/online-view-wrapper
|
||||||
:online-view styles/online-view
|
:online-view styles/online-view
|
||||||
@ -65,8 +64,8 @@
|
|||||||
:default-chat-icon-text (styles/default-chat-icon-text 40)}])
|
:default-chat-icon-text (styles/default-chat-icon-text 40)}])
|
||||||
|
|
||||||
(defn chat-icon-view-chat-sheet
|
(defn chat-icon-view-chat-sheet
|
||||||
[contact group-chat name color online]
|
[chat-id group-chat name color]
|
||||||
[chat-icon-view contact group-chat name online
|
[chat-icon-view chat-id group-chat name
|
||||||
{:container styles/container-chat-list
|
{:container styles/container-chat-list
|
||||||
:online-view-wrapper styles/online-view-wrapper
|
:online-view-wrapper styles/online-view-wrapper
|
||||||
:online-view styles/online-view
|
:online-view styles/online-view
|
||||||
@ -116,11 +115,12 @@
|
|||||||
:default-chat-icon (styles/default-chat-icon-profile colors/default-chat-color size)
|
:default-chat-icon (styles/default-chat-icon-profile colors/default-chat-color size)
|
||||||
:default-chat-icon-text (styles/default-chat-icon-text size)}])
|
:default-chat-icon-text (styles/default-chat-icon-text size)}])
|
||||||
|
|
||||||
(defn chat-intro-icon-view [icon-text chat-id styles]
|
(defn chat-intro-icon-view [icon-text chat-id group-chat styles]
|
||||||
(let [photo-path (re-frame.core/subscribe [:contacts/chat-photo chat-id])]
|
(if group-chat
|
||||||
(if-not (string/blank? @photo-path)
|
[default-chat-icon icon-text styles]
|
||||||
[photos/photo @photo-path styles]
|
(let [photo-path @(re-frame.core/subscribe [:chats/photo-path chat-id])]
|
||||||
[default-chat-icon icon-text styles])))
|
(if-not (string/blank? photo-path)
|
||||||
|
[photos/photo photo-path styles]))))
|
||||||
|
|
||||||
(defn profile-icon-view [photo-path name color edit? size override-styles]
|
(defn profile-icon-view [photo-path name color edit? size override-styles]
|
||||||
(let [styles (merge {:container {:width size :height size}
|
(let [styles (merge {:container {:width size :height size}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.ui.components.button :as button]
|
[status-im.ui.components.button :as button]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
|
[status-im.utils.universal-links.core :as links]
|
||||||
[status-im.ui.screens.chat.styles.main :as style]
|
[status-im.ui.screens.chat.styles.main :as style]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
[status-im.ui.components.colors :as colors]))
|
[status-im.ui.components.colors :as colors])
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defn join-chat-button [chat-id]
|
(defn join-chat-button [chat-id]
|
||||||
[button/button
|
[button/button
|
||||||
@ -20,15 +22,16 @@
|
|||||||
[react/text {:style style/decline-chat}
|
[react/text {:style style/decline-chat}
|
||||||
(i18n/label :t/group-chat-decline-invitation)]])
|
(i18n/label :t/group-chat-decline-invitation)]])
|
||||||
|
|
||||||
(defn group-chat-footer
|
(defview group-chat-footer
|
||||||
[chat-id]
|
[chat-id]
|
||||||
|
(letsubs [{:keys [joined?]} [:group-chat/inviter-info chat-id]]
|
||||||
|
(when-not joined?
|
||||||
[react/view {:style style/group-chat-join-footer}
|
[react/view {:style style/group-chat-join-footer}
|
||||||
[react/view {:style style/group-chat-join-container}
|
[react/view {:style style/group-chat-join-container}
|
||||||
[join-chat-button chat-id]
|
[join-chat-button chat-id]
|
||||||
[decline-chat chat-id]]])
|
[decline-chat chat-id]]])))
|
||||||
|
|
||||||
(defn group-chat-description-loading
|
(def group-chat-description-loading
|
||||||
[]
|
|
||||||
[react/view {:style (merge style/intro-header-description-container
|
[react/view {:style (merge style/intro-header-description-container
|
||||||
{:margin-bottom 36
|
{:margin-bottom 36
|
||||||
:height 44})}
|
:height 44})}
|
||||||
@ -38,16 +41,9 @@
|
|||||||
:size :small
|
:size :small
|
||||||
:color colors/gray}]])
|
:color colors/gray}]])
|
||||||
|
|
||||||
(defn group-chat-description-container
|
(defview no-messages-group-chat-description-container [chat-id]
|
||||||
[{:keys [pending-invite-inviter-name inviter-name chat-name public?
|
(letsubs [{:keys [highest-request-to lowest-request-from]}
|
||||||
universal-link range intro-status]}]
|
[:mailserver/ranges-by-chat-id chat-id]]
|
||||||
(let [{:keys [lowest-request-from highest-request-to]} range]
|
|
||||||
(case intro-status
|
|
||||||
:loading
|
|
||||||
[group-chat-description-loading]
|
|
||||||
|
|
||||||
:empty
|
|
||||||
(when public?
|
|
||||||
[react/nested-text {:style (merge style/intro-header-description
|
[react/nested-text {:style (merge style/intro-header-description
|
||||||
{:margin-bottom 36})}
|
{:margin-bottom 36})}
|
||||||
(let [quiet-hours (quot (- highest-request-to lowest-request-from)
|
(let [quiet-hours (quot (- highest-request-to lowest-request-from)
|
||||||
@ -63,23 +59,54 @@
|
|||||||
:on-press #(list-selection/open-share
|
:on-press #(list-selection/open-share
|
||||||
{:message
|
{:message
|
||||||
(i18n/label
|
(i18n/label
|
||||||
:t/share-public-chat-text {:link universal-link})})}
|
:t/share-public-chat-text {:link (links/generate-link :public-chat :external chat-id)})})}
|
||||||
(i18n/label :t/empty-chat-description-public-share-this)]])
|
(i18n/label :t/empty-chat-description-public-share-this)]]))
|
||||||
|
|
||||||
:messages
|
(defview pending-invitation-description
|
||||||
(when (not public?)
|
[inviter-pk chat-name]
|
||||||
(if pending-invite-inviter-name
|
(letsubs [inviter-name [:contacts/contact-name-by-identity inviter-pk]]
|
||||||
[react/nested-text {:style style/intro-header-description}
|
[react/nested-text {:style style/intro-header-description}
|
||||||
[{:style {:color colors/black}} pending-invite-inviter-name]
|
[{:style {:color colors/black}} inviter-name]
|
||||||
(i18n/label :t/join-group-chat-description
|
(i18n/label :t/join-group-chat-description
|
||||||
{:username ""
|
{:username ""
|
||||||
:group-name chat-name})]
|
:group-name chat-name})]))
|
||||||
(if (not= inviter-name "Unknown")
|
|
||||||
|
(defview joined-group-chat-description
|
||||||
|
[inviter-pk chat-name]
|
||||||
|
(letsubs [inviter-name [:contacts/contact-name-by-identity inviter-pk]]
|
||||||
[react/nested-text {:style style/intro-header-description}
|
[react/nested-text {:style style/intro-header-description}
|
||||||
(i18n/label :t/joined-group-chat-description
|
(i18n/label :t/joined-group-chat-description
|
||||||
{:username ""
|
{:username ""
|
||||||
:group-name chat-name})
|
:group-name chat-name})
|
||||||
[{:style {:color colors/black}} inviter-name]]
|
[{:style {:color colors/black}} inviter-name]]))
|
||||||
|
|
||||||
|
(defn created-group-chat-description [chat-name]
|
||||||
[react/text {:style style/intro-header-description}
|
[react/text {:style style/intro-header-description}
|
||||||
(i18n/label :t/created-group-chat-description
|
(i18n/label :t/created-group-chat-description
|
||||||
{:group-name chat-name})]))))))
|
{:group-name chat-name})])
|
||||||
|
|
||||||
|
(defview group-chat-inviter-description-container [chat-id chat-name]
|
||||||
|
(letsubs [{:keys [joined? inviter-pk]}
|
||||||
|
[:group-chat/inviter-info chat-id]]
|
||||||
|
(cond
|
||||||
|
(not joined?)
|
||||||
|
[pending-invitation-description inviter-pk chat-name]
|
||||||
|
inviter-pk
|
||||||
|
[joined-group-chat-description inviter-pk chat-name]
|
||||||
|
:else
|
||||||
|
[created-group-chat-description chat-name])))
|
||||||
|
|
||||||
|
(defn group-chat-description-container
|
||||||
|
[{:keys [public?
|
||||||
|
chat-id
|
||||||
|
chat-name
|
||||||
|
loading-messages?
|
||||||
|
no-messages?]}]
|
||||||
|
(cond loading-messages?
|
||||||
|
group-chat-description-loading
|
||||||
|
|
||||||
|
(and no-messages? public?)
|
||||||
|
[no-messages-group-chat-description-container chat-id]
|
||||||
|
|
||||||
|
(not public?)
|
||||||
|
[group-chat-inviter-description-container chat-id chat-name]))
|
||||||
|
@ -33,21 +33,6 @@
|
|||||||
:placeholder-text-color colors/gray
|
:placeholder-text-color colors/gray
|
||||||
:auto-capitalize :sentences}])
|
:auto-capitalize :sentences}])
|
||||||
|
|
||||||
(defview reply-message [from alias content]
|
|
||||||
(letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]
|
|
||||||
current-public-key [:multiaccount/public-key]]
|
|
||||||
[react/scroll-view {:style style/reply-message-content}
|
|
||||||
[react/view {:style style/reply-message-to-container}
|
|
||||||
(chat-utils/format-reply-author from alias ens-name current-public-key style/reply-message-author)]
|
|
||||||
(if (:image content)
|
|
||||||
[react/image {:style {:width 56
|
|
||||||
:height 56
|
|
||||||
:background-color :black
|
|
||||||
:border-radius 4}
|
|
||||||
:source {:uri (:image content)}}]
|
|
||||||
[react/text {:style (assoc (message-style/style-message-text false) :font-size 14)
|
|
||||||
:number-of-lines 3} (:text content)])]))
|
|
||||||
|
|
||||||
(defn close-button [on-press]
|
(defn close-button [on-press]
|
||||||
[react/touchable-highlight
|
[react/touchable-highlight
|
||||||
{:style style/cancel-reply-highlight
|
{:style style/cancel-reply-highlight
|
||||||
@ -58,12 +43,6 @@
|
|||||||
:height 19
|
:height 19
|
||||||
:color colors/white}]])
|
:color colors/white}]])
|
||||||
|
|
||||||
(defn reply-message-view [{:keys [content from alias]}]
|
|
||||||
[react/view {:style style/reply-message}
|
|
||||||
[photos/member-photo from]
|
|
||||||
[reply-message from alias content]
|
|
||||||
[close-button #(re-frame/dispatch [:chat.ui/cancel-message-reply])]])
|
|
||||||
|
|
||||||
(defn send-image-view [{:keys [uri]}]
|
(defn send-image-view [{:keys [uri]}]
|
||||||
[react/view {:style style/reply-message}
|
[react/view {:style style/reply-message}
|
||||||
[react/image {:style {:width 56 :height 56
|
[react/image {:style {:width 56 :height 56
|
||||||
@ -71,6 +50,29 @@
|
|||||||
:source {:uri uri}}]
|
:source {:uri uri}}]
|
||||||
[close-button #(re-frame/dispatch [:chat.ui/cancel-sending-image])]])
|
[close-button #(re-frame/dispatch [:chat.ui/cancel-sending-image])]])
|
||||||
|
|
||||||
|
(defview reply-message [from message-text image]
|
||||||
|
(letsubs [contact-name [:contacts/contact-name-by-identity from]
|
||||||
|
current-public-key [:multiaccount/public-key]]
|
||||||
|
[react/scroll-view {:style style/reply-message-content}
|
||||||
|
[react/view {:style style/reply-message-to-container}
|
||||||
|
(chat-utils/format-reply-author from contact-name current-public-key style/reply-message-author)]
|
||||||
|
(if image
|
||||||
|
[react/image {:style {:width 56
|
||||||
|
:height 56
|
||||||
|
:background-color :black
|
||||||
|
:border-radius 4}
|
||||||
|
:source {:uri image}}]
|
||||||
|
[react/text {:style (assoc (message-style/style-message-text false) :font-size 14)
|
||||||
|
:number-of-lines 3} message-text])]))
|
||||||
|
|
||||||
|
(defview reply-message-view []
|
||||||
|
(letsubs [{:keys [content from] :as message} [:chats/reply-message]]
|
||||||
|
(when message
|
||||||
|
[react/view {:style style/reply-message}
|
||||||
|
[photos/member-photo from]
|
||||||
|
[reply-message from (:text content) (:image content)]
|
||||||
|
[close-button #(re-frame/dispatch [:chat.ui/cancel-message-reply])]])))
|
||||||
|
|
||||||
(defview container []
|
(defview container []
|
||||||
(letsubs [mainnet? [:mainnet?]
|
(letsubs [mainnet? [:mainnet?]
|
||||||
input-text [:chats/current-chat-input-text]
|
input-text [:chats/current-chat-input-text]
|
||||||
|
@ -21,15 +21,15 @@
|
|||||||
|
|
||||||
(views/defview gap
|
(views/defview gap
|
||||||
[{:keys [gaps first-gap?]} idx list-ref]
|
[{:keys [gaps first-gap?]} idx list-ref]
|
||||||
(views/letsubs [{:keys [range intro-status]} [:chats/current-chat]
|
(views/letsubs [range [:chats/range]
|
||||||
|
{:keys [might-have-join-time-messages?]} [:chats/current-raw-chat]
|
||||||
in-progress? [:chats/fetching-gap-in-progress?
|
in-progress? [:chats/fetching-gap-in-progress?
|
||||||
(if first-gap?
|
(if first-gap?
|
||||||
[:first-gap]
|
[:first-gap]
|
||||||
(:ids gaps))]
|
(:ids gaps))]
|
||||||
connected? [:mailserver/connected?]]
|
connected? [:mailserver/connected?]]
|
||||||
(let [ids (:ids gaps)
|
(let [ids (:ids gaps)]
|
||||||
intro-loading? (= intro-status :loading)]
|
(when-not (and first-gap? might-have-join-time-messages?)
|
||||||
(when-not (and first-gap? intro-loading?)
|
|
||||||
[react/view {:style style/gap-container}
|
[react/view {:style style/gap-container}
|
||||||
[react/touchable-highlight
|
[react/touchable-highlight
|
||||||
{:on-press (when (and connected? (not in-progress?))
|
{:on-press (when (and connected? (not in-progress?))
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defview mention-element [from]
|
(defview mention-element [from]
|
||||||
(letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]]
|
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||||
(if ens-name (str "@" ens-name) alias)))
|
contact-name))
|
||||||
|
|
||||||
(defn message-timestamp
|
(defn message-timestamp
|
||||||
([message]
|
([message]
|
||||||
@ -38,14 +38,13 @@
|
|||||||
appender])
|
appender])
|
||||||
|
|
||||||
(defview quoted-message
|
(defview quoted-message
|
||||||
[_ {:keys [from text image]} outgoing current-public-key public?]
|
[_ {:keys [from text]} outgoing current-public-key public?]
|
||||||
(letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]]
|
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||||
[react/view {:style (style/quoted-message-container outgoing)}
|
[react/view {:style (style/quoted-message-container outgoing)}
|
||||||
[react/view {:style style/quoted-message-author-container}
|
[react/view {:style style/quoted-message-author-container}
|
||||||
[chat.utils/format-reply-author
|
[chat.utils/format-reply-author
|
||||||
from
|
from
|
||||||
alias
|
contact-name
|
||||||
ens-name
|
|
||||||
current-public-key
|
current-public-key
|
||||||
(partial style/quoted-message-author outgoing)]]
|
(partial style/quoted-message-author outgoing)]]
|
||||||
(if (and image
|
(if (and image
|
||||||
@ -239,8 +238,8 @@
|
|||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
(defview message-author-name [from alias]
|
(defview message-author-name [from alias]
|
||||||
(letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]]
|
(letsubs [contact-name [:contacts/raw-contact-name-by-identity from]]
|
||||||
(chat.utils/format-author alias style/message-author-name-container ens-name)))
|
(chat.utils/format-author (or contact-name alias) style/message-author-name-container)))
|
||||||
|
|
||||||
(defn message-content-wrapper
|
(defn message-content-wrapper
|
||||||
"Author, userpic and delivery wrapper"
|
"Author, userpic and delivery wrapper"
|
||||||
@ -261,7 +260,6 @@
|
|||||||
(when display-username?
|
(when display-username?
|
||||||
[react/touchable-opacity {:style style/message-author-touchable
|
[react/touchable-opacity {:style style/message-author-touchable
|
||||||
:on-press #(re-frame/dispatch [:chat.ui/show-profile from])}
|
:on-press #(re-frame/dispatch [:chat.ui/show-profile from])}
|
||||||
;;TODO (perf) move to event
|
|
||||||
[message-author-name from alias]])
|
[message-author-name from alias]])
|
||||||
;;MESSAGE CONTENT
|
;;MESSAGE CONTENT
|
||||||
content]]
|
content]]
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
[status-im.utils.universal-links.core :as universal-links]
|
[status-im.utils.universal-links.core :as universal-links]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
@ -27,12 +26,14 @@
|
|||||||
:color colors/gray}}
|
:color colors/gray}}
|
||||||
(i18n/label helper)]])
|
(i18n/label helper)]])
|
||||||
|
|
||||||
(defn chat-actions [{:keys [chat-id contact chat-name]}]
|
(defn one-to-one-chat-actions [{:keys [chat-id]}]
|
||||||
|
(let [photo @(re-frame/subscribe [:chats/photo-path chat-id])
|
||||||
|
contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity chat-id])]
|
||||||
[react/view
|
[react/view
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:theme :action
|
{:theme :action
|
||||||
:icon (multiaccounts/displayed-photo contact)
|
:icon photo
|
||||||
:title [view-profile {:name chat-name
|
:title [view-profile {:name contact-name
|
||||||
:helper :t/view-profile}]
|
:helper :t/view-profile}]
|
||||||
:accessibility-label :view-chat-details-button
|
:accessibility-label :view-chat-details-button
|
||||||
:accessories [:chevron]
|
:accessories [:chevron]
|
||||||
@ -60,7 +61,7 @@
|
|||||||
:title :t/delete-chat
|
:title :t/delete-chat
|
||||||
:accessibility-label :delete-chat-button
|
:accessibility-label :delete-chat-button
|
||||||
:icon :main-icons/delete
|
:icon :main-icons/delete
|
||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id])}]])
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id])}]]))
|
||||||
|
|
||||||
(defn public-chat-actions [{:keys [chat-id]}]
|
(defn public-chat-actions [{:keys [chat-id]}]
|
||||||
(let [link (universal-links/generate-link :public-chat :external chat-id)
|
(let [link (universal-links/generate-link :public-chat :external chat-id)
|
||||||
@ -101,15 +102,15 @@
|
|||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id])}]]))
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id])}]]))
|
||||||
|
|
||||||
(defn group-chat-actions []
|
(defn group-chat-actions []
|
||||||
(fn [{:keys [chat-id contact group-chat chat-name color online]}]
|
(fn [{:keys [chat-id group-chat chat-name color]}]
|
||||||
(let [joined @(re-frame/subscribe [:group-chat/chat-joined? chat-id])]
|
(let [{:keys [joined?]} @(re-frame/subscribe [:group-chat/inviter-info chat-id])]
|
||||||
[react/view
|
[react/view
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:theme :action
|
{:theme :action
|
||||||
:title [view-profile {:name chat-name
|
:title [view-profile {:name chat-name
|
||||||
:helper :t/group-info}]
|
:helper :t/group-info}]
|
||||||
:icon [chat-icon/chat-icon-view-chat-sheet
|
:icon [chat-icon/chat-icon-view-chat-sheet
|
||||||
contact group-chat chat-name color online]
|
chat-id group-chat chat-name color]
|
||||||
:accessories [:chevron]
|
:accessories [:chevron]
|
||||||
:on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])}]
|
:on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])}]
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
@ -130,7 +131,7 @@
|
|||||||
:accessibility-label :fetch-history-button
|
:accessibility-label :fetch-history-button
|
||||||
:icon :main-icons/arrow-down
|
:icon :main-icons/arrow-down
|
||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/fetch-history-pressed chat-id])}]
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/fetch-history-pressed chat-id])}]
|
||||||
(when joined
|
(when joined?
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:theme :action
|
{:theme :action
|
||||||
:title :t/leave-chat
|
:title :t/leave-chat
|
||||||
@ -143,7 +144,7 @@
|
|||||||
(cond
|
(cond
|
||||||
public? [public-chat-actions current-chat]
|
public? [public-chat-actions current-chat]
|
||||||
group-chat [group-chat-actions current-chat]
|
group-chat [group-chat-actions current-chat]
|
||||||
:else [chat-actions current-chat]))
|
:else [one-to-one-chat-actions current-chat]))
|
||||||
|
|
||||||
(defn options [chat-id message-id]
|
(defn options [chat-id message-id]
|
||||||
(fn []
|
(fn []
|
||||||
@ -162,16 +163,16 @@
|
|||||||
:accessibility-label :delete-transaction-button
|
:accessibility-label :delete-transaction-button
|
||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message chat-id message-id])}]]))
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message chat-id message-id])}]]))
|
||||||
|
|
||||||
(defn message-long-press [{:keys [content identicon from outgoing] :as message}]
|
(defn message-long-press [{:keys [content from outgoing] :as message}]
|
||||||
(fn []
|
(fn []
|
||||||
(let [{:keys [ens-name alias]} @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
|
(let [photo @(re-frame/subscribe [:chats/photo-path from])
|
||||||
|
contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
|
||||||
[react/view
|
[react/view
|
||||||
(when-not outgoing
|
(when-not outgoing
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:theme :action
|
{:theme :action
|
||||||
:icon (multiaccounts/displayed-photo {:identicon identicon
|
:icon photo
|
||||||
:public-key from})
|
:title [view-profile {:name contact-name
|
||||||
:title [view-profile {:name (or ens-name alias)
|
|
||||||
:helper :t/view-profile}]
|
:helper :t/view-profile}]
|
||||||
:accessibility-label :view-chat-details-button
|
:accessibility-label :view-chat-details-button
|
||||||
:accessories [:chevron]
|
:accessories [:chevron]
|
||||||
@ -197,15 +198,15 @@
|
|||||||
(re-frame/dispatch [:bottom-sheet/hide-sheet])
|
(re-frame/dispatch [:bottom-sheet/hide-sheet])
|
||||||
(list-selection/open-share {:message (:text content)}))}])])))
|
(list-selection/open-share {:message (:text content)}))}])])))
|
||||||
|
|
||||||
(defn sticker-long-press [{:keys [from identicon]}]
|
(defn sticker-long-press [{:keys [from]}]
|
||||||
(fn []
|
(fn []
|
||||||
(let [{:keys [ens-name alias]} @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
|
(let [photo @(re-frame/subscribe [:chats/photo-path from])
|
||||||
|
contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
|
||||||
[react/view
|
[react/view
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:theme :action
|
{:theme :action
|
||||||
:icon (multiaccounts/displayed-photo {:identicon identicon
|
:icon photo
|
||||||
:public-key from})
|
:title [view-profile {:name contact-name
|
||||||
:title [view-profile {:name (or ens-name alias)
|
|
||||||
:helper :t/view-profile}]
|
:helper :t/view-profile}]
|
||||||
:accessibility-label :view-chat-details-button
|
:accessibility-label :view-chat-details-button
|
||||||
:accessories [:chevron]
|
:accessories [:chevron]
|
||||||
|
@ -47,8 +47,8 @@
|
|||||||
:margin-right 6})
|
:margin-right 6})
|
||||||
|
|
||||||
(defn intro-header-container
|
(defn intro-header-container
|
||||||
[status no-messages]
|
[loading-messages? no-messages?]
|
||||||
(if (or no-messages (= status (or :loading :empty)))
|
(if (or loading-messages? no-messages?)
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:flex-direction :column
|
:flex-direction :column
|
||||||
:justify-content :center
|
:justify-content :center
|
||||||
|
@ -5,29 +5,7 @@
|
|||||||
[status-im.ui.screens.chat.styles.main :as st])
|
[status-im.ui.screens.chat.styles.main :as st])
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defn- in-progress-text [{:keys [highestBlock currentBlock startBlock]}]
|
(defn- group-last-activity [{:keys [contacts public?]}]
|
||||||
(let [total (- highestBlock startBlock)
|
|
||||||
ready (- currentBlock startBlock)
|
|
||||||
percentage (if (zero? ready)
|
|
||||||
0
|
|
||||||
(->> (/ ready total)
|
|
||||||
(* 100)
|
|
||||||
(.round js/Math)))]
|
|
||||||
|
|
||||||
(str (i18n/label :t/sync-in-progress) " " percentage "% " currentBlock)))
|
|
||||||
|
|
||||||
(defview last-activity [{:keys [sync-state accessibility-label]}]
|
|
||||||
(letsubs [state [:sync-data]]
|
|
||||||
[react/text {:style st/last-activity-text
|
|
||||||
:accessibility-label accessibility-label}
|
|
||||||
(case sync-state
|
|
||||||
:in-progress (in-progress-text state)
|
|
||||||
:synced (i18n/label :t/sync-synced))]))
|
|
||||||
|
|
||||||
(defn- group-last-activity [{:keys [contacts sync-state public?]}]
|
|
||||||
(if (or (= sync-state :in-progress)
|
|
||||||
(= sync-state :synced))
|
|
||||||
[last-activity {:sync-state sync-state}]
|
|
||||||
[react/view {:flex-direction :row}
|
[react/view {:flex-direction :row}
|
||||||
[react/text {:style st/toolbar-subtitle}
|
[react/text {:style st/toolbar-subtitle}
|
||||||
(if public?
|
(if public?
|
||||||
@ -35,34 +13,40 @@
|
|||||||
(let [cnt (count contacts)]
|
(let [cnt (count contacts)]
|
||||||
(if (zero? cnt)
|
(if (zero? cnt)
|
||||||
(i18n/label :members-active-none)
|
(i18n/label :members-active-none)
|
||||||
(i18n/label-pluralize cnt :t/members-active))))]]))
|
(i18n/label-pluralize cnt :t/members-active))))]])
|
||||||
|
|
||||||
(defn- contact-indicator [{:keys [added?]}]
|
(defview one-to-one-name [from]
|
||||||
|
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||||
|
contact-name))
|
||||||
|
|
||||||
|
(defview contact-indicator [contact-id]
|
||||||
|
(letsubs [added? [:contacts/contact-added? contact-id]]
|
||||||
[react/view {:flex-direction :row}
|
[react/view {:flex-direction :row}
|
||||||
[react/text {:style st/toolbar-subtitle}
|
[react/text {:style st/toolbar-subtitle}
|
||||||
(if added?
|
(if added?
|
||||||
(i18n/label :chat-is-a-contact)
|
(i18n/label :chat-is-a-contact)
|
||||||
(i18n/label :chat-is-not-a-contact))]])
|
(i18n/label :chat-is-not-a-contact))]]))
|
||||||
|
|
||||||
(defview toolbar-content-view []
|
(defview toolbar-content-view []
|
||||||
(letsubs [{:keys [group-chat color online contacts chat-name contact public?]}
|
(letsubs [{:keys [group-chat
|
||||||
[:chats/current-chat]
|
color
|
||||||
sync-state [:sync-state]]
|
chat-id
|
||||||
(let [has-subtitle? (or group-chat (not= :done sync-state))]
|
contacts
|
||||||
|
chat-name
|
||||||
|
public?]}
|
||||||
|
[:chats/current-chat]]
|
||||||
[react/view {:style st/toolbar-container}
|
[react/view {:style st/toolbar-container}
|
||||||
[react/view {:margin-right 10}
|
[react/view {:margin-right 10}
|
||||||
[chat-icon.screen/chat-icon-view-toolbar contact group-chat chat-name color online]]
|
[chat-icon.screen/chat-icon-view-toolbar chat-id group-chat chat-name color]]
|
||||||
[react/view {:style st/chat-name-view}
|
[react/view {:style st/chat-name-view}
|
||||||
[react/text {:style st/chat-name-text
|
[react/text {:style st/chat-name-text
|
||||||
:number-of-lines 1
|
:number-of-lines 1
|
||||||
:accessibility-label :chat-name-text}
|
:accessibility-label :chat-name-text}
|
||||||
chat-name]
|
|
||||||
(when contact
|
|
||||||
[contact-indicator contact])
|
|
||||||
(if group-chat
|
(if group-chat
|
||||||
|
chat-name
|
||||||
|
[one-to-one-name chat-id])]
|
||||||
|
(when-not group-chat
|
||||||
|
[contact-indicator chat-id])
|
||||||
|
(when group-chat
|
||||||
[group-last-activity {:contacts contacts
|
[group-last-activity {:contacts contacts
|
||||||
:public? public?
|
:public? public?}])]]))
|
||||||
:sync-state sync-state}]
|
|
||||||
(when has-subtitle?
|
|
||||||
[last-activity {:sync-state sync-state
|
|
||||||
:accessibility-label :last-seen-text}]))]])))
|
|
||||||
|
@ -4,30 +4,26 @@
|
|||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.colors :as colors]))
|
[status-im.ui.components.colors :as colors]))
|
||||||
|
|
||||||
(defn format-author [alias style name]
|
(defn format-author [contact-name style]
|
||||||
(let [additional-styles (style false)]
|
(let [additional-styles (style false)]
|
||||||
(if name
|
(if (= (aget contact-name 0) "@")
|
||||||
(let [name (subs name 0 80)]
|
(let [trimmed-name (subs contact-name 0 81)]
|
||||||
[react/text {:number-of-lines 2
|
[react/text {:number-of-lines 2
|
||||||
:style (merge {:color colors/blue
|
:style (merge {:color colors/blue
|
||||||
:font-size 13
|
:font-size 13
|
||||||
:line-height 18
|
:line-height 18
|
||||||
:font-weight "500"} additional-styles)}
|
:font-weight "500"} additional-styles)}
|
||||||
(str "@" (or (stateofus/username name) name))])
|
(or (stateofus/username trimmed-name) trimmed-name)])
|
||||||
[react/text {:style (merge {:color colors/gray
|
[react/text {:style (merge {:color colors/gray
|
||||||
:font-size 12
|
:font-size 12
|
||||||
:line-height 18
|
:line-height 18
|
||||||
:font-weight "400"} additional-styles)}
|
:font-weight "400"} additional-styles)}
|
||||||
alias])))
|
contact-name])))
|
||||||
|
|
||||||
(def ^:private reply-symbol "↪ ")
|
(def ^:private reply-symbol "↪ ")
|
||||||
|
|
||||||
(defn format-reply-author [from alias username current-public-key style]
|
(defn format-reply-author [from username current-public-key style]
|
||||||
(let [reply-name (or (some->> username
|
|
||||||
(str "@")
|
|
||||||
(str reply-symbol))
|
|
||||||
(str reply-symbol alias))]
|
|
||||||
(or (and (= from current-public-key)
|
(or (and (= from current-public-key)
|
||||||
[react/text {:style (style true)}
|
[react/text {:style (style true)}
|
||||||
(str reply-symbol (i18n/label :t/You))])
|
(str reply-symbol (i18n/label :t/You))])
|
||||||
(format-author (subs reply-name 0 80) style false))))
|
(format-author username style)))
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
(ns status-im.ui.screens.chat.views
|
(ns status-im.ui.screens.chat.views
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.contact.db :as contact.db]
|
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.connectivity.view :as connectivity]
|
[status-im.ui.components.connectivity.view :as connectivity]
|
||||||
@ -41,8 +39,9 @@
|
|||||||
[sheets/actions current-chat])
|
[sheets/actions current-chat])
|
||||||
:height 256}])}]}])
|
:height 256}])}]}])
|
||||||
|
|
||||||
(defn add-contact-bar
|
(defview add-contact-bar [public-key]
|
||||||
[public-key]
|
(letsubs [added? [:contacts/contact-added? public-key]]
|
||||||
|
(when-not added?
|
||||||
[react/touchable-highlight
|
[react/touchable-highlight
|
||||||
{:on-press
|
{:on-press
|
||||||
#(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
#(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
||||||
@ -50,24 +49,58 @@
|
|||||||
[react/view {:style (style/add-contact)}
|
[react/view {:style (style/add-contact)}
|
||||||
[vector-icons/icon :main-icons/add
|
[vector-icons/icon :main-icons/add
|
||||||
{:color colors/blue}]
|
{:color colors/blue}]
|
||||||
[react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]])
|
[react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]])))
|
||||||
|
|
||||||
(defn intro-header
|
(defn intro-header [name]
|
||||||
[contact]
|
|
||||||
[react/text {:style (assoc style/intro-header-description
|
[react/text {:style (assoc style/intro-header-description
|
||||||
:margin-bottom 32)}
|
:margin-bottom 32)}
|
||||||
(str
|
(str
|
||||||
(i18n/label :t/empty-chat-description-one-to-one)
|
(i18n/label :t/empty-chat-description-one-to-one)
|
||||||
(multiaccounts/displayed-name contact))])
|
name)])
|
||||||
|
|
||||||
|
(defn chat-intro [{:keys [chat-id
|
||||||
|
chat-name
|
||||||
|
group-chat
|
||||||
|
contact-name
|
||||||
|
public?
|
||||||
|
color
|
||||||
|
loading-messages?
|
||||||
|
no-messages?]}]
|
||||||
|
[react/view (style/intro-header-container loading-messages? no-messages?)
|
||||||
|
;; Icon section
|
||||||
|
[react/view {:style {:margin-top 42
|
||||||
|
:margin-bottom 24}}
|
||||||
|
[chat-icon.screen/chat-intro-icon-view
|
||||||
|
chat-name chat-id group-chat
|
||||||
|
{:default-chat-icon (style/intro-header-icon 120 color)
|
||||||
|
:default-chat-icon-text style/intro-header-icon-text
|
||||||
|
:size 120}]]
|
||||||
|
;; Chat title section
|
||||||
|
[react/text {:style (style/intro-header-chat-name)} (if group-chat chat-name contact-name)]
|
||||||
|
;; Description section
|
||||||
|
(if group-chat
|
||||||
|
[chat.group/group-chat-description-container {:chat-id chat-id
|
||||||
|
:loading-messages? loading-messages?
|
||||||
|
:chat-name chat-name
|
||||||
|
:public? public?
|
||||||
|
:no-messages? no-messages?}]
|
||||||
|
[react/text {:style (assoc style/intro-header-description
|
||||||
|
:margin-bottom 32)}
|
||||||
|
|
||||||
|
(str
|
||||||
|
(i18n/label :t/empty-chat-description-one-to-one)
|
||||||
|
contact-name)])])
|
||||||
|
|
||||||
|
(defview chat-intro-one-to-one [{:keys [chat-id] :as opts}]
|
||||||
|
(letsubs [contact-name [:contacts/contact-name-by-identity chat-id]]
|
||||||
|
(chat-intro (assoc opts :contact-name contact-name))))
|
||||||
|
|
||||||
(defn chat-intro-header-container
|
(defn chat-intro-header-container
|
||||||
[{:keys [group-chat name pending-invite-inviter-name color chat-id chat-name
|
[{:keys [group-chat
|
||||||
public? contact intro-status] :as chat}
|
might-have-join-time-messages?
|
||||||
|
color chat-id chat-name
|
||||||
|
public?]}
|
||||||
no-messages]
|
no-messages]
|
||||||
(let [icon-text (if public? chat-id name)
|
|
||||||
intro-name (if public? chat-name (multiaccounts/displayed-name contact))]
|
|
||||||
(when (or pending-invite-inviter-name
|
|
||||||
(not= (get-in contact [:tribute-to-talk :snt-amount]) 0))
|
|
||||||
[react/touchable-without-feedback
|
[react/touchable-without-feedback
|
||||||
{:style {:flex 1
|
{:style {:flex 1
|
||||||
:align-items :flex-start}
|
:align-items :flex-start}
|
||||||
@ -75,22 +108,17 @@
|
|||||||
(re-frame/dispatch
|
(re-frame/dispatch
|
||||||
[:chat.ui/set-chat-ui-props {:input-bottom-sheet nil}])
|
[:chat.ui/set-chat-ui-props {:input-bottom-sheet nil}])
|
||||||
(react/dismiss-keyboard!))}
|
(react/dismiss-keyboard!))}
|
||||||
[react/view (style/intro-header-container intro-status no-messages)
|
(let [opts
|
||||||
;; Icon section
|
{:chat-id chat-id
|
||||||
[react/view {:style {:margin-top 42
|
:group-chat group-chat
|
||||||
:margin-bottom 24}}
|
:chat-name chat-name
|
||||||
[chat-icon.screen/chat-intro-icon-view
|
:public? public?
|
||||||
icon-text chat-id
|
:color color
|
||||||
{:default-chat-icon (style/intro-header-icon 120 color)
|
:loading-messages? might-have-join-time-messages?
|
||||||
:default-chat-icon-text style/intro-header-icon-text
|
:no-messages? no-messages}]
|
||||||
:size 120}]]
|
|
||||||
;; Chat title section
|
|
||||||
[react/text {:style (style/intro-header-chat-name)}
|
|
||||||
(if group-chat chat-name intro-name)]
|
|
||||||
;; Description section
|
|
||||||
(if group-chat
|
(if group-chat
|
||||||
[chat.group/group-chat-description-container chat]
|
[chat-intro opts]
|
||||||
[intro-header contact])]])))
|
[chat-intro-one-to-one opts]))])
|
||||||
|
|
||||||
(defonce messages-list-ref (atom nil))
|
(defonce messages-list-ref (atom nil))
|
||||||
|
|
||||||
@ -110,15 +138,16 @@
|
|||||||
(debounce/debounce-and-dispatch [:chat.ui/message-visibility-changed e] 5000))
|
(debounce/debounce-and-dispatch [:chat.ui/message-visibility-changed e] 5000))
|
||||||
|
|
||||||
(defview messages-view
|
(defview messages-view
|
||||||
[{:keys [public? group-chat chat-id pending-invite-inviter-name] :as chat}]
|
[{:keys [group-chat chat-id public?] :as chat}]
|
||||||
(letsubs [messages [:chats/current-chat-messages-stream]
|
(letsubs [messages [:chats/current-chat-messages-stream]
|
||||||
|
no-messages? [:chats/current-chat-no-messages?]
|
||||||
current-public-key [:multiaccount/public-key]]
|
current-public-key [:multiaccount/public-key]]
|
||||||
[list/flat-list
|
[list/flat-list
|
||||||
{:key-fn #(or (:message-id %) (:value %))
|
{:key-fn #(or (:message-id %) (:value %))
|
||||||
:ref #(reset! messages-list-ref %)
|
:ref #(reset! messages-list-ref %)
|
||||||
:header (when pending-invite-inviter-name
|
:header (when (and group-chat (not public?))
|
||||||
[chat.group/group-chat-footer chat-id])
|
[chat.group/group-chat-footer chat-id])
|
||||||
:footer [chat-intro-header-container chat (empty? messages)]
|
:footer [chat-intro-header-container chat no-messages?]
|
||||||
:data messages
|
:data messages
|
||||||
:inverted true
|
:inverted true
|
||||||
:render-fn (fn [{:keys [outgoing type] :as message} idx]
|
:render-fn (fn [{:keys [outgoing type] :as message} idx]
|
||||||
@ -154,14 +183,13 @@
|
|||||||
[empty-bottom-sheet])))
|
[empty-bottom-sheet])))
|
||||||
|
|
||||||
(defview chat []
|
(defview chat []
|
||||||
(letsubs [{:keys [chat-id show-input? group-chat contact] :as current-chat}
|
(letsubs [{:keys [chat-id show-input? group-chat] :as current-chat}
|
||||||
[:chats/current-chat]]
|
[:chats/current-chat]]
|
||||||
[react/view {:style {:flex 1}}
|
[react/view {:style {:flex 1}}
|
||||||
[connectivity/connectivity
|
[connectivity/connectivity
|
||||||
[topbar current-chat]
|
[topbar current-chat]
|
||||||
[react/view {:style {:flex 1}}
|
[react/view {:style {:flex 1}}
|
||||||
;;TODO contact.db/added? looks weird here, move to events
|
(when-not group-chat
|
||||||
(when (and (not group-chat) (not (contact.db/added? contact)))
|
|
||||||
[add-contact-bar chat-id])
|
[add-contact-bar chat-id])
|
||||||
[messages-view current-chat]]]
|
[messages-view current-chat]]]
|
||||||
(when show-input?
|
(when show-input?
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
[status-im.ui.components.radio :as radio]
|
[status-im.ui.components.radio :as radio]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.topbar :as topbar]
|
[status-im.ui.components.topbar :as topbar]
|
||||||
|
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||||
[status-im.ui.screens.chat.message.message :as message]
|
[status-im.ui.screens.chat.message.message :as message]
|
||||||
|
[status-im.ui.screens.chat.styles.message.message :as message.style]
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.screens.chat.photos :as photos]
|
||||||
[status-im.ui.screens.profile.components.views :as profile.components]
|
[status-im.ui.screens.profile.components.views :as profile.components]
|
||||||
[status-im.utils.debounce :as debounce])
|
[status-im.utils.debounce :as debounce])
|
||||||
@ -624,7 +626,11 @@
|
|||||||
[name-item {:name name :hide-chevron? true :action action}]]
|
[name-item {:name name :hide-chevron? true :action action}]]
|
||||||
[radio/radio (= name preferred-name)]]]))]]]])
|
[radio/radio (= name preferred-name)]]]))]]]])
|
||||||
|
|
||||||
(defn- registered [names {:keys [preferred-name public-key] :as account} _]
|
(views/defview my-name []
|
||||||
|
(views/letsubs [contact-name [:multiaccount/my-name]]
|
||||||
|
(chat.utils/format-author contact-name message.style/message-author-name-container)))
|
||||||
|
|
||||||
|
(defn- registered [names {:keys [preferred-name] :as account} _]
|
||||||
[react/view {:style {:flex 1}}
|
[react/view {:style {:flex 1}}
|
||||||
[react/scroll-view
|
[react/scroll-view
|
||||||
[react/view {:style {:margin-top 8}}
|
[react/view {:style {:margin-top 8}}
|
||||||
@ -663,7 +669,7 @@
|
|||||||
:timestamp-str "9:41 AM"}]
|
:timestamp-str "9:41 AM"}]
|
||||||
[react/view
|
[react/view
|
||||||
[react/view {:padding-left 72}
|
[react/view {:padding-left 72}
|
||||||
[message/message-author-name public-key]]
|
[my-name]]
|
||||||
[react/view {:flex-direction :row}
|
[react/view {:flex-direction :row}
|
||||||
[react/view {:padding-left 16 :padding-right 8 :padding-top 4}
|
[react/view {:padding-left 16 :padding-right 8 :padding-top 4}
|
||||||
[photos/photo (multiaccounts/displayed-photo account) {:size 36}]]
|
[photos/photo (multiaccounts/displayed-photo account) {:size 36}]]
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defview mention-element [from]
|
(defview mention-element [from]
|
||||||
(letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]]
|
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||||
(if ens-name (str "@" ens-name) alias)))
|
contact-name))
|
||||||
|
|
||||||
(defn render-subheader-inline [acc {:keys [type destination literal children]}]
|
(defn render-subheader-inline [acc {:keys [type destination literal children]}]
|
||||||
(case type
|
(case type
|
||||||
@ -108,20 +108,20 @@
|
|||||||
|
|
||||||
(defn home-list-item [[_ home-item]]
|
(defn home-list-item [[_ home-item]]
|
||||||
(let [{:keys [chat-id chat-name color online group-chat
|
(let [{:keys [chat-id chat-name color online group-chat
|
||||||
public? contact timestamp last-message]}
|
public? timestamp last-message]}
|
||||||
home-item
|
home-item
|
||||||
private-group? (and group-chat (not public?))
|
private-group? (and group-chat (not public?))
|
||||||
public-group? (and group-chat public?)
|
public-group? (and group-chat public?)]
|
||||||
;;TODO (perf) move to event
|
|
||||||
truncated-chat-name (utils/truncate-str chat-name 30)]
|
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:icon [chat-icon.screen/chat-icon-view-chat-list
|
{:icon [chat-icon.screen/chat-icon-view-chat-list
|
||||||
contact group-chat truncated-chat-name color online false]
|
chat-id group-chat chat-name color online false]
|
||||||
:title-prefix (cond
|
:title-prefix (cond
|
||||||
private-group? :main-icons/tiny-group
|
private-group? :main-icons/tiny-group
|
||||||
public-group? :main-icons/tiny-public
|
public-group? :main-icons/tiny-public
|
||||||
:else nil)
|
:else nil)
|
||||||
:title truncated-chat-name
|
:title (if group-chat
|
||||||
|
(utils/truncate-str chat-name 30)
|
||||||
|
@(re-frame/subscribe [:contacts/contact-name-by-identity chat-id]))
|
||||||
:title-accessibility-label :chat-name-text
|
:title-accessibility-label :chat-name-text
|
||||||
:title-row-accessory [message-timestamp (if (pos? (:whisper-timestamp last-message))
|
:title-row-accessory [message-timestamp (if (pos? (:whisper-timestamp last-message))
|
||||||
(:whisper-timestamp last-message)
|
(:whisper-timestamp last-message)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user