mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-13 18:25:45 +00:00
feat: new delete message (#14232)
This commit is contained in:
parent
9be8a5b961
commit
bd84a36582
BIN
resources/images/icons2/16x16/sad-face@2x.png
Normal file
BIN
resources/images/icons2/16x16/sad-face@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
resources/images/icons2/16x16/sad-face@3x.png
Normal file
BIN
resources/images/icons2/16x16/sad-face@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@ -1,11 +1,11 @@
|
||||
(ns quo2.components.messages.system-message
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[quo2.theme :as theme]
|
||||
[quo2.components.avatars.icon-avatar :as icon-avatar]
|
||||
(:require [quo2.components.avatars.icon-avatar :as icon-avatar]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.theme :as theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[utils.string :as utils]))
|
||||
|
||||
(def themes-landed {:pinned colors/primary-50-opa-5
|
||||
@ -60,19 +60,19 @@
|
||||
:flex-direction :row}
|
||||
[rn/view {:align-items :center
|
||||
:flex-direction :row}
|
||||
[sm-icon {:icon :main-icons/delete16
|
||||
[sm-icon {:icon :main-icons/delete
|
||||
:color :danger
|
||||
:opacity 5}]
|
||||
[text/text {:size :paragraph-2
|
||||
:style {:color (get-color :text)
|
||||
:margin-right 5}}
|
||||
(or label (:message-deleted labels))]
|
||||
(or (get labels label) label (:message-deleted labels))]
|
||||
[sm-timestamp timestamp-str]]])
|
||||
|
||||
(defmethod sm-render :added [{:keys [state mentions timestamp-str labels]}]
|
||||
[rn/view {:align-items :center
|
||||
:flex-direction :row}
|
||||
[sm-icon {:icon :main-icons/add-user16
|
||||
[sm-icon {:icon :main-icons/add-user
|
||||
:color :primary
|
||||
:opacity (if (= state :landed) 0 5)}]
|
||||
[sm-user-avatar (:image (first mentions))]
|
||||
@ -94,7 +94,7 @@
|
||||
[rn/view {:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :center}
|
||||
[sm-icon {:icon :main-icons/pin16
|
||||
[sm-icon {:icon :main-icons/pin
|
||||
:color :primary
|
||||
:opacity (if (= state :landed) 0 5)}]
|
||||
[rn/view {:flex-direction :column
|
||||
|
@ -3,6 +3,8 @@
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.multiaccounts.model :as multiaccounts.model]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.chat.models.delete-message :as delete-message]
|
||||
[status-im.chat.models.delete-message-for-me :as delete-for-me]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
@ -212,6 +214,8 @@
|
||||
(when-let [chat-id (:current-chat-id db)]
|
||||
(chat.state/reset-visible-item)
|
||||
(fx/merge cofx
|
||||
(delete-for-me/sync-all)
|
||||
(delete-message/send-all)
|
||||
{:db (dissoc db :current-chat-id)}
|
||||
(offload-messages chat-id))))
|
||||
|
||||
|
109
src/status_im/chat/models/delete_message.cljs
Normal file
109
src/status_im/chat/models/delete_message.cljs
Normal file
@ -0,0 +1,109 @@
|
||||
(ns status-im.chat.models.delete-message
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.chat.models.pin-message :as models.pin-message]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.encore :as enc]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn- update-db-clear-undo-timer
|
||||
[db chat-id message-id]
|
||||
(when (get-in db [:messages chat-id message-id])
|
||||
(update-in db
|
||||
[:messages chat-id message-id]
|
||||
dissoc
|
||||
:deleted-undoable-till)))
|
||||
|
||||
(defn- update-db-delete-locally
|
||||
"Delete message in re-frame db and set the undo timelimit"
|
||||
[db chat-id message-id undo-time-limit-ms]
|
||||
(when (get-in db [:messages chat-id message-id])
|
||||
(update-in db
|
||||
[:messages chat-id message-id]
|
||||
assoc
|
||||
:deleted? true
|
||||
:deleted-undoable-till (+ (datetime/timestamp)
|
||||
undo-time-limit-ms))))
|
||||
|
||||
(defn- update-db-undo-locally
|
||||
"Restore deleted message if called within timelimit"
|
||||
[db chat-id message-id]
|
||||
(let [{:keys [deleted? deleted-undoable-till]}
|
||||
(get-in db [:messages chat-id message-id])]
|
||||
(if (and deleted?
|
||||
(> deleted-undoable-till (datetime/timestamp)))
|
||||
(update-in db
|
||||
[:messages chat-id message-id]
|
||||
dissoc
|
||||
:deleted?
|
||||
:deleted-undoable-till)
|
||||
(update-db-clear-undo-timer db chat-id message-id))))
|
||||
|
||||
(defn- update-db-delete-locally-without-time-limit
|
||||
"Delete message in re-frame db, used to handle received removed-messages"
|
||||
[db chat-id message-id]
|
||||
(when (get-in db [:messages chat-id message-id])
|
||||
(update-in db [:messages chat-id message-id] assoc :deleted? true)))
|
||||
|
||||
(fx/defn delete
|
||||
"Delete message now locally and broadcast after undo time limit timeout"
|
||||
{:events [:chat.ui/delete-message]}
|
||||
[{:keys [db]} {:keys [chat-id message-id]} undo-time-limit-ms]
|
||||
(when (get-in db [:messages chat-id message-id])
|
||||
(assoc
|
||||
(message-list/rebuild-message-list
|
||||
{:db (update-db-delete-locally db chat-id message-id undo-time-limit-ms)}
|
||||
chat-id)
|
||||
:utils/dispatch-later [{:dispatch [:chat.ui/delete-message-and-send
|
||||
{:chat-id chat-id
|
||||
:message-id message-id}]
|
||||
:ms undo-time-limit-ms}])))
|
||||
|
||||
(fx/defn undo
|
||||
{:events [:chat.ui/undo-delete-message]}
|
||||
[{:keys [db]} {:keys [chat-id message-id]}]
|
||||
(when (get-in db [:messages chat-id message-id])
|
||||
(message-list/rebuild-message-list
|
||||
{:db (update-db-undo-locally db chat-id message-id)}
|
||||
chat-id)))
|
||||
|
||||
(fx/defn delete-and-send
|
||||
{:events [:chat.ui/delete-message-and-send]}
|
||||
[{:keys [db]} {:keys [message-id chat-id]}]
|
||||
(when-let [message (get-in db [:messages chat-id message-id])]
|
||||
(enc/assoc-when
|
||||
{:db (update-db-clear-undo-timer db chat-id message-id)
|
||||
::json-rpc/call [{:method "wakuext_deleteMessageAndSend"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to delete message " {:message-id message-id :error %})
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}
|
||||
:dispatch (and (get-in db [:pin-messages chat-id message-id])
|
||||
[::models.pin-message/send-pin-message {:chat-id chat-id :message-id message-id :pinned false}]))))
|
||||
|
||||
(defn- filter-pending-send-messages
|
||||
"traverse all messages find not yet synced deleted? messages"
|
||||
[acc chat-id messages]
|
||||
(->> messages
|
||||
(filter (fn [[_ {:keys [deleted? deleted-undoable-till]}]] (and deleted? deleted-undoable-till)))
|
||||
(map (fn [message] {:chat-id chat-id :message-id (first message)}))
|
||||
(concat acc)))
|
||||
|
||||
(fx/defn send-all
|
||||
"Get all deleted messages that not yet synced with status-go and send them"
|
||||
{:events [:chat.ui/send-all-deleted-messages]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pending-send-messages (reduce-kv filter-pending-send-messages [] (:messages db))]
|
||||
(apply fx/merge cofx (map delete-and-send pending-send-messages))))
|
||||
|
||||
(fx/defn delete-messages-localy
|
||||
"Mark messages :deleted? localy in client"
|
||||
{:events [:chat.ui/delete-messages-localy]}
|
||||
[{:keys [db]} messages chat-id]
|
||||
(let [new-db (->> messages
|
||||
(filter #(get-in db [:messages chat-id (:message-id %)]))
|
||||
(reduce #(update-db-delete-locally-without-time-limit %1 chat-id (:message-id %2)) db))]
|
||||
(when new-db
|
||||
(message-list/rebuild-message-list {:db new-db} chat-id))))
|
@ -69,22 +69,20 @@
|
||||
::json-rpc/call [{:method "wakuext_deleteMessageForMeAndSync"
|
||||
:params [chat-id message-id]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to delete message for me " %)
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response
|
||||
%])}]}))
|
||||
(defn- chats-reducer
|
||||
"traverse all messages find not yet synced deleted-for-me? messages, generate dispatch vector"
|
||||
:on-error #(log/error "failed to delete message for me, message id: " {:message-id message-id :error %})
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}))
|
||||
|
||||
(defn- filter-pending-sync-messages
|
||||
"traverse all messages find not yet synced deleted-for-me? messages"
|
||||
[acc chat-id messages]
|
||||
(reduce-kv
|
||||
(fn [inner-acc message-id {:keys [deleted-for-me? deleted-for-me-undoable-till]}]
|
||||
(if (and deleted-for-me? deleted-for-me-undoable-till)
|
||||
(conj inner-acc [:chat.ui/delete-message-for-me-and-sync chat-id message-id])
|
||||
inner-acc))
|
||||
acc
|
||||
messages))
|
||||
(->> messages
|
||||
(filter (fn [[_ {:keys [deleted-for-me? deleted-for-me-undoable-till]}]] (and deleted-for-me? deleted-for-me-undoable-till)))
|
||||
(map (fn [message] {:chat-id chat-id :message-id (first message)}))
|
||||
(concat acc)))
|
||||
|
||||
(fx/defn sync-all
|
||||
"Get all deleted-for-me messages that not yet synced with status-go and sync them"
|
||||
{:events [:chat.ui/sync-all-deleted-for-me-messages]}
|
||||
[{:keys [db]}]
|
||||
{:dispatch-n (reduce-kv chats-reducer [] (:messages db))})
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [pending-sync-messages (reduce-kv filter-pending-sync-messages [] (:messages db))]
|
||||
(apply fx/merge cofx (map delete-and-sync pending-sync-messages))))
|
||||
|
@ -4,94 +4,97 @@
|
||||
delete-message-for-me]
|
||||
[status-im.utils.datetime :as datetime]))
|
||||
|
||||
(defonce mid "message-id")
|
||||
(defonce cid "chat-id")
|
||||
(def mid "message-id")
|
||||
(def cid "chat-id")
|
||||
|
||||
(deftest delete-for-me
|
||||
(with-redefs [datetime/timestamp (constantly 1)]
|
||||
(let [db {:messages {cid {mid {:id mid :whisper-timestamp 1}}}}
|
||||
message {:message-id mid :chat-id cid}]
|
||||
(testing "delete for me"
|
||||
(let [result-message (get-in (delete-message-for-me/delete {:db db} message 1000)
|
||||
(testing "dispatch right db fx"
|
||||
(let [result-message (get-in (delete-message-for-me/delete {:db db} message 1000)
|
||||
[:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (true? (:deleted-for-me? result-message)))
|
||||
(is (= (:deleted-for-me-undoable-till result-message) 1001))))
|
||||
(testing "should return nil if message not in db"
|
||||
(is (= (delete-message-for-me/delete {:db {:messages []}} message 1000)
|
||||
nil))))))
|
||||
(is (= (:id result-message) mid))
|
||||
(is (true? (:deleted-for-me? result-message)))
|
||||
(is (= (:deleted-for-me-undoable-till result-message) 1001))))
|
||||
(testing "return nil if message not in db"
|
||||
(is (= (delete-message-for-me/delete {:db {:messages []}} message 1000)
|
||||
nil)))))))
|
||||
|
||||
(deftest undo-delete-for-me
|
||||
(let [db {:messages {cid {mid {:id mid :whisper-timestamp 1}}}}
|
||||
message {:message-id mid :chat-id cid}]
|
||||
(testing "undo delete for me in time"
|
||||
(let [db (update-in db
|
||||
[:messages cid mid]
|
||||
assoc
|
||||
:deleted-for-me? true
|
||||
:deleted-for-me-undoable-till
|
||||
(+ (datetime/timestamp) 1000))
|
||||
result-message (get-in (delete-message-for-me/undo {:db db} message)
|
||||
[:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (nil? (:deleted-for-me? result-message)))
|
||||
(is (nil? (:deleted-for-me-undoable-till result-message)))))
|
||||
(testing "undo delete for me"
|
||||
(testing "in time"
|
||||
(let [db (update-in db
|
||||
[:messages cid mid]
|
||||
assoc
|
||||
:deleted-for-me? true
|
||||
:deleted-for-me-undoable-till
|
||||
(+ (datetime/timestamp) 1000))
|
||||
result-message (get-in (delete-message-for-me/undo {:db db} message)
|
||||
[:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (nil? (:deleted-for-me? result-message)))
|
||||
(is (nil? (:deleted-for-me-undoable-till result-message)))))
|
||||
|
||||
(testing "remain deleted for me when undo delete for me late"
|
||||
(let [db (update-in db
|
||||
[:messages cid mid]
|
||||
assoc
|
||||
:deleted-for-me? true
|
||||
:deleted-for-me-undoable-till (- (datetime/timestamp) 1000))
|
||||
result-message (get-in (delete-message-for-me/undo {:db db} message) [:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (nil? (:deleted-for-me-undoable-till result-message)))
|
||||
(is (true? (:deleted-for-me? result-message)))))
|
||||
(testing "remain deleted for me when undo after timelimit"
|
||||
(let [db (update-in db
|
||||
[:messages cid mid]
|
||||
assoc
|
||||
:deleted-for-me? true
|
||||
:deleted-for-me-undoable-till (- (datetime/timestamp) 1000))
|
||||
result-message (get-in (delete-message-for-me/undo {:db db} message) [:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (nil? (:deleted-for-me-undoable-till result-message)))
|
||||
(is (true? (:deleted-for-me? result-message)))))
|
||||
|
||||
(testing "should return nil if message not in db"
|
||||
(is (= (delete-message-for-me/undo {:db {:messages []}} message)
|
||||
nil)))))
|
||||
(testing "return nil if message not in db"
|
||||
(is (= (delete-message-for-me/undo {:db {:messages []}} message)
|
||||
nil))))))
|
||||
|
||||
(deftest delete-for-me-and-sync
|
||||
(let [db {:messages {cid {mid {:id mid}}}}
|
||||
message {:message-id mid :chat-id cid}]
|
||||
(testing "delete for me and sync"
|
||||
(let [expected-db {:messages {cid {mid {:id mid}}}}
|
||||
effects (delete-message-for-me/delete-and-sync {:db db} message)
|
||||
result-db (:db effects)
|
||||
rpc-calls (:status-im.ethereum.json-rpc/call effects)]
|
||||
(is (= result-db expected-db))
|
||||
(is (= (count rpc-calls) 1))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:method)
|
||||
"wakuext_deleteMessageForMeAndSync"))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
count)
|
||||
2))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
first)
|
||||
cid))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
second)
|
||||
mid))))
|
||||
(testing "delete for me and sync, should clean undo timer"
|
||||
(let [expected-db {:messages {cid {mid {:id mid}}}}
|
||||
effects (delete-message-for-me/delete-and-sync
|
||||
{:db (update-in db
|
||||
[:messages cid mid
|
||||
:deleted-for-me-undoable-till]
|
||||
(constantly (datetime/timestamp)))}
|
||||
message)
|
||||
result-db (:db effects)]
|
||||
(is (= result-db expected-db))))
|
||||
(testing "should return nil if message not in db"
|
||||
(is (= (delete-message-for-me/delete-and-sync {:db {:messages []}}
|
||||
message)
|
||||
nil)))))
|
||||
(testing "dispatch right rpc call"
|
||||
(let [expected-db {:messages {cid {mid {:id mid}}}}
|
||||
effects (delete-message-for-me/delete-and-sync {:db db} message)
|
||||
result-db (:db effects)
|
||||
rpc-calls (:status-im.ethereum.json-rpc/call effects)]
|
||||
(is (= result-db expected-db))
|
||||
(is (= (count rpc-calls) 1))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:method)
|
||||
"wakuext_deleteMessageForMeAndSync"))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
count)
|
||||
2))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
first)
|
||||
cid))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
second)
|
||||
mid))))
|
||||
(testing "clean undo timer"
|
||||
(let [expected-db {:messages {cid {mid {:id mid}}}}
|
||||
effects (delete-message-for-me/delete-and-sync
|
||||
{:db (update-in db
|
||||
[:messages cid mid
|
||||
:deleted-for-me-undoable-till]
|
||||
(constantly (datetime/timestamp)))}
|
||||
message)
|
||||
result-db (:db effects)]
|
||||
(is (= result-db expected-db))))
|
||||
(testing "return nil if message not in db"
|
||||
(is (= (delete-message-for-me/delete-and-sync {:db {:messages []}}
|
||||
message)
|
||||
nil))))))
|
||||
|
95
src/status_im/chat/models/delete_message_test.cljs
Normal file
95
src/status_im/chat/models/delete_message_test.cljs
Normal file
@ -0,0 +1,95 @@
|
||||
(ns status-im.chat.models.delete-message-test
|
||||
(:require
|
||||
[cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.chat.models.delete-message :as delete-message]
|
||||
[status-im.utils.datetime :as datetime]))
|
||||
|
||||
(def mid "message-id")
|
||||
(def cid "chat-id")
|
||||
|
||||
(deftest delete
|
||||
(with-redefs [datetime/timestamp (constantly 1)]
|
||||
(let [db {:messages {cid {mid {:id mid :whisper-timestamp 1}}}}
|
||||
message {:message-id mid :chat-id cid}]
|
||||
(testing "delete"
|
||||
(testing "dispatch right db fx"
|
||||
(let [result-message (get-in (delete-message/delete {:db db} message 1000)
|
||||
[:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (true? (:deleted? result-message)))
|
||||
(is (= (:deleted-undoable-till result-message) 1001))))
|
||||
(testing "return nil if message not in db"
|
||||
(is (= (delete-message/delete {:db {:messages []}} message 1000)
|
||||
nil)))))))
|
||||
|
||||
(deftest undo-delete
|
||||
(let [db {:messages {cid {mid {:id mid :whisper-timestamp 1}}}}
|
||||
message {:message-id mid :chat-id cid}]
|
||||
(testing "undo delete"
|
||||
(testing "undo in time"
|
||||
(let [db (update-in db
|
||||
[:messages cid mid]
|
||||
assoc
|
||||
:deleted? true
|
||||
:deleted-undoable-till
|
||||
(+ (datetime/timestamp) 1000))
|
||||
result-message (get-in (delete-message/undo {:db db} message)
|
||||
[:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (nil? (:deleted? result-message)))
|
||||
(is (nil? (:deleted-undoable-till result-message)))))
|
||||
|
||||
(testing "remain deleted when undo after timelimit"
|
||||
(let [db (update-in db
|
||||
[:messages cid mid]
|
||||
assoc
|
||||
:deleted? true
|
||||
:deleted-undoable-till (- (datetime/timestamp) 1000))
|
||||
result-message (get-in (delete-message/undo {:db db} message) [:db :messages cid mid])]
|
||||
(is (= (:id result-message) mid))
|
||||
(is (nil? (:deleted-undoable-till result-message)))
|
||||
(is (true? (:deleted? result-message)))))
|
||||
|
||||
(testing "return nil if message not in db"
|
||||
(is (= (delete-message/undo {:db {:messages []}} message)
|
||||
nil))))))
|
||||
|
||||
(deftest delete-and-send
|
||||
(let [db {:messages {cid {mid {:id mid}}}}
|
||||
message {:message-id mid :chat-id cid}]
|
||||
(testing "delete and send"
|
||||
(testing "dispatch right rpc call fx"
|
||||
(let [expected-db {:messages {cid {mid {:id mid}}}}
|
||||
effects (delete-message/delete-and-send {:db db} message)
|
||||
result-db (:db effects)
|
||||
rpc-calls (:status-im.ethereum.json-rpc/call effects)]
|
||||
(is (= result-db expected-db))
|
||||
(is (= (count rpc-calls) 1))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:method)
|
||||
"wakuext_deleteMessageAndSend"))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
count)
|
||||
1))
|
||||
(is (= (-> rpc-calls
|
||||
first
|
||||
:params
|
||||
first)
|
||||
mid))))
|
||||
(testing "clean undo timer"
|
||||
(let [expected-db {:messages {cid {mid {:id mid}}}}
|
||||
effects (delete-message/delete-and-send
|
||||
{:db (update-in db
|
||||
[:messages cid mid
|
||||
:deleted-undoable-till]
|
||||
(constantly (datetime/timestamp)))}
|
||||
message)
|
||||
result-db (:db effects)]
|
||||
(is (= result-db expected-db))))
|
||||
(testing "return nil if message not in db"
|
||||
(is (= (delete-message/delete-and-send {:db {:messages []}}
|
||||
message)
|
||||
nil))))))
|
@ -1,20 +1,20 @@
|
||||
(ns status-im.chat.models.input
|
||||
(:require [clojure.string :as string]
|
||||
(:require ["emojilib" :as emojis]
|
||||
[clojure.string :as string]
|
||||
[goog.object :as object]
|
||||
[re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.chat.models.message-content :as message-content]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.utils.fx :as fx]
|
||||
["emojilib" :as emojis]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.utils.utils :as utils]))
|
||||
[status-im.utils.utils :as utils]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn text->emoji
|
||||
"Replaces emojis in a specified `text`"
|
||||
@ -134,16 +134,6 @@
|
||||
(update-in [:chat/inputs current-chat-id :metadata]
|
||||
dissoc :sending-image))}))
|
||||
|
||||
(fx/defn soft-delete-message
|
||||
"Does't delete from db, this is a soft delete"
|
||||
{:events [:chat.ui/soft-delete-message]}
|
||||
[{:keys [db] :as cofx} {:keys [message-id chat-id]}]
|
||||
{::json-rpc/call [{:method "wakuext_deleteMessageAndSend"
|
||||
:params [message-id]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to delete message message " %)
|
||||
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
|
||||
|
||||
(fx/defn show-contact-request-input
|
||||
"Sets reference to previous chat message and focuses on input"
|
||||
{:events [:chat.ui/send-contact-request]}
|
||||
|
@ -1,20 +1,21 @@
|
||||
(ns status-im.chat.models.message
|
||||
(:require [status-im.chat.models :as chat-model]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.models.delete-message :as delete-message]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.chat.models.message-list :as message-list]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.ui.screens.chat.state :as view.state]
|
||||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.gfycat.core :as gfycat]))
|
||||
[status-im.utils.types :as types]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn- message-loaded?
|
||||
[db chat-id message-id]
|
||||
@ -181,15 +182,6 @@
|
||||
:on-error #(log/error "failed to re-send message" %)}]}
|
||||
(update-message-status chat-id message-id :sending)))
|
||||
|
||||
(fx/defn delete-message
|
||||
"Deletes chat message, rebuild message-list"
|
||||
{:events [:chat.ui/delete-message]}
|
||||
[{:keys [db] :as cofx} chat-id message-id]
|
||||
(fx/merge cofx
|
||||
{:db (update-in db [:messages chat-id] dissoc message-id)}
|
||||
(data-store.messages/delete-message message-id)
|
||||
(message-list/rebuild-message-list chat-id)))
|
||||
|
||||
(fx/defn send-message
|
||||
[cofx message]
|
||||
(protocol/send-chat-messages cofx [message]))
|
||||
@ -201,19 +193,23 @@
|
||||
(fx/defn handle-removed-messages
|
||||
{:events [::handle-removed-messages]}
|
||||
[{:keys [db] :as cofx} removed-messages]
|
||||
(let [mark-as-seen-fx (mapv (fn [removed-message]
|
||||
(let [chat-id (:chatId removed-message)
|
||||
message-id (:messageId removed-message)]
|
||||
(data-store.messages/mark-messages-seen chat-id
|
||||
[message-id]
|
||||
#(re-frame/dispatch [:chat/decrease-unviewed-count chat-id %3])))) removed-messages)
|
||||
(let [mark-as-deleted-fx (->> removed-messages
|
||||
(map #(assoc % :message-id (:messageId %)))
|
||||
(group-by :chatId)
|
||||
(mapv (fn [[chat-id messages]] (delete-message/delete-messages-localy messages chat-id))))
|
||||
mark-as-seen-fx (mapv (fn [removed-message]
|
||||
(let [chat-id (:chatId removed-message)
|
||||
message-id (:messageId removed-message)]
|
||||
(data-store.messages/mark-messages-seen chat-id
|
||||
[message-id]
|
||||
#(re-frame/dispatch [:chat/decrease-unviewed-count chat-id %3]))))
|
||||
removed-messages)
|
||||
remove-messages-fx (fn [{:keys [db]}]
|
||||
{:db (reduce (fn [acc current]
|
||||
(update-in acc [:messages (:chatId current)] dissoc (:messageId current)))
|
||||
db removed-messages)
|
||||
:dispatch-n [[:get-activity-center-notifications]
|
||||
{:dispatch-n [[:get-activity-center-notifications]
|
||||
[:get-activity-center-notifications-count]]})]
|
||||
(apply fx/merge cofx (conj mark-as-seen-fx remove-messages-fx))))
|
||||
(apply fx/merge cofx (-> mark-as-deleted-fx
|
||||
(concat mark-as-seen-fx)
|
||||
(conj remove-messages-fx)))))
|
||||
|
||||
(comment
|
||||
(handle-removed-messages
|
||||
|
@ -1,9 +1,7 @@
|
||||
(ns status-im.chat.models.message-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.chat.models.message :as message]
|
||||
[status-im.chat.models.message-list :as models.message-list]
|
||||
[status-im.chat.models.loading :as loading]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.ui.screens.chat.state :as view.state]))
|
||||
|
||||
(deftest add-received-message-test
|
||||
@ -130,54 +128,3 @@
|
||||
{:chats {"a" {:deleted-at-clock-value 1}}}
|
||||
"a"
|
||||
0))))
|
||||
|
||||
(deftest delete-message
|
||||
(with-redefs [time/day-relative (constantly "day-relative")
|
||||
time/timestamp->time (constantly "timestamp")]
|
||||
(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 :messages "chat-id"]))))
|
||||
(is (= [{:one-to-one? false
|
||||
:message-id 0
|
||||
:whisper-timestamp 0
|
||||
:type :message
|
||||
:display-photo? true
|
||||
:system-message? false
|
||||
:last-in-group? true
|
||||
:datemark "day-relative"
|
||||
:clock-value 0
|
||||
:first-in-group? true
|
||||
:from nil
|
||||
:first-outgoing? false
|
||||
:outgoing-seen? false
|
||||
:timestamp-str "timestamp"
|
||||
:first? true
|
||||
:display-username? true
|
||||
:outgoing false}]
|
||||
(models.message-list/->seq
|
||||
(get-in fx1 [:db :message-lists "chat-id"]))))
|
||||
(is (= {}
|
||||
(get-in fx2 [:db :messages "chat-id"])))
|
||||
(is (= nil
|
||||
(get-in fx2 [:db :message-lists "chat-id"])))))))
|
||||
|
@ -197,8 +197,6 @@
|
||||
(def ^:const sticker-pack-status-pending 2)
|
||||
(def ^:const sticker-pack-status-owned 3)
|
||||
|
||||
(def ^:const delete-message-for-me-undo-time-limit-ms 4000)
|
||||
|
||||
(def ^:const community-member-role-all 1)
|
||||
(def ^:const community-member-role-manage-users 2)
|
||||
(def ^:const community-member-role-moderator 3)
|
||||
|
@ -32,6 +32,7 @@
|
||||
:quotedMessage :quoted-message
|
||||
:outgoingStatus :outgoing-status
|
||||
:audioDurationMs :audio-duration-ms
|
||||
:deleted :deleted?
|
||||
:deletedForMe :deleted-for-me?
|
||||
:new :new?})
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
[status-im.ui.screens.views :as views]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.encore :as enc]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(def debug? ^boolean js/goog.DEBUG)
|
||||
@ -439,6 +438,4 @@
|
||||
:community
|
||||
|
||||
:else
|
||||
:home))
|
||||
:dispatch-n (enc/conj-when []
|
||||
(and (= view-id :chat) [:chat.ui/sync-all-deleted-for-me-messages]))}))
|
||||
:home))}))
|
||||
|
@ -177,7 +177,7 @@
|
||||
:title (i18n/label :t/delete-message)
|
||||
:icon :main-icons/delete
|
||||
:accessibility-label :delete-transaccent-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-not-used-any-more chat-id message-id])}]]))
|
||||
|
||||
(defn image-long-press [{:keys [content identicon from outgoing cant-be-replied] :as message} hide]
|
||||
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
|
||||
|
@ -1,16 +1,17 @@
|
||||
(ns status-im.ui2.screens.chat.components.reply
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
(:require [clojure.string :as string]
|
||||
[quo.react-native :as rn]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.handlers :refer [<sub >evt]]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[quo2.components.buttons.button :as quo2.button]
|
||||
[clojure.string :as string]
|
||||
[quo2.components.icon :as quo2.icon]
|
||||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.ui2.screens.chat.composer.style :as styles]))
|
||||
[i18n.i18n :as i18n]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui2.screens.chat.composer.style :as styles]
|
||||
[status-im.utils.handlers :refer [<sub >evt]]))
|
||||
|
||||
(defn get-quoted-text-with-mentions [parsed-text]
|
||||
(string/join
|
||||
@ -43,8 +44,21 @@
|
||||
(i18n/label :t/You))
|
||||
(format-author username)))
|
||||
|
||||
; This component is also used for quoted pinned message as the UI is very similar
|
||||
(defn reply-message [{:keys [from identicon content-type contentType parsed-text content]} in-chat-input? pin?]
|
||||
(defn reply-deleted-message []
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
[quo2.icon/icon :sad-face {:size 16}]
|
||||
[quo2.text/text
|
||||
{:number-of-lines 1
|
||||
:size :label
|
||||
:weight :regular
|
||||
:accessibility-label :quoted-message
|
||||
:style {:text-transform :none
|
||||
:margin-left 4
|
||||
:margin-top 2}}
|
||||
(i18n/label :t/message-deleted)]])
|
||||
|
||||
(defn reply-message [{:keys [from identicon content-type contentType parsed-text content deleted? deleted-for-me?]} in-chat-input? pin?]
|
||||
(let [contact-name (<sub [:contacts/contact-name-by-identity from])
|
||||
current-public-key (<sub [:multiaccount/public-key])
|
||||
content-type (or content-type contentType)]
|
||||
@ -56,32 +70,35 @@
|
||||
;;TODO quo2 icon should be used
|
||||
[icons/icon :main-icons/connector {:color (colors/theme-colors colors/neutral-40 colors/neutral-60)
|
||||
:container-style {:position :absolute :left 10 :bottom -4 :width 16 :height 16}}])
|
||||
[rn/view {:style (styles/quoted-message pin?)}
|
||||
[photos/member-photo from identicon 16]
|
||||
[quo2.text/text {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style {:margin-left 4}}
|
||||
(format-reply-author from contact-name current-public-key)]
|
||||
[quo2.text/text
|
||||
{:number-of-lines 1
|
||||
:size :label
|
||||
:weight :regular
|
||||
:accessibility-label :quoted-message
|
||||
:ellipsize-mode :tail
|
||||
:style (merge
|
||||
{:text-transform :none
|
||||
:margin-left 4
|
||||
:margin-top 2}
|
||||
(when (or (= constants/content-type-image content-type)
|
||||
(= constants/content-type-sticker content-type)
|
||||
(= constants/content-type-audio content-type))
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}))}
|
||||
(case (or content-type contentType)
|
||||
constants/content-type-image "Image"
|
||||
constants/content-type-sticker "Sticker"
|
||||
constants/content-type-audio "Audio"
|
||||
(get-quoted-text-with-mentions (or parsed-text (:parsed-text content))))]]]
|
||||
(if (or deleted? deleted-for-me?)
|
||||
[rn/view {:style (styles/quoted-message pin?)}
|
||||
[reply-deleted-message]]
|
||||
[rn/view {:style (styles/quoted-message pin?)}
|
||||
[photos/member-photo from identicon 16]
|
||||
[quo2.text/text {:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style {:margin-left 4}}
|
||||
(format-reply-author from contact-name current-public-key)]
|
||||
[quo2.text/text
|
||||
{:number-of-lines 1
|
||||
:size :label
|
||||
:weight :regular
|
||||
:accessibility-label :quoted-message
|
||||
:ellipsize-mode :tail
|
||||
:style (merge
|
||||
{:text-transform :none
|
||||
:margin-left 4
|
||||
:margin-top 2}
|
||||
(when (or (= constants/content-type-image content-type)
|
||||
(= constants/content-type-sticker content-type)
|
||||
(= constants/content-type-audio content-type))
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}))}
|
||||
(case (or content-type contentType)
|
||||
constants/content-type-image "Image"
|
||||
constants/content-type-sticker "Sticker"
|
||||
constants/content-type-audio "Audio"
|
||||
(get-quoted-text-with-mentions (or parsed-text (:parsed-text content))))]])]
|
||||
(when in-chat-input?
|
||||
[quo2.button/button {:width 24
|
||||
:size 24
|
||||
|
@ -2,11 +2,16 @@
|
||||
(:require [quo.core :as quo]
|
||||
[quo.design-system.colors :as quo.colors]
|
||||
[quo.react-native :as rn]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.icon :as icons]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[quo2.components.messages.system-message :as system-message]
|
||||
[quo2.core :as quo2]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[quo2.foundations.typography :as typography]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.chat.models.delete-message]
|
||||
[status-im.chat.models.delete-message-for-me]
|
||||
[status-im.chat.models.images :as images]
|
||||
[status-im.chat.models.pin-message :as models.pin-message]
|
||||
@ -19,7 +24,6 @@
|
||||
[status-im.ui.components.fast-image :as fast-image]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui2.screens.chat.components.reaction-drawer :as reaction-drawer]
|
||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
||||
[status-im.ui.screens.chat.message.audio :as message.audio]
|
||||
[status-im.ui.screens.chat.message.command :as message.command]
|
||||
@ -32,17 +36,14 @@
|
||||
[status-im.ui.screens.chat.styles.photos :as photos.style]
|
||||
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||
[status-im.ui.screens.communities.icon :as communities.icon]
|
||||
[status-im.ui2.screens.chat.components.reaction-drawer :as reaction-drawer]
|
||||
[status-im.ui2.screens.chat.components.reply :as components.reply]
|
||||
[status-im.utils.config :as config]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.utils.security :as security]
|
||||
[quo2.components.icon :as icons]
|
||||
[status-im.utils.datetime :as time]
|
||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||
[quo2.components.markdown.text :as text]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.contexts.chat.home.chat-list-item.view :as home.chat-list-item]
|
||||
[quo2.core :as quo2])
|
||||
[utils.re-frame :as rf])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defview mention-element [from]
|
||||
@ -83,10 +84,12 @@
|
||||
:accessibility-label :message-timestamp}
|
||||
timestamp-str]])))
|
||||
|
||||
(defview quoted-message
|
||||
[_ reply pin?]
|
||||
[rn/view {:style (when-not pin? (style/quoted-message-container))}
|
||||
[components.reply/reply-message reply false pin?]])
|
||||
(defn quoted-message
|
||||
[{:keys [message-id chat-id]} reply pin?]
|
||||
(let [{:keys [deleted? deleted-for-me?]} (get @(re-frame/subscribe [:chats/chat-messages chat-id]) message-id)
|
||||
reply (assoc reply :deleted? deleted? :deleted-for-me? deleted-for-me?)]
|
||||
[rn/view {:style (when-not pin? (style/quoted-message-container))}
|
||||
[components.reply/reply-message reply false pin?]]))
|
||||
|
||||
(defn system-text? [content-type]
|
||||
(= content-type constants/content-type-system-text))
|
||||
@ -251,7 +254,7 @@
|
||||
|
||||
(defview community-content [{:keys [community-id] :as message}]
|
||||
(letsubs [{:keys [name description verified] :as community} [:communities/community community-id]
|
||||
communities-enabled? [:communities/enabled?]]
|
||||
communities-enabled? [:communities/enabled?]]
|
||||
(when (and communities-enabled? community)
|
||||
[rn/view {:style (assoc (style/message-wrapper message)
|
||||
:margin-vertical 10
|
||||
@ -304,29 +307,32 @@
|
||||
|
||||
(defn message-content-wrapper
|
||||
"Author, userpic and delivery wrapper"
|
||||
[{:keys [last-in-group? timestamp-str timestamp
|
||||
deleted-for-me? deleted-for-me-undoable-till pinned from]
|
||||
[{:keys [last-in-group? timestamp-str timestamp deleted? deleted-undoable-till
|
||||
deleted-for-me? deleted-for-me-undoable-till pinned from chat-id]
|
||||
:as message} content]
|
||||
(let [response-to (:response-to (:content message))
|
||||
display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
|
||||
contact (rf/sub [:contacts/contact-by-address from])
|
||||
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))
|
||||
online? (rf/sub [:visibility-status-updates/online? from])]
|
||||
(if deleted-for-me?
|
||||
(if (or deleted? deleted-for-me?)
|
||||
[system-message/system-message
|
||||
{:type :deleted
|
||||
:label (i18n/label :message-deleted-for-you)
|
||||
:labels {:pinned-a-message (i18n/label :pinned-a-message)
|
||||
:message-deleted (i18n/label :message-deleted)
|
||||
:added (i18n/label :added)}
|
||||
:label (if deleted? :message-deleted :message-deleted-for-you)
|
||||
:labels {:pinned-a-message (i18n/label :pinned-a-message)
|
||||
:message-deleted (i18n/label :message-deleted-for-everyone)
|
||||
:message-deleted-for-you (i18n/label :message-deleted-for-you)
|
||||
:added (i18n/label :added)}
|
||||
:timestamp-str timestamp-str
|
||||
:non-pressable? true
|
||||
:animate-landing? (if deleted-for-me-undoable-till true false)}]
|
||||
:animate-landing? (if (or deleted-undoable-till deleted-for-me-undoable-till)
|
||||
true
|
||||
false)}]
|
||||
[rn/view {:style (style/message-wrapper message)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label :chat-item}
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message)])
|
||||
[quoted-message {:message-id response-to :chat-id chat-id} (:quoted-message message)])
|
||||
[rn/view {:style (style/message-body)
|
||||
:pointer-events :box-none}
|
||||
[rn/view {:style {:width 40}}
|
||||
@ -444,20 +450,20 @@
|
||||
:label (i18n/label (if pinned (if community? :t/unpin-from-channel :t/unpin-from-chat) (if community? :t/pin-to-channel :t/pin-to-chat)))
|
||||
:icon :i/pin
|
||||
:id (if pinned :unpin :pin)}])
|
||||
[{:type :danger
|
||||
:on-press (fn []
|
||||
(when pinned (pin-message message))
|
||||
(re-frame/dispatch
|
||||
[:chat.ui/delete-message-for-me message
|
||||
constants/delete-message-for-me-undo-time-limit-ms]))
|
||||
:label (i18n/label :t/delete-for-me)
|
||||
:icon :i/delete
|
||||
:id :delete-for-me}]
|
||||
(when (and (or outgoing can-delete-message-for-everyone?) config/delete-message-enabled?)
|
||||
(when-not pinned
|
||||
[{:type :danger
|
||||
:on-press (fn []
|
||||
(when pinned (pin-message message))
|
||||
(re-frame/dispatch [:chat.ui/soft-delete-message message]))
|
||||
(re-frame/dispatch
|
||||
[:chat.ui/delete-message-for-me message
|
||||
config/delete-message-for-me-undo-time-limit-ms]))
|
||||
:label (i18n/label :t/delete-for-me)
|
||||
:icon :i/delete
|
||||
:id :delete-for-me}])
|
||||
(when (and (or outgoing can-delete-message-for-everyone?) config/delete-message-enabled?)
|
||||
[{:type :danger
|
||||
:on-press #(re-frame/dispatch [:chat.ui/delete-message
|
||||
message
|
||||
config/delete-message-undo-time-limit-ms])
|
||||
:label (i18n/label :t/delete-for-everyone)
|
||||
:icon :i/delete
|
||||
:id :delete-for-all}]))))
|
||||
@ -600,13 +606,15 @@
|
||||
[{:type :danger
|
||||
:on-press #(re-frame/dispatch
|
||||
[:chat.ui/delete-message-for-me message
|
||||
constants/delete-message-for-me-undo-time-limit-ms])
|
||||
config/delete-message-undo-time-limit-ms])
|
||||
:label (i18n/label :t/delete-for-me)
|
||||
:icon :i/delete
|
||||
:id :delete-for-me}]
|
||||
(when (and outgoing config/delete-message-enabled?)
|
||||
[{:type :danger
|
||||
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||
:on-press #(re-frame/dispatch [:chat.ui/delete-message
|
||||
message
|
||||
config/delete-message-undo-time-limit-ms])
|
||||
:label (i18n/label :t/delete-for-everyone)
|
||||
:icon :i/delete
|
||||
:id :delete}]))))]
|
||||
@ -637,13 +645,15 @@
|
||||
{:type :danger
|
||||
:on-press #(re-frame/dispatch
|
||||
[:chat.ui/delete-message-for-me message
|
||||
constants/delete-message-for-me-undo-time-limit-ms])
|
||||
config/delete-message-for-me-undo-time-limit-ms])
|
||||
:label (i18n/label :t/delete-for-me)
|
||||
:icon :i/delete
|
||||
:id :delete-for-me}
|
||||
(when (and outgoing config/delete-message-enabled?)
|
||||
{:type :danger
|
||||
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||
:on-press #(re-frame/dispatch [:chat.ui/delete-message
|
||||
message
|
||||
config/delete-message-undo-time-limit-ms])
|
||||
:label (i18n/label :t/delete-for-everyone)
|
||||
:icon :i/delete
|
||||
:id :delete})]))]
|
||||
@ -708,7 +718,7 @@
|
||||
[message-content-wrapper message
|
||||
[unknown-content-type message]])
|
||||
|
||||
(defn chat-message [{:keys [pinned pinned-by mentioned in-pinned-view? last-in-group?] :as message}]
|
||||
(defn chat-message [{:keys [pinned pinned-by mentioned in-pinned-view? last-in-group? deleted? deleted-for-me?] :as message}]
|
||||
(let [reactions @(re-frame/subscribe [:chats/message-reactions (:message-id message) (:chat-id message)])
|
||||
own-reactions (reduce (fn [acc {:keys [emoji-id own]}]
|
||||
(if own (conj acc emoji-id) acc))
|
||||
@ -742,13 +752,14 @@
|
||||
(when (or mentioned pinned last-in-group?) {:margin-top 8})
|
||||
{:margin-horizontal 8})}
|
||||
|
||||
(when pinned
|
||||
(when (and pinned (not (or deleted? deleted-for-me?)))
|
||||
[rn/view {:style (style/pin-indicator-container)}
|
||||
[pinned-by-indicator pinned-by]])
|
||||
[->message message {:ref on-long-press
|
||||
:modal false
|
||||
:on-long-press on-open-drawer}]
|
||||
[reaction-row/message-reactions message reactions nil on-emoji-press on-long-press]])) ;; TODO: pass on-open-drawer function
|
||||
(when-not (or deleted? deleted-for-me?)
|
||||
[reaction-row/message-reactions message reactions nil on-emoji-press on-long-press])])) ;; TODO: pass on-open-drawer function
|
||||
|
||||
(defn message-render-fn
|
||||
[{:keys [outgoing whisper-timestamp] :as message}
|
||||
@ -849,7 +860,7 @@
|
||||
(style/message-timestamp-text))
|
||||
:accessibility-label :message-timestamp}
|
||||
timestamp-str]]
|
||||
[quoted-message response-to (:quoted-message message) true]]]))
|
||||
[quoted-message {:message-id response-to :chat-id chat-id} (:quoted-message message) true]]]))
|
||||
|
||||
(defmethod ->message constants/content-type-system-text [{:keys [content quoted-message] :as message}]
|
||||
(if quoted-message
|
||||
|
@ -143,5 +143,8 @@
|
||||
|
||||
(def wallet-connect-project-id "87815d72a81d739d2a7ce15c2cfdefb3")
|
||||
|
||||
(def delete-message-undo-time-limit-ms 4000)
|
||||
(def delete-message-for-me-undo-time-limit-ms 4000)
|
||||
|
||||
;;TODO for development only should be removed in status 2.0
|
||||
(def new-ui-enabled? true)
|
||||
|
@ -1,10 +1,10 @@
|
||||
(ns status-im2.subs.chat.messages
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models.reactions :as models.reactions]
|
||||
[status-im.chat.models.message-list :as models.message-list]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.constants :as constants]))
|
||||
[status-im.chat.models.message-list :as models.message-list]
|
||||
[status-im.chat.models.reactions :as models.reactions]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.datetime :as datetime]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/chat-messages
|
||||
@ -14,18 +14,26 @@
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/pinned
|
||||
:<- [:messages/pin-messages]
|
||||
(fn [pin-messages [_ chat-id]]
|
||||
(get pin-messages chat-id {})))
|
||||
(fn [[_ chat-id] _]
|
||||
[(re-frame/subscribe [:messages/pin-messages])
|
||||
(re-frame/subscribe [:chats/chat-messages chat-id])])
|
||||
(fn [[pin-messages messages] [_ chat-id]]
|
||||
(let [pin-messages (get pin-messages chat-id {})]
|
||||
(reduce-kv (fn [acc message-id message]
|
||||
(let [{:keys [deleted? deleted-for-me?]} (get messages message-id)]
|
||||
(if (or deleted? deleted-for-me?)
|
||||
acc
|
||||
(assoc acc message-id message))))
|
||||
{} pin-messages))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/pinned-sorted-list
|
||||
:<- [:messages/pin-messages]
|
||||
(fn [pin-messages [_ chat-id]]
|
||||
(->>
|
||||
(get pin-messages chat-id {})
|
||||
vals
|
||||
(sort-by :pinned-at <))))
|
||||
(fn [[_ chat-id] _]
|
||||
(re-frame/subscribe [:chats/pinned chat-id]))
|
||||
(fn [pin-messages _]
|
||||
(->> pin-messages
|
||||
vals
|
||||
(sort-by :pinned-at <))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/pin-modal
|
||||
|
@ -3,7 +3,7 @@
|
||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.115.5",
|
||||
"commit-sha1": "684e9654de4800df619ce593b5d331ebea9ed1a8",
|
||||
"src-sha256": "0ci1s3w5jnf6sz2b6hn30gy14hp142gic006r6c3g5ln8y19wdbi"
|
||||
"version": "v0.115.6",
|
||||
"commit-sha1": "a97b5527305b9f23b15246c5489726f8cd758edd",
|
||||
"src-sha256": "18x506xrxbpabfy0vn82bzyd0f6zmr5khclqbzfwymi5d1m35cjm"
|
||||
}
|
||||
|
@ -876,6 +876,7 @@
|
||||
"members-title": "Members",
|
||||
"message": "Message",
|
||||
"message-deleted": "Message deleted",
|
||||
"message-deleted-for-everyone": "Message deleted for everyone",
|
||||
"message-deleted-for-you": "Message deleted for you",
|
||||
"message-not-sent": "Message not sent",
|
||||
"message-options-cancel": "Cancel",
|
||||
|
Loading…
x
Reference in New Issue
Block a user