diff --git a/src/status_im/chat/db.cljs b/src/status_im/chat/db.cljs index fb9a6217d3..f9de641c88 100644 --- a/src/status_im/chat/db.cljs +++ b/src/status_im/chat/db.cljs @@ -1,69 +1,11 @@ (ns status-im.chat.db - (:require [clojure.set :as clojure.set] - [clojure.string :as clojure.string] - [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])) + (:require [clojure.string :as clojure.string] + [status-im.mailserver.constants :as mailserver.constants])) (defn group-chat-name [{:keys [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]}] (= type :datemark)) diff --git a/src/status_im/chat/db_test.cljs b/src/status_im/chat/db_test.cljs index d5a1f9cc38..4d1f03eb22 100644 --- a/src/status_im/chat/db_test.cljs +++ b/src/status_im/chat/db_test.cljs @@ -1,7 +1,5 @@ (ns status-im.chat.db-test (: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])) (deftest group-chat-name @@ -41,18 +39,6 @@ (is (= {:type :datemark :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 (testing "empty state" (is (empty? diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index 32f15e6e0d..38ed94bb92 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -4,7 +4,6 @@ [status-im.transport.filters.core :as transport.filters] [status-im.contact.core :as contact.core] [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.messages :as messages-store] [status-im.ethereum.json-rpc :as json-rpc] @@ -92,8 +91,7 @@ :is-active true :timestamp now :contacts #{chat-id} - :last-clock-value 0 - :messages {}})) + :last-clock-value 0})) (fx/defn ensure-chat "Add chat to db and update" @@ -165,6 +163,7 @@ {:chat-id topic :is-active true :name topic + :chat-name (str "#" topic) :group-chat true :contacts #{} :public? true @@ -175,20 +174,20 @@ (fx/defn clear-history "Clears history of the particular chat" [{:keys [db] :as cofx} chat-id] - (let [{:keys [messages - last-message + (let [{:keys [last-message deleted-at-clock-value]} (get-in db [:chats chat-id]) last-message-clock-value (or (:clock-value last-message) deleted-at-clock-value (utils.clocks/send 0))] (fx/merge cofx - {:db (update-in db [:chats chat-id] merge - {:messages {} - :message-list nil - :last-message nil - :unviewed-messages-count 0 - :deleted-at-clock-value last-message-clock-value})} + {:db (-> db + (assoc-in [:messages chat-id] {}) + (update-in [:message-lists] dissoc chat-id) + (update-in [:chats chat-id] merge + {:last-message nil + :unviewed-messages-count 0 + :deleted-at-clock-value last-message-clock-value}))} (messages-store/delete-messages-by-chat-id chat-id) #(chats-store/save-chat % (get-in % [:db :chats chat-id]))))) @@ -218,13 +217,9 @@ {:db (-> db (dissoc :loaded-chat-id) - (update-in [:chats current-chat-id] - assoc - :all-loaded? false - :cursor nil - :messages-initialized? false - :messages {} - :message-list nil))})) + (update :messages dissoc current-chat-id) + (update :message-lists dissoc current-chat-id) + (update :pagination-info dissoc current-chat-id))})) (fx/defn preload-chat-data "Takes chat-id and coeffects map, returns effects necessary when navigating to chat" @@ -241,8 +236,6 @@ (transport.filters/load-chat chat-id)) (when platform/desktop? (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)))) (fx/defn navigate-to-chat diff --git a/src/status_im/chat/models/loading.cljs b/src/status_im/chat/models/loading.cljs index ba78fad937..8c7cb824c2 100644 --- a/src/status_im/chat/models/loading.cljs +++ b/src/status_im/chat/models/loading.cljs @@ -24,10 +24,7 @@ [{:keys [db] :as cofx} new-chats] (let [old-chats (:chats db) chats (reduce (fn [acc {:keys [chat-id] :as chat}] - (assoc acc chat-id - (assoc chat - :messages-initialized? false - :messages {}))) + (assoc acc chat-id chat)) {} new-chats) chats (merge old-chats chats)] @@ -52,12 +49,11 @@ acc)) {} (get-in db [:chats chat-id :messages]))] - {:db (update-in db [:chats chat-id] - assoc - :messages new-messages - :all-loaded? false - :message-list (message-list/add-many nil (vals new-messages)) - :cursor (clock-value->cursor last-element-clock-value))})))))) + {:db (-> db + (assoc-in [:messages chat-id] new-messages) + (assoc-in [:pagination-info chat-id] {:all-loaded? false + :cursor (clock-value->cursor last-element-clock-value)}) + (assoc-in [:message-lists chat-id] (message-list/add-many nil (vals new-messages))))})))))) (fx/defn initialize-chats "Initialize persisted chats on startup" @@ -70,7 +66,7 @@ [{:keys [db]} current-chat-id _ err] (log/error "failed loading messages" current-chat-id err) (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 "Loads more messages for current chat" @@ -81,10 +77,10 @@ {:keys [cursor messages]}] (when-not (or (nil? 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 - (get-in db [:chats current-chat-id :messages-initialized?])))) - (let [already-loaded-messages (get-in db [:chats current-chat-id :messages]) + (get-in db [:pagination-info current-chat-id :messages-initialized?])))) + (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] #{}) ;; We remove those messages that are already loaded, as we might get some duplicates {:keys [all-messages @@ -111,23 +107,23 @@ messages)] (fx/merge cofx {: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 :loading-messages?] false) - (assoc-in [:chats current-chat-id :messages] all-messages) - (update-in [:chats current-chat-id :message-list] message-list/add-many new-messages) - (assoc-in [:chats current-chat-id :cursor] cursor) - (assoc-in [:chats current-chat-id :all-loaded?] + (assoc-in [:pagination-info current-chat-id :loading-messages?] false) + (assoc-in [:messages current-chat-id] all-messages) + (update-in [:message-lists current-chat-id] message-list/add-many new-messages) + (assoc-in [:pagination-info current-chat-id :cursor] cursor) + (assoc-in [:pagination-info current-chat-id :all-loaded?] (empty? cursor)))} (message-seen/mark-messages-seen current-chat-id))))) (fx/defn load-more-messages [{:keys [db] :as cofx}] (when-let [current-chat-id (:current-chat-id db)] - (when-let [session-id (get-in db [:chats current-chat-id :messages-initialized?])] - (when-not (or (get-in db [:chats current-chat-id :all-loaded?]) - (get-in db [:chats current-chat-id :loading-messages?])) - (let [cursor (get-in db [:chats current-chat-id :cursor]) + (when-let [session-id (get-in db [:pagination-info current-chat-id :messages-initialized?])] + (when-not (or (get-in db [:pagination-info current-chat-id :all-loaded?]) + (get-in db [:pagination-info current-chat-id :loading-messages?])) + (let [cursor (get-in db [:pagination-info current-chat-id :cursor]) load-messages-fx (data-store.messages/messages-by-chat-id-rpc (waku/enabled? cofx) current-chat-id @@ -142,7 +138,7 @@ (fx/defn load-messages [{:keys [db now] :as cofx}] (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 ; reset chat first-not-visible-items state (chat.state/reset) @@ -151,7 +147,7 @@ ;; We keep track of whether there's a loaded chat ;; which will be reset only if we hit home (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) (load-more-messages))) ;; We mark messages as seen in case we received them while on a different tab diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 91d40b27a2..c870dc67c3 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -28,8 +28,8 @@ (fx/defn rebuild-message-list [{:keys [db]} chat-id] - {:db (assoc-in db [:chats chat-id :message-list] - (message-list/add-many nil (vals (get-in db [:chats chat-id :messages]))))}) + {:db (assoc-in db [:message-lists chat-id] + (message-list/add-many nil (vals (get-in db [:messages chat-id]))))}) (fx/defn hidden-message-marked-as-seen {:events [::hidden-message-marked-as-seen]} @@ -42,7 +42,7 @@ "Hide chat message, rebuild message-list" [{:keys [db] :as cofx} chat-id {:keys [seen message-id]}] (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])) (rebuild-message-list chat-id))) @@ -52,7 +52,7 @@ :keys [seen-by-user?]}] (let [current-public-key (multiaccounts.model/current-public-key cofx) 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?)] (fx/merge cofx (when message-to-be-removed @@ -62,8 +62,8 @@ ;; 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 ;; some troubles disabling it, so next time - (update-in [:chats chat-id :messages] assoc message-id prepared-message) - (update-in [:chats chat-id :message-list] message-list/add prepared-message)) + (update-in [:messages chat-id] assoc message-id prepared-message) + (update-in [:message-lists chat-id] message-list/add prepared-message)) (and (not seen-by-user?) (not= from current-public-key)) (update-in [:chats chat-id :loaded-unviewed-messages-ids] @@ -94,7 +94,7 @@ (defn- message-loaded? [{: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? [{:keys [db]} {:keys [chat-id clock-value]}] @@ -145,7 +145,7 @@ ;; 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 ;; 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 (add-received-message message-with-chat-id) (update-unviewed-count message-with-chat-id) @@ -202,7 +202,7 @@ [{:keys [db] :as cofx} chat-id message-id status] (fx/merge cofx {:db (assoc-in db - [:chats chat-id :messages message-id :outgoing-status] + [:messages chat-id message-id :outgoing-status] status)} (data-store.messages/update-outgoing-status message-id status))) @@ -219,7 +219,7 @@ "Deletes chat message, rebuild message-list" [{:keys [db] :as cofx} chat-id message-id] (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) (rebuild-message-list chat-id))) @@ -229,4 +229,4 @@ (fx/defn toggle-expand-message [{: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)}) diff --git a/src/status_im/chat/models/message_seen.cljs b/src/status_im/chat/models/message_seen.cljs index c387ba61f3..948dc50b1a 100644 --- a/src/status_im/chat/models/message_seen.cljs +++ b/src/status_im/chat/models/message_seen.cljs @@ -41,12 +41,11 @@ (when (seq loaded-unviewed-ids) (fx/merge cofx {:db (reduce (fn [acc message-id] - (assoc-in acc [:chats chat-id :messages - message-id :seen] + (assoc-in acc [:messages chat-id message-id :seen] true)) db loaded-unviewed-ids)} (messages-store/mark-messages-seen chat-id loaded-unviewed-ids nil) (update-chats-unviewed-messages-count {:chat-id chat-id}) (when platform/desktop? - (update-dock-badge-label)))))) \ No newline at end of file + (update-dock-badge-label)))))) diff --git a/src/status_im/chat/models/message_test.cljs b/src/status_im/chat/models/message_test.cljs index 0513bd9346..2079dd65b6 100644 --- a/src/status_im/chat/models/message_test.cljs +++ b/src/status_im/chat/models/message_test.cljs @@ -94,7 +94,8 @@ :clock-value 1 :chat-id "a"})))) (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" :from "a" :clock-value 1 @@ -124,7 +125,8 @@ :view-id :chat :loaded-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!" (let [actual (message/receive-one {:db db} {:from "me" @@ -136,7 +138,7 @@ :outgoing true :content "b" :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" (is message)))))) @@ -170,7 +172,7 @@ :whisper-timestamp 0 :timestamp 0}] (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" (is (not (message/receive-one cofx bad-from-message)))) (testing "a message with non existing chat-id" @@ -199,7 +201,7 @@ :whisper-timestamp 0 :timestamp 0}] (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" (is (not (message/receive-one cofx bad-chat-id-message)))))) @@ -235,37 +237,39 @@ :whisper-timestamp 0 :timestamp 0}] (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" - (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" - (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 (with-redefs [time/day-relative (constantly "day-relative") time/timestamp->time (constantly "timestamp")] - (let [cofx1 {:db {:chats {"chat-id" {:messages {0 {:message-id 0 - :content "a" - :clock-value 0 - :whisper-timestamp 0 - :timestamp 0} - 1 {:message-id 1 - :content "b" - :clock-value 1 - :whisper-timestamp 1 - :timestamp 1}} - :message-list [{:something :something}]}}}} - cofx2 {:db {:chats {"chat-id" {:messages {0 {:message-id 0 - :content "a" - :clock-value 0 - :whisper-timestamp 1 - :timestamp 1}} - :message-list [{:something :something}]}}}} + (let [cofx1 {:db {:messages {"chat-id" {0 {:message-id 0 + :content "a" + :clock-value 0 + :whisper-timestamp 0 + :timestamp 0} + 1 {:message-id 1 + :content "b" + :clock-value 1 + :whisper-timestamp 1 + :timestamp 1}}} + :message-lists {"chat-id" [{:something :something}]} + :chats {"chat-id" {}}}} + cofx2 {:db {:messages {"chat-id" {0 {:message-id 0 + :content "a" + :clock-value 0 + :whisper-timestamp 1 + :timestamp 1}}} + :message-list {"chat-id" [{:something :something}]} + :chats {"chat-id" {}}}} fx1 (message/delete-message cofx1 "chat-id" 1) fx2 (message/delete-message cofx2 "chat-id" 0)] (testing "Deleting message deletes it along with all references" (is (= '(0) - (keys (get-in fx1 [:db :chats "chat-id" :messages])))) + (keys (get-in fx1 [:db :messages "chat-id"])))) (is (= [{:one-to-one? false :message-id 0 :whisper-timestamp 0 @@ -284,8 +288,8 @@ :display-username? true :outgoing false}] (models.message-list/->seq - (get-in fx1 [:db :chats "chat-id" :message-list])))) + (get-in fx1 [:db :message-lists "chat-id"])))) (is (= {} - (get-in fx2 [:db :chats "chat-id" :messages]))) + (get-in fx2 [:db :messages "chat-id"]))) (is (= nil - (get-in fx2 [:db :chats "chat-id" :message-list]))))))) + (get-in fx2 [:db :message-lists "chat-id"]))))))) diff --git a/src/status_im/chat/models_test.cljs b/src/status_im/chat/models_test.cljs index 01cd0bffc4..cff1e9c497 100644 --- a/src/status_im/chat/models_test.cljs +++ b/src/status_im/chat/models_test.cljs @@ -65,15 +65,15 @@ (deftest clear-history-test (let [chat-id "1" - cofx {:db {:chats {chat-id {:message-list [{:something "a"}] - :last-message {:clock-value 10} + cofx {:db {:message-lists {chat-id [{:something "a"}]} + :chats {chat-id {:last-message {:clock-value 10} :unviewed-messages-count 1}}}}] (testing "it deletes all the messages" (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" (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" (let [actual (chat/clear-history cofx chat-id)] (is (= 0 (get-in actual [:db :chats chat-id :unviewed-messages-count]))))) @@ -103,13 +103,13 @@ (deftest remove-chat-test (let [chat-id "1" - cofx {:db {:chats {chat-id {:last-message {:clock-value 10} - :messages {"1" {:clock-value 1} - "2" {:clock-value 10} - "3" {:clock-value 2}}}}}}] + cofx {:db {:messages {chat-id {"1" {:clock-value 1} + "2" {:clock-value 10} + "3" {:clock-value 2}}} + :chats {chat-id {:last-message {:clock-value 10}}}}}] (testing "it deletes all the messages" (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" (let [actual (chat/remove-chat cofx chat-id)] (is (= 10 (get-in actual [:db :chats chat-id :deleted-at-clock-value]))))) @@ -147,9 +147,10 @@ (def test-db {:multiaccount {:public-key "me"} + + :messages {"status" {"4" {} "5" {} "6" {}}} :chats {"status" {:public? true :group-chat true - :messages {"4" {} "5" {} "6" {}} :loaded-unviewed-messages-ids #{"6" "5" "4"}} "opened" {:loaded-unviewed-messages-ids #{}} "1-1" {:loaded-unviewed-messages-ids #{"6" "5" "4"}}}}) diff --git a/src/status_im/data_store/chats.cljs b/src/status_im/data_store/chats.cljs index cb736fc4df..2950950823 100644 --- a/src/status_im/data_store/chats.cljs +++ b/src/status_im/data_store/chats.cljs @@ -16,10 +16,16 @@ group-chat private-group-chat-type :else one-to-one-chat-type))) -(defn rpc->type [{:keys [chatType] :as chat}] +(defn rpc->type [{:keys [chatType name] :as chat}] (cond - (= public-chat-type chatType) (assoc chat :public? true :group-chat true) - (= private-group-chat-type chatType) (assoc chat :public? false :group-chat true) + (= public-chat-type chatType) (assoc chat + :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))) (defn- marshal-members [{:keys [admins contacts members-joined chatType] :as chat}] @@ -68,11 +74,10 @@ :deleted-at-clock-value :deletedAtClockValue :is-active :active :last-clock-value :lastClockValue}) - (dissoc :message-list :gaps-loaded? :pagination-info - :public? :group-chat :messages + (dissoc :public? :group-chat :messages :might-have-join-time-messages? :loaded-unviewed-messages-ids - :messages-initialized? :contacts :admins :members-joined))) + :contacts :admins :members-joined))) (defn <-rpc [chat] (-> chat diff --git a/src/status_im/data_store/chats_test.cljs b/src/status_im/data_store/chats_test.cljs index 692a48e2e7..2e30591083 100644 --- a/src/status_im/data_store/chats_test.cljs +++ b/src/status_im/data_store/chats_test.cljs @@ -5,7 +5,6 @@ (deftest ->to-rpc (let [chat {:public? false :group-chat true - :message-list [] :color "color" :contacts #{"a" "b" "c" "d"} :last-clock-value 10 @@ -13,15 +12,11 @@ :members-joined #{"a" "c"} :name "name" :membership-update-events :events - :gaps-loaded? true :unviewed-messages-count 2 :is-active true - :messages {} - :pagination-info {} :chat-id "chat-id" :loaded-unviewed-messages-ids [] - :timestamp 2 - :messages-initialized? true} + :timestamp 2} expected-chat {:id "chat-id" :color "color" :name "name" @@ -73,6 +68,7 @@ expected-chat {:public? false :group-chat true :color "color" + :chat-name "name" :contacts #{"a" "b" "c" "d"} :last-clock-value 10 :last-message nil diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index c7d8aa6cd4..ccad314f6a 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -519,7 +519,7 @@ (handlers/register-handler-fx :chat.ui/resend-message (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 cofx (transport.message/set-message-envelope-hash chat-id message-id (:message-type message) 1) diff --git a/src/status_im/group_chats/db.cljs b/src/status_im/group_chats/db.cljs index b7eb21f81d..6bb6283344 100644 --- a/src/status_im/group_chats/db.cljs +++ b/src/status_im/group_chats/db.cljs @@ -1,5 +1,4 @@ -(ns status-im.group-chats.db - (:require [status-im.multiaccounts.core :as multiaccounts])) +(ns status-im.group-chats.db) (def members-added-type 3) @@ -23,21 +22,3 @@ (defn group-chat? [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}))))) diff --git a/src/status_im/mailserver/core.cljs b/src/status_im/mailserver/core.cljs index 85f6a097de..80787b1f95 100644 --- a/src/status_im/mailserver/core.cljs +++ b/src/status_im/mailserver/core.cljs @@ -1171,7 +1171,7 @@ {}))) (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])] (data-store.mailservers/load-gaps cofx chat-id success-fn)))) @@ -1190,7 +1190,7 @@ cofx {:db (-> db - (assoc-in [:chats chat-id :gaps-loaded?] true) + (assoc-in [:gaps-loaded? chat-id] true) (assoc-in [:mailserver/gaps chat-id] gaps))} (data-store.mailservers/delete-gaps outdated-gaps)))) diff --git a/src/status_im/mailserver/core_test.cljs b/src/status_im/mailserver/core_test.cljs index 26833c62b2..c849fbb936 100644 --- a/src/status_im/mailserver/core_test.cljs +++ b/src/status_im/mailserver/core_test.cljs @@ -389,13 +389,11 @@ {:multiaccount {:public-key "me"} :chats {"chat-id-1" {:is-active true - :messages {} :might-have-join-time-messages? true :group-chat true :public? true :chat-id "chat-id-1"} "chat-id-2" {:is-active true - :messages {} :group-chat true :public? true :chat-id "chat-id-2"}}}}) @@ -405,14 +403,12 @@ {:multiaccount {:public-key "me"} :chats {"chat-id-1" {:is-active true - :messages {} :join-time-mail-request-id "a" :might-have-join-time-messages? true :group-chat true :public? true :chat-id "chat-id-1"} "chat-id-2" {:is-active true - :messages {} :group-chat true :public? true :chat-id "chat-id-2"}}}}) @@ -422,26 +418,22 @@ {:multiaccount {:public-key "me"} :chats {"chat-id-1" {:is-active true - :messages {} :join-time-mail-request-id "a" :might-have-join-time-messages? true :group-chat true :public? true :chat-id "chat-id-1"} "chat-id-2" {:is-active true - :messages {} :join-time-mail-request-id "a" :might-have-join-time-messages? true :group-chat true :public? true :chat-id "chat-id-2"} "chat-id-3" {:is-active true - :messages {} :group-chat true :public? true :chat-id "chat-id-3"} "chat-id-4" {:is-active true - :messages {} :join-time-mail-request-id "a" :might-have-join-time-messages? true :group-chat true diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 570ae60013..096907c0c7 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -37,7 +37,6 @@ [status-im.utils.money :as money] [status-im.utils.platform :as platform] [status-im.utils.security :as security] - [status-im.utils.universal-links.core :as links] [status-im.wallet.db :as wallet.db] [status-im.wallet.utils :as wallet.utils] status-im.ui.screens.keycard.subs @@ -185,6 +184,10 @@ (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 ============================================================================================================== (re-frame/reg-sub @@ -450,6 +453,21 @@ (fn [{:keys [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 :multiaccount/default-account :<- [:multiaccount/accounts] @@ -608,77 +626,24 @@ (re-frame/reg-sub :chats/active-chats - :<- [:contacts/contacts] :<- [::chats] - :<- [:multiaccount] - (fn [[contacts chats multiaccount]] - (chat.db/active-chats contacts chats multiaccount))) + (fn [chats] + (reduce-kv (fn [acc id {:keys [is-active] :as chat}] + (if is-active + (assoc acc id chat) + acc)) + {} + chats))) -;; TODO: this is no useful without tribute to talk -#_(defn enrich-current-one-to-one-chat - [{:keys [contact] :as current-chat} my-public-key ttt-settings - chain-keyword prices currency] - (let [{:keys [tribute-to-talk]} contact - {: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 + ::chat + :<- [::chats] + (fn [chats [_ chat-id]] + (get chats chat-id))) (re-frame/reg-sub :chats/current-raw-chat - :<- [:chats/active-chats] + :<- [::chats] :<- [:chats/current-chat-id] (fn [[chats current-chat-id]] (get chats current-chat-id))) @@ -694,15 +659,10 @@ :chats/current-chat :<- [:chats/current-raw-chat] :<- [:multiaccount/public-key] - :<- [:mailserver/ranges] - (fn [[{:keys [group-chat chat-id messages] :as current-chat} - my-public-key ranges]] + (fn [[{:keys [group-chat] :as current-chat} + my-public-key]] (when current-chat - (cond-> (enrich-current-chat current-chat ranges) - (empty? messages) - (assoc :universal-link - (links/generate-link :public-chat :external chat-id)) - + (cond-> current-chat (chat.models/public-chat? current-chat) (assoc :show-input? true) @@ -727,17 +687,12 @@ (fn [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 :chats/current-chat-messages - :<- [:chats/current-chat] - (fn [{:keys [messages]}] - (or messages {}))) + :<- [::messages] + :<- [:chats/current-chat-id] + (fn [[messages chat-id]] + (get messages chat-id {}))) (re-frame/reg-sub :chats/messages-gaps @@ -746,6 +701,12 @@ (fn [[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 :chats/range :<- [:mailserver/ranges] @@ -755,27 +716,23 @@ (re-frame/reg-sub :chats/all-loaded? - :<- [:chats/current-chat] - (fn [chat] - (:all-loaded? chat))) + :<- [::pagination-info] + :<- [:chats/current-chat-id] + (fn [[pagination-info chat-id]] + (get-in pagination-info [chat-id :all-loaded?]))) (re-frame/reg-sub :chats/public? - :<- [:chats/current-chat] + :<- [:chats/current-raw-chat] (fn [chat] (:public? chat))) (re-frame/reg-sub :chats/message-list - :<- [:chats/current-chat] - (fn [chat] - (:message-list chat))) - -(re-frame/reg-sub - :chats/messages - :<- [:chats/current-chat] - (fn [chat] - (:messages chat))) + :<- [::message-lists] + :<- [:chats/current-chat-id] + (fn [[message-lists chat-id]] + (get message-lists chat-id))) (defn hydrate-messages "Pull data from messages and add it to the sorted list" @@ -786,10 +743,16 @@ %) message-list)) +(re-frame/reg-sub + :chats/current-chat-no-messages? + :<- [:chats/current-chat-messages] + (fn [messages] + (empty? messages))) + (re-frame/reg-sub :chats/current-chat-messages-stream :<- [:chats/message-list] - :<- [:chats/messages] + :<- [:chats/current-chat-messages] :<- [:chats/messages-gaps] :<- [:chats/range] :<- [:chats/all-loaded?] @@ -801,17 +764,6 @@ (hydrate-messages messages) (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 :chats/photo-path :<- [:contacts/contacts] @@ -826,9 +778,15 @@ :chats/unread-messages-number :<- [:chats/active-chats] (fn [chats _] - (let [grouped-chats (group-by :public? (vals chats))] - {:public (apply + (map :unviewed-messages-count (get grouped-chats true))) - :other (apply + (map :unviewed-messages-count (get grouped-chats false)))}))) + (reduce-kv (fn [{:keys [public other]} _ {:keys [unviewed-messages-count public?]}] + (if public? + {:public (+ public unviewed-messages-count) + :other other} + {:other (+ other unviewed-messages-count) + :public public})) + {:public 0 + :other 0} + chats))) (re-frame/reg-sub :chats/cooldown-enabled? @@ -886,13 +844,13 @@ (filter-contacts selected-contacts active-contacts))) (re-frame/reg-sub - :group-chat/chat-joined? - :<- [:multiaccount/public-key] - :<- [:chats/active-chats] - (fn [[my-public-key chats] [_ chat-id]] - (let [current-chat (get chats chat-id)] - (and (chat.models/group-chat? current-chat) - (group-chats.db/joined? my-public-key current-chat))))) + :group-chat/inviter-info + (fn [[_ chat-id] _] + [(re-frame/subscribe [::chat chat-id]) + (re-frame/subscribe [:multiaccount/public-key])]) + (fn [[chat my-public-key]] + {:joined? (group-chats.db/joined? my-public-key chat) + :inviter-pk (group-chats.db/get-inviter-pk my-public-key chat)})) (re-frame/reg-sub :chats/transaction-status @@ -1631,21 +1589,40 @@ contact.db/public-key->new-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 :contacts/contact-name-by-identity - :<- [:contacts/contacts] - :<- [:multiaccount] - (fn [[contacts current-multiaccount] [_ identity]] + (fn [[_ identity] _] + [(re-frame/subscribe [:contacts/raw-contact-name-by-identity identity]) + (re-frame/subscribe [:multiaccount])]) + (fn [[contact-name current-multiaccount] [_ identity]] (let [me? (= (:public-key current-multiaccount) identity)] (if me? - {:ens-name (:preferred-name current-multiaccount) - :alias (gfycat/generate-gfy identity)} - (let [contact (or (contacts identity) - (contact.db/public-key->new-contact identity))] - {:ens-name (when (:ens-verified contact) - (:name contact)) - :alias (or (:alias contact) - (gfycat/generate-gfy identity))}))))) + (or (:preferred-name current-multiaccount) + (gfycat/generate-gfy identity)) + (or contact-name + (gfycat/generate-gfy identity)))))) (re-frame/reg-sub :messages/quote-info @@ -1694,17 +1671,6 @@ (fn [[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 :contacts/contact-by-address :<- [:contacts/contacts] diff --git a/src/status_im/transport/core_test.cljs b/src/status_im/transport/core_test.cljs index 8be7d492f8..a1eb80eabf 100644 --- a/src/status_im/transport/core_test.cljs +++ b/src/status_im/transport/core_test.cljs @@ -60,7 +60,8 @@ (let [chat-id "chat-id" from "from" 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" (let [cofx (message/set-message-envelope-hash initial-cofx chat-id message-id :message-type 1)] @@ -72,12 +73,12 @@ (is (= :sent (get-in (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" (is (= :not-sent (get-in (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 "only inserts" (let [cofx (fx/merge @@ -103,7 +104,7 @@ (is (= :sent (get-in cofx - [:db :chats chat-id :messages message-id :outgoing-status])))))) + [:db :messages chat-id message-id :outgoing-status])))))) (testing "order of events is reversed" (let [cofx (fx/merge initial-cofx @@ -119,7 +120,7 @@ (is (= :sent (get-in cofx - [:db :chats chat-id :messages message-id :outgoing-status])))))) + [:db :messages chat-id message-id :outgoing-status])))))) (testing "message not sent" (let [cofx (fx/merge initial-cofx @@ -135,4 +136,4 @@ (is (= :not-sent (get-in cofx - [:db :chats chat-id :messages message-id :outgoing-status]))))))))) + [:db :messages chat-id message-id :outgoing-status]))))))))) diff --git a/src/status_im/transport/message/core.cljs b/src/status_im/transport/message/core.cljs index c06d9ea261..fefe2e0f62 100644 --- a/src/status_im/transport/message/core.cljs +++ b/src/status_im/transport/message/core.cljs @@ -91,7 +91,7 @@ [{:keys [db] :as cofx} message-id status] (if-let [{:keys [chat-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)) ;; We don't have a message-envelope for this, might be that the confirmation ;; came too early @@ -118,4 +118,4 @@ :message-type message-type}) (update-in [:transport/message-ids->confirmations message-id] #(or % {:pending-confirmations messages-count})))})] - (apply fx/merge cofx (conj check-confirmations-fx add-envelope-data)))) \ No newline at end of file + (apply fx/merge cofx (conj check-confirmations-fx add-envelope-data)))) diff --git a/src/status_im/ui/components/chat_icon/screen.cljs b/src/status_im/ui/components/chat_icon/screen.cljs index 1a7f131dc1..33d80cc0b8 100644 --- a/src/status_im/ui/components/chat_icon/screen.cljs +++ b/src/status_im/ui/components/chat_icon/screen.cljs @@ -8,8 +8,6 @@ [status-im.ui.screens.chat.photos :as photos] [status-im.utils.platform :as platform])) -;;TODO REWORK THIS NAMESPACE - (defn default-chat-icon [name styles] (when-not (string/blank? name) [react/view (:default-chat-icon styles) @@ -32,15 +30,16 @@ [react/view online-dot-right]]]]) (defn chat-icon-view - [contact group-chat name _online styles] + [chat-id group-chat name styles] [react/view (:container styles) - (if-not group-chat - [photos/photo (multiaccounts/displayed-photo contact) styles] - [default-chat-icon name styles])]) + (if group-chat + [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 - [contact group-chat name color online] - [chat-icon-view contact group-chat name online + [chat-id group-chat name color] + [chat-icon-view chat-id group-chat name {:container styles/container-chat-toolbar :online-view-wrapper styles/online-view-wrapper :online-view styles/online-view @@ -52,8 +51,8 @@ :default-chat-icon-text (styles/default-chat-icon-text 36)}]) (defn chat-icon-view-chat-list - [contact group-chat name color online] - [chat-icon-view contact group-chat name online + [chat-id group-chat name color] + [chat-icon-view chat-id group-chat name {:container styles/container-chat-list :online-view-wrapper styles/online-view-wrapper :online-view styles/online-view @@ -65,8 +64,8 @@ :default-chat-icon-text (styles/default-chat-icon-text 40)}]) (defn chat-icon-view-chat-sheet - [contact group-chat name color online] - [chat-icon-view contact group-chat name online + [chat-id group-chat name color] + [chat-icon-view chat-id group-chat name {:container styles/container-chat-list :online-view-wrapper styles/online-view-wrapper :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-text (styles/default-chat-icon-text size)}]) -(defn chat-intro-icon-view [icon-text chat-id styles] - (let [photo-path (re-frame.core/subscribe [:contacts/chat-photo chat-id])] - (if-not (string/blank? @photo-path) - [photos/photo @photo-path styles] - [default-chat-icon icon-text styles]))) +(defn chat-intro-icon-view [icon-text chat-id group-chat styles] + (if group-chat + [default-chat-icon icon-text styles] + (let [photo-path @(re-frame.core/subscribe [:chats/photo-path chat-id])] + (if-not (string/blank? photo-path) + [photos/photo photo-path styles])))) (defn profile-icon-view [photo-path name color edit? size override-styles] (let [styles (merge {:container {:width size :height size} diff --git a/src/status_im/ui/screens/chat/group.cljs b/src/status_im/ui/screens/chat/group.cljs index 208a2444db..5814fc49c9 100644 --- a/src/status_im/ui/screens/chat/group.cljs +++ b/src/status_im/ui/screens/chat/group.cljs @@ -2,10 +2,12 @@ (:require [re-frame.core :as re-frame] [status-im.ui.components.button :as button] [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.i18n :as i18n] [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] [button/button @@ -20,15 +22,16 @@ [react/text {:style style/decline-chat} (i18n/label :t/group-chat-decline-invitation)]]) -(defn group-chat-footer +(defview group-chat-footer [chat-id] - [react/view {:style style/group-chat-join-footer} - [react/view {:style style/group-chat-join-container} - [join-chat-button chat-id] - [decline-chat 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-container} + [join-chat-button 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 {:margin-bottom 36 :height 44})} @@ -38,48 +41,72 @@ :size :small :color colors/gray}]]) +(defview no-messages-group-chat-description-container [chat-id] + (letsubs [{:keys [highest-request-to lowest-request-from]} + [:mailserver/ranges-by-chat-id chat-id]] + [react/nested-text {:style (merge style/intro-header-description + {:margin-bottom 36})} + (let [quiet-hours (quot (- highest-request-to lowest-request-from) + (* 60 60)) + quiet-time (if (<= quiet-hours 24) + (i18n/label :t/quiet-hours + {:quiet-hours quiet-hours}) + (i18n/label :t/quiet-days + {:quiet-days (quot quiet-hours 24)}))] + (i18n/label :t/empty-chat-description-public + {:quiet-hours quiet-time})) + [{:style {:color colors/blue} + :on-press #(list-selection/open-share + {:message + (i18n/label + :t/share-public-chat-text {:link (links/generate-link :public-chat :external chat-id)})})} + (i18n/label :t/empty-chat-description-public-share-this)]])) + +(defview pending-invitation-description + [inviter-pk chat-name] + (letsubs [inviter-name [:contacts/contact-name-by-identity inviter-pk]] + [react/nested-text {:style style/intro-header-description} + [{:style {:color colors/black}} inviter-name] + (i18n/label :t/join-group-chat-description + {:username "" + :group-name chat-name})])) + +(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} + (i18n/label :t/joined-group-chat-description + {:username "" + :group-name chat-name}) + [{:style {:color colors/black}} inviter-name]])) + +(defn created-group-chat-description [chat-name] + [react/text {:style style/intro-header-description} + (i18n/label :t/created-group-chat-description + {: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 [pending-invite-inviter-name inviter-name chat-name public? - universal-link range intro-status]}] - (let [{:keys [lowest-request-from highest-request-to]} range] - (case intro-status - :loading - [group-chat-description-loading] + [{:keys [public? + chat-id + chat-name + loading-messages? + no-messages?]}] + (cond loading-messages? + group-chat-description-loading - :empty - (when public? - [react/nested-text {:style (merge style/intro-header-description - {:margin-bottom 36})} - (let [quiet-hours (quot (- highest-request-to lowest-request-from) - (* 60 60)) - quiet-time (if (<= quiet-hours 24) - (i18n/label :t/quiet-hours - {:quiet-hours quiet-hours}) - (i18n/label :t/quiet-days - {:quiet-days (quot quiet-hours 24)}))] - (i18n/label :t/empty-chat-description-public - {:quiet-hours quiet-time})) - [{:style {:color colors/blue} - :on-press #(list-selection/open-share - {:message - (i18n/label - :t/share-public-chat-text {:link universal-link})})} - (i18n/label :t/empty-chat-description-public-share-this)]]) + (and no-messages? public?) + [no-messages-group-chat-description-container chat-id] - :messages - (when (not public?) - (if pending-invite-inviter-name - [react/nested-text {:style style/intro-header-description} - [{:style {:color colors/black}} pending-invite-inviter-name] - (i18n/label :t/join-group-chat-description - {:username "" - :group-name chat-name})] - (if (not= inviter-name "Unknown") - [react/nested-text {:style style/intro-header-description} - (i18n/label :t/joined-group-chat-description - {:username "" - :group-name chat-name}) - [{:style {:color colors/black}} inviter-name]] - [react/text {:style style/intro-header-description} - (i18n/label :t/created-group-chat-description - {:group-name chat-name})])))))) + (not public?) + [group-chat-inviter-description-container chat-id chat-name])) diff --git a/src/status_im/ui/screens/chat/input/input.cljs b/src/status_im/ui/screens/chat/input/input.cljs index 501f4be08d..6cb5c6f6de 100644 --- a/src/status_im/ui/screens/chat/input/input.cljs +++ b/src/status_im/ui/screens/chat/input/input.cljs @@ -33,21 +33,6 @@ :placeholder-text-color colors/gray :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] [react/touchable-highlight {:style style/cancel-reply-highlight @@ -58,12 +43,6 @@ :height 19 :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]}] [react/view {:style style/reply-message} [react/image {:style {:width 56 :height 56 @@ -71,6 +50,29 @@ :source {:uri uri}}] [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 [] (letsubs [mainnet? [:mainnet?] input-text [:chats/current-chat-input-text] diff --git a/src/status_im/ui/screens/chat/message/gap.cljs b/src/status_im/ui/screens/chat/message/gap.cljs index 66b6e8bc59..d5aa38809c 100644 --- a/src/status_im/ui/screens/chat/message/gap.cljs +++ b/src/status_im/ui/screens/chat/message/gap.cljs @@ -21,15 +21,15 @@ (views/defview gap [{: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? (if first-gap? [:first-gap] (:ids gaps))] connected? [:mailserver/connected?]] - (let [ids (:ids gaps) - intro-loading? (= intro-status :loading)] - (when-not (and first-gap? intro-loading?) + (let [ids (:ids gaps)] + (when-not (and first-gap? might-have-join-time-messages?) [react/view {:style style/gap-container} [react/touchable-highlight {:on-press (when (and connected? (not in-progress?)) diff --git a/src/status_im/ui/screens/chat/message/message.cljs b/src/status_im/ui/screens/chat/message/message.cljs index 2946244579..1a53dca15e 100644 --- a/src/status_im/ui/screens/chat/message/message.cljs +++ b/src/status_im/ui/screens/chat/message/message.cljs @@ -18,8 +18,8 @@ (:require-macros [status-im.utils.views :refer [defview letsubs]])) (defview mention-element [from] - (letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]] - (if ens-name (str "@" ens-name) alias))) + (letsubs [contact-name [:contacts/contact-name-by-identity from]] + contact-name)) (defn message-timestamp ([message] @@ -38,14 +38,13 @@ appender]) (defview quoted-message - [_ {:keys [from text image]} outgoing current-public-key public?] - (letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]] + [_ {:keys [from text]} outgoing current-public-key public?] + (letsubs [contact-name [:contacts/contact-name-by-identity from]] [react/view {:style (style/quoted-message-container outgoing)} [react/view {:style style/quoted-message-author-container} [chat.utils/format-reply-author from - alias - ens-name + contact-name current-public-key (partial style/quoted-message-author outgoing)]] (if (and image @@ -239,8 +238,8 @@ nil))) (defview message-author-name [from alias] - (letsubs [{:keys [ens-name]} [:contacts/contact-name-by-identity from]] - (chat.utils/format-author alias style/message-author-name-container ens-name))) + (letsubs [contact-name [:contacts/raw-contact-name-by-identity from]] + (chat.utils/format-author (or contact-name alias) style/message-author-name-container))) (defn message-content-wrapper "Author, userpic and delivery wrapper" @@ -261,7 +260,6 @@ (when display-username? [react/touchable-opacity {:style style/message-author-touchable :on-press #(re-frame/dispatch [:chat.ui/show-profile from])} - ;;TODO (perf) move to event [message-author-name from alias]]) ;;MESSAGE CONTENT content]] diff --git a/src/status_im/ui/screens/chat/sheets.cljs b/src/status_im/ui/screens/chat/sheets.cljs index 79361e7223..bede117ca4 100644 --- a/src/status_im/ui/screens/chat/sheets.cljs +++ b/src/status_im/ui/screens/chat/sheets.cljs @@ -4,7 +4,6 @@ [status-im.ui.components.react :as react] [status-im.ui.components.list-selection :as list-selection] [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.colors :as colors] [status-im.utils.platform :as platform] @@ -27,40 +26,42 @@ :color colors/gray}} (i18n/label helper)]]) -(defn chat-actions [{:keys [chat-id contact chat-name]}] - [react/view - [list-item/list-item - {:theme :action - :icon (multiaccounts/displayed-photo contact) - :title [view-profile {:name chat-name - :helper :t/view-profile}] - :accessibility-label :view-chat-details-button - :accessories [:chevron] - :on-press #(hide-sheet-and-dispatch [:chat.ui/show-profile chat-id])}] - [list-item/list-item - {:theme :action - :title :t/mark-all-read - :accessibility-label :mark-all-read-button - :icon :main-icons/check - :on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-pressed chat-id])}] - [list-item/list-item - {:theme :action - :title :t/clear-history - :accessibility-label :clear-history-button - :icon :main-icons/close - :on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history-pressed chat-id])}] - [list-item/list-item - {:theme :action - :title :t/fetch-history - :accessibility-label :fetch-history-button - :icon :main-icons/arrow-down - :on-press #(hide-sheet-and-dispatch [:chat.ui/fetch-history-pressed chat-id])}] - [list-item/list-item - {:theme :action-destructive - :title :t/delete-chat - :accessibility-label :delete-chat-button - :icon :main-icons/delete - :on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id])}]]) +(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 + [list-item/list-item + {:theme :action + :icon photo + :title [view-profile {:name contact-name + :helper :t/view-profile}] + :accessibility-label :view-chat-details-button + :accessories [:chevron] + :on-press #(hide-sheet-and-dispatch [:chat.ui/show-profile chat-id])}] + [list-item/list-item + {:theme :action + :title :t/mark-all-read + :accessibility-label :mark-all-read-button + :icon :main-icons/check + :on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-pressed chat-id])}] + [list-item/list-item + {:theme :action + :title :t/clear-history + :accessibility-label :clear-history-button + :icon :main-icons/close + :on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history-pressed chat-id])}] + [list-item/list-item + {:theme :action + :title :t/fetch-history + :accessibility-label :fetch-history-button + :icon :main-icons/arrow-down + :on-press #(hide-sheet-and-dispatch [:chat.ui/fetch-history-pressed chat-id])}] + [list-item/list-item + {:theme :action-destructive + :title :t/delete-chat + :accessibility-label :delete-chat-button + :icon :main-icons/delete + :on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat-pressed chat-id])}]])) (defn public-chat-actions [{:keys [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])}]])) (defn group-chat-actions [] - (fn [{:keys [chat-id contact group-chat chat-name color online]}] - (let [joined @(re-frame/subscribe [:group-chat/chat-joined? chat-id])] + (fn [{:keys [chat-id group-chat chat-name color]}] + (let [{:keys [joined?]} @(re-frame/subscribe [:group-chat/inviter-info chat-id])] [react/view [list-item/list-item {:theme :action :title [view-profile {:name chat-name :helper :t/group-info}] :icon [chat-icon/chat-icon-view-chat-sheet - contact group-chat chat-name color online] + chat-id group-chat chat-name color] :accessories [:chevron] :on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])}] [list-item/list-item @@ -130,7 +131,7 @@ :accessibility-label :fetch-history-button :icon :main-icons/arrow-down :on-press #(hide-sheet-and-dispatch [:chat.ui/fetch-history-pressed chat-id])}] - (when joined + (when joined? [list-item/list-item {:theme :action :title :t/leave-chat @@ -143,7 +144,7 @@ (cond public? [public-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] (fn [] @@ -162,16 +163,16 @@ :accessibility-label :delete-transaction-button :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 [] - (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 (when-not outgoing [list-item/list-item {:theme :action - :icon (multiaccounts/displayed-photo {:identicon identicon - :public-key from}) - :title [view-profile {:name (or ens-name alias) + :icon photo + :title [view-profile {:name contact-name :helper :t/view-profile}] :accessibility-label :view-chat-details-button :accessories [:chevron] @@ -197,15 +198,15 @@ (re-frame/dispatch [:bottom-sheet/hide-sheet]) (list-selection/open-share {:message (:text content)}))}])]))) -(defn sticker-long-press [{:keys [from identicon]}] +(defn sticker-long-press [{:keys [from]}] (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 [list-item/list-item {:theme :action - :icon (multiaccounts/displayed-photo {:identicon identicon - :public-key from}) - :title [view-profile {:name (or ens-name alias) + :icon photo + :title [view-profile {:name contact-name :helper :t/view-profile}] :accessibility-label :view-chat-details-button :accessories [:chevron] diff --git a/src/status_im/ui/screens/chat/styles/main.cljs b/src/status_im/ui/screens/chat/styles/main.cljs index 5c913b26c6..cc663b546a 100644 --- a/src/status_im/ui/screens/chat/styles/main.cljs +++ b/src/status_im/ui/screens/chat/styles/main.cljs @@ -47,8 +47,8 @@ :margin-right 6}) (defn intro-header-container - [status no-messages] - (if (or no-messages (= status (or :loading :empty))) + [loading-messages? no-messages?] + (if (or loading-messages? no-messages?) {:flex 1 :flex-direction :column :justify-content :center @@ -143,4 +143,4 @@ (def tribute-received-note {:font-size 13 :line-height 18 - :text-align :center}) \ No newline at end of file + :text-align :center}) diff --git a/src/status_im/ui/screens/chat/toolbar_content.cljs b/src/status_im/ui/screens/chat/toolbar_content.cljs index c8fe47daea..d6bad19039 100644 --- a/src/status_im/ui/screens/chat/toolbar_content.cljs +++ b/src/status_im/ui/screens/chat/toolbar_content.cljs @@ -5,64 +5,48 @@ [status-im.ui.screens.chat.styles.main :as st]) (:require-macros [status-im.utils.views :refer [defview letsubs]])) -(defn- in-progress-text [{:keys [highestBlock currentBlock startBlock]}] - (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/text {:style st/toolbar-subtitle} - (if public? - (i18n/label :t/public-group-status) - (let [cnt (count contacts)] - (if (zero? cnt) - (i18n/label :members-active-none) - (i18n/label-pluralize cnt :t/members-active))))]])) - -(defn- contact-indicator [{:keys [added?]}] +(defn- group-last-activity [{:keys [contacts public?]}] [react/view {:flex-direction :row} [react/text {:style st/toolbar-subtitle} - (if added? - (i18n/label :chat-is-a-contact) - (i18n/label :chat-is-not-a-contact))]]) + (if public? + (i18n/label :t/public-group-status) + (let [cnt (count contacts)] + (if (zero? cnt) + (i18n/label :members-active-none) + (i18n/label-pluralize cnt :t/members-active))))]]) + +(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/text {:style st/toolbar-subtitle} + (if added? + (i18n/label :chat-is-a-contact) + (i18n/label :chat-is-not-a-contact))]])) (defview toolbar-content-view [] - (letsubs [{:keys [group-chat color online contacts chat-name contact public?]} - [:chats/current-chat] - sync-state [:sync-state]] - (let [has-subtitle? (or group-chat (not= :done sync-state))] - [react/view {:style st/toolbar-container} - [react/view {:margin-right 10} - [chat-icon.screen/chat-icon-view-toolbar contact group-chat chat-name color online]] - [react/view {:style st/chat-name-view} - [react/text {:style st/chat-name-text - :number-of-lines 1 - :accessibility-label :chat-name-text} - chat-name] - (when contact - [contact-indicator contact]) - (if group-chat - [group-last-activity {:contacts contacts - :public? public? - :sync-state sync-state}] - (when has-subtitle? - [last-activity {:sync-state sync-state - :accessibility-label :last-seen-text}]))]]))) + (letsubs [{:keys [group-chat + color + chat-id + contacts + chat-name + public?]} + [:chats/current-chat]] + [react/view {:style st/toolbar-container} + [react/view {:margin-right 10} + [chat-icon.screen/chat-icon-view-toolbar chat-id group-chat chat-name color]] + [react/view {:style st/chat-name-view} + [react/text {:style st/chat-name-text + :number-of-lines 1 + :accessibility-label :chat-name-text} + (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 + :public? public?}])]])) diff --git a/src/status_im/ui/screens/chat/utils.cljs b/src/status_im/ui/screens/chat/utils.cljs index 08c4142640..ce25f66ef0 100644 --- a/src/status_im/ui/screens/chat/utils.cljs +++ b/src/status_im/ui/screens/chat/utils.cljs @@ -4,30 +4,26 @@ [status-im.ui.components.react :as react] [status-im.ui.components.colors :as colors])) -(defn format-author [alias style name] +(defn format-author [contact-name style] (let [additional-styles (style false)] - (if name - (let [name (subs name 0 80)] + (if (= (aget contact-name 0) "@") + (let [trimmed-name (subs contact-name 0 81)] [react/text {:number-of-lines 2 :style (merge {:color colors/blue :font-size 13 :line-height 18 :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 :font-size 12 :line-height 18 :font-weight "400"} additional-styles)} - alias]))) + contact-name]))) (def ^:private reply-symbol "↪ ") -(defn format-reply-author [from alias 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) - [react/text {:style (style true)} - (str reply-symbol (i18n/label :t/You))]) - (format-author (subs reply-name 0 80) style false)))) \ No newline at end of file +(defn format-reply-author [from username current-public-key style] + (or (and (= from current-public-key) + [react/text {:style (style true)} + (str reply-symbol (i18n/label :t/You))]) + (format-author username style))) diff --git a/src/status_im/ui/screens/chat/views.cljs b/src/status_im/ui/screens/chat/views.cljs index ef47f28ab1..a225d02d6c 100644 --- a/src/status_im/ui/screens/chat/views.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -1,8 +1,6 @@ (ns status-im.ui.screens.chat.views (:require [re-frame.core :as re-frame] - [status-im.contact.db :as contact.db] [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.colors :as colors] [status-im.ui.components.connectivity.view :as connectivity] @@ -41,56 +39,86 @@ [sheets/actions current-chat]) :height 256}])}]}]) -(defn add-contact-bar - [public-key] - [react/touchable-highlight - {:on-press - #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key]) - :accessibility-label :add-to-contacts-button} - [react/view {:style (style/add-contact)} - [vector-icons/icon :main-icons/add - {:color colors/blue}] - [react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]]) +(defview add-contact-bar [public-key] + (letsubs [added? [:contacts/contact-added? public-key]] + (when-not added? + [react/touchable-highlight + {:on-press + #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key]) + :accessibility-label :add-to-contacts-button} + [react/view {:style (style/add-contact)} + [vector-icons/icon :main-icons/add + {:color colors/blue}] + [react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]]))) -(defn intro-header - [contact] +(defn intro-header [name] [react/text {:style (assoc style/intro-header-description :margin-bottom 32)} (str (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 - [{:keys [group-chat name pending-invite-inviter-name color chat-id chat-name - public? contact intro-status] :as chat} + [{:keys [group-chat + might-have-join-time-messages? + color chat-id chat-name + public?]} 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 - {:style {:flex 1 - :align-items :flex-start} - :on-press (fn [_] - (re-frame/dispatch - [:chat.ui/set-chat-ui-props {:input-bottom-sheet nil}]) - (react/dismiss-keyboard!))} - [react/view (style/intro-header-container intro-status no-messages) - ;; Icon section - [react/view {:style {:margin-top 42 - :margin-bottom 24}} - [chat-icon.screen/chat-intro-icon-view - icon-text chat-id - {: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 intro-name)] - ;; Description section - (if group-chat - [chat.group/group-chat-description-container chat] - [intro-header contact])]]))) + [react/touchable-without-feedback + {:style {:flex 1 + :align-items :flex-start} + :on-press (fn [_] + (re-frame/dispatch + [:chat.ui/set-chat-ui-props {:input-bottom-sheet nil}]) + (react/dismiss-keyboard!))} + (let [opts + {:chat-id chat-id + :group-chat group-chat + :chat-name chat-name + :public? public? + :color color + :loading-messages? might-have-join-time-messages? + :no-messages? no-messages}] + (if group-chat + [chat-intro opts] + [chat-intro-one-to-one opts]))]) (defonce messages-list-ref (atom nil)) @@ -110,15 +138,16 @@ (debounce/debounce-and-dispatch [:chat.ui/message-visibility-changed e] 5000)) (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] + no-messages? [:chats/current-chat-no-messages?] current-public-key [:multiaccount/public-key]] [list/flat-list {:key-fn #(or (:message-id %) (:value %)) :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]) - :footer [chat-intro-header-container chat (empty? messages)] + :footer [chat-intro-header-container chat no-messages?] :data messages :inverted true :render-fn (fn [{:keys [outgoing type] :as message} idx] @@ -154,14 +183,13 @@ [empty-bottom-sheet]))) (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]] [react/view {:style {:flex 1}} [connectivity/connectivity [topbar current-chat] [react/view {:style {:flex 1}} - ;;TODO contact.db/added? looks weird here, move to events - (when (and (not group-chat) (not (contact.db/added? contact))) + (when-not group-chat [add-contact-bar chat-id]) [messages-view current-chat]]] (when show-input? diff --git a/src/status_im/ui/screens/ens/views.cljs b/src/status_im/ui/screens/ens/views.cljs index ffd399cc3f..6e2633dba0 100644 --- a/src/status_im/ui/screens/ens/views.cljs +++ b/src/status_im/ui/screens/ens/views.cljs @@ -18,7 +18,9 @@ [status-im.ui.components.radio :as radio] [status-im.ui.components.react :as react] [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.styles.message.message :as message.style] [status-im.ui.screens.chat.photos :as photos] [status-im.ui.screens.profile.components.views :as profile.components] [status-im.utils.debounce :as debounce]) @@ -624,7 +626,11 @@ [name-item {:name name :hide-chevron? true :action action}]] [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/scroll-view [react/view {:style {:margin-top 8}} @@ -663,7 +669,7 @@ :timestamp-str "9:41 AM"}] [react/view [react/view {:padding-left 72} - [message/message-author-name public-key]] + [my-name]] [react/view {:flex-direction :row} [react/view {:padding-left 16 :padding-right 8 :padding-top 4} [photos/photo (multiaccounts/displayed-photo account) {:size 36}]] diff --git a/src/status_im/ui/screens/home/views/inner_item.cljs b/src/status_im/ui/screens/home/views/inner_item.cljs index 7d8227bc22..6b88030b15 100644 --- a/src/status_im/ui/screens/home/views/inner_item.cljs +++ b/src/status_im/ui/screens/home/views/inner_item.cljs @@ -15,8 +15,8 @@ (:require-macros [status-im.utils.views :refer [defview letsubs]])) (defview mention-element [from] - (letsubs [{:keys [ens-name alias]} [:contacts/contact-name-by-identity from]] - (if ens-name (str "@" ens-name) alias))) + (letsubs [contact-name [:contacts/contact-name-by-identity from]] + contact-name)) (defn render-subheader-inline [acc {:keys [type destination literal children]}] (case type @@ -108,20 +108,20 @@ (defn home-list-item [[_ home-item]] (let [{:keys [chat-id chat-name color online group-chat - public? contact timestamp last-message]} + public? timestamp last-message]} home-item private-group? (and group-chat (not public?)) - public-group? (and group-chat public?) - ;;TODO (perf) move to event - truncated-chat-name (utils/truncate-str chat-name 30)] + public-group? (and group-chat public?)] [list-item/list-item {: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 private-group? :main-icons/tiny-group public-group? :main-icons/tiny-public :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-row-accessory [message-timestamp (if (pos? (:whisper-timestamp last-message)) (:whisper-timestamp last-message)