feat: delete for me logic without UI (#14007)
This commit is contained in:
parent
d6a8f912ea
commit
bc050af9ed
|
@ -0,0 +1,68 @@
|
||||||
|
(ns status-im.chat.models.delete-message-for-me
|
||||||
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
|
[status-im.utils.datetime :as datetime]
|
||||||
|
[status-im.utils.fx :as fx]
|
||||||
|
[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-for-me-undoable-till)))
|
||||||
|
|
||||||
|
(defn- update-db-delete-locally
|
||||||
|
"Delete message for me 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-for-me? true
|
||||||
|
:deleted-for-me-undoable-till (+ (datetime/timestamp)
|
||||||
|
undo-time-limit-ms))))
|
||||||
|
|
||||||
|
(defn- update-db-undo-locally
|
||||||
|
"Restore deleted-for-me message if called within timelimit"
|
||||||
|
[db chat-id message-id]
|
||||||
|
(let [{:keys [deleted-for-me? deleted-for-me-undoable-till]}
|
||||||
|
(get-in db [:messages chat-id message-id])]
|
||||||
|
(if (and deleted-for-me?
|
||||||
|
(> deleted-for-me-undoable-till (datetime/timestamp)))
|
||||||
|
(update-in db
|
||||||
|
[:messages chat-id message-id]
|
||||||
|
dissoc
|
||||||
|
:deleted-for-me?
|
||||||
|
:deleted-for-me-undoable-till)
|
||||||
|
(update-db-clear-undo-timer db chat-id message-id))))
|
||||||
|
|
||||||
|
(fx/defn delete
|
||||||
|
"Delete message for me now locally and broadcast after undo time limit timeout"
|
||||||
|
{:events [:chat.ui/delete-message-for-me]}
|
||||||
|
[{:keys [db]} {:keys [chat-id message-id]} undo-time-limit-ms]
|
||||||
|
(when (get-in db [:messages chat-id message-id])
|
||||||
|
{:db (update-db-delete-locally db chat-id message-id undo-time-limit-ms)
|
||||||
|
:utils/dispatch-later [{:dispatch [:chat.ui/delete-message-for-me-and-sync
|
||||||
|
{:chat-id chat-id
|
||||||
|
:message-id message-id}]
|
||||||
|
:ms undo-time-limit-ms}]}))
|
||||||
|
|
||||||
|
(fx/defn undo
|
||||||
|
{:events [:chat.ui/undo-delete-message-for-me]}
|
||||||
|
[{:keys [db]} {:keys [chat-id message-id]}]
|
||||||
|
(when (get-in db [:messages chat-id message-id])
|
||||||
|
{:db (update-db-undo-locally db chat-id message-id)}))
|
||||||
|
|
||||||
|
(fx/defn delete-and-sync
|
||||||
|
{:events [:chat.ui/delete-message-for-me-and-sync]}
|
||||||
|
[{:keys [db]} {:keys [message-id chat-id]}]
|
||||||
|
(when (get-in db [:messages chat-id message-id])
|
||||||
|
{:db (update-db-clear-undo-timer db chat-id message-id)
|
||||||
|
::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
|
||||||
|
%])}]}))
|
|
@ -0,0 +1,113 @@
|
||||||
|
(ns status-im.chat.models.delete-message-for-me-test
|
||||||
|
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||||
|
[status-im.chat.models.delete-message-for-me :as
|
||||||
|
delete-message-for-me]
|
||||||
|
[status-im.utils.datetime :as datetime]))
|
||||||
|
|
||||||
|
(defonce mid "message-id")
|
||||||
|
(defonce cid "chat-id")
|
||||||
|
|
||||||
|
(deftest delete-for-me
|
||||||
|
(let [db {:messages {cid {mid {:id mid}}}}
|
||||||
|
message {:message-id mid :chat-id cid}]
|
||||||
|
(testing "delete for me"
|
||||||
|
(let [expected {:db {:messages {"chat-id" {"message-id"
|
||||||
|
{:id "message-id"
|
||||||
|
:deleted-for-me? true
|
||||||
|
:deleted-for-me-undoable-till
|
||||||
|
(+ (datetime/timestamp)
|
||||||
|
1000)}}}}
|
||||||
|
:utils/dispatch-later
|
||||||
|
[{:dispatch [:chat.ui/delete-message-for-me-and-sync
|
||||||
|
{:chat-id "chat-id" :message-id "message-id"}]
|
||||||
|
:ms 1000}]}]
|
||||||
|
(is (= (delete-message-for-me/delete {:db db} message 1000) expected))))
|
||||||
|
(testing "should return nil if message 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}}}}
|
||||||
|
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))
|
||||||
|
|
||||||
|
expected {:db {:messages {"chat-id" {"message-id"
|
||||||
|
{:id "message-id"}}}}}]
|
||||||
|
(is (= (delete-message-for-me/undo {:db db} message) expected))))
|
||||||
|
(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))
|
||||||
|
|
||||||
|
expected {:db {:messages {"chat-id" {"message-id" {:id "message-id"
|
||||||
|
:deleted-for-me?
|
||||||
|
true}}}}}]
|
||||||
|
(is (= (delete-message-for-me/undo {:db db} message) expected))))
|
||||||
|
(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))
|
||||||
|
|
||||||
|
expected {:db {:messages {"chat-id" {"message-id" {:id "message-id"
|
||||||
|
:deleted-for-me?
|
||||||
|
true}}}}}]
|
||||||
|
(is (= (delete-message-for-me/undo {:db db} message) expected))))
|
||||||
|
(testing "should return nil if message 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 {"chat-id" {"message-id" {:id "message-id"}}}}
|
||||||
|
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 {"chat-id" {"message-id" {:id "message-id"}}}}
|
||||||
|
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 in db"
|
||||||
|
(is (= (delete-message-for-me/delete-and-sync {:db {:messages []}}
|
||||||
|
message)
|
||||||
|
nil)))))
|
|
@ -31,6 +31,7 @@
|
||||||
:quotedMessage :quoted-message
|
:quotedMessage :quoted-message
|
||||||
:outgoingStatus :outgoing-status
|
:outgoingStatus :outgoing-status
|
||||||
:audioDurationMs :audio-duration-ms
|
:audioDurationMs :audio-duration-ms
|
||||||
|
:deletedForMe :deleted-for-me?
|
||||||
:new :new?})
|
:new :new?})
|
||||||
|
|
||||||
(update :quoted-message clojure.set/rename-keys {:parsedText :parsed-text :communityId :community-id})
|
(update :quoted-message clojure.set/rename-keys {:parsedText :parsed-text :communityId :community-id})
|
||||||
|
|
|
@ -1,34 +1,35 @@
|
||||||
(ns status-im.ui.screens.chat.message.message
|
(ns status-im.ui.screens.chat.message.message
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [quo.core :as quo]
|
||||||
|
[quo.design-system.colors :as colors]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[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]
|
||||||
|
[status-im.chat.models.reactions :as models.reactions]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.i18n.i18n :as i18n]
|
[status-im.i18n.i18n :as i18n]
|
||||||
[status-im.react-native.resources :as resources]
|
[status-im.react-native.resources :as resources]
|
||||||
[quo.design-system.colors :as colors]
|
[status-im.ui.components.animation :as animation]
|
||||||
|
[status-im.ui.components.fast-image :as fast-image]
|
||||||
[status-im.ui.components.icons.icons :as icons]
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
|
[status-im.ui.screens.chat.bottom-sheets.context-drawer :as message-context-drawer]
|
||||||
|
[status-im.ui.screens.chat.components.reply :as components.reply]
|
||||||
|
[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.audio :as message.audio]
|
||||||
[status-im.chat.models.reactions :as models.reactions]
|
|
||||||
[status-im.ui.screens.chat.message.command :as message.command]
|
[status-im.ui.screens.chat.message.command :as message.command]
|
||||||
|
[status-im.ui.screens.chat.message.gap :as message.gap]
|
||||||
|
[status-im.ui.screens.chat.message.link-preview :as link-preview]
|
||||||
|
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||||
|
[status-im.ui.screens.chat.message.reactions-row :as reaction-row]
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.screens.chat.photos :as photos]
|
||||||
[status-im.ui.screens.chat.sheets :as sheets]
|
[status-im.ui.screens.chat.sheets :as sheets]
|
||||||
[status-im.ui.screens.chat.message.gap :as message.gap]
|
|
||||||
[status-im.ui.screens.chat.styles.message.message :as style]
|
[status-im.ui.screens.chat.styles.message.message :as style]
|
||||||
[status-im.ui.screens.chat.utils :as chat.utils]
|
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||||
[status-im.utils.security :as security]
|
|
||||||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
|
||||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
|
||||||
[quo.core :as quo]
|
|
||||||
[status-im.utils.config :as config]
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[status-im.ui.screens.chat.components.reply :as components.reply]
|
|
||||||
[status-im.ui.screens.chat.message.link-preview :as link-preview]
|
|
||||||
[status-im.ui.screens.communities.icon :as communities.icon]
|
[status-im.ui.screens.communities.icon :as communities.icon]
|
||||||
[status-im.ui.components.animation :as animation]
|
[status-im.utils.config :as config]
|
||||||
[status-im.chat.models.images :as images]
|
[status-im.utils.security :as security])
|
||||||
[status-im.chat.models.pin-message :as models.pin-message]
|
|
||||||
[status-im.ui.components.fast-image :as fast-image]
|
|
||||||
[status-im.ui.screens.chat.bottom-sheets.context-drawer :as message-context-drawer]
|
|
||||||
[status-im.ui.screens.chat.message.reactions-row :as reaction-row])
|
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defn message-timestamp-anim
|
(defn message-timestamp-anim
|
||||||
|
@ -294,7 +295,8 @@
|
||||||
"Author, userpic and delivery wrapper"
|
"Author, userpic and delivery wrapper"
|
||||||
[{:keys [last-in-group?
|
[{:keys [last-in-group?
|
||||||
identicon
|
identicon
|
||||||
from in-popover? timestamp-str]
|
from in-popover? timestamp-str
|
||||||
|
deleted-for-me?]
|
||||||
:as message} content {:keys [modal close-modal]}]
|
:as message} content {:keys [modal close-modal]}]
|
||||||
(let [response-to (:response-to (:content message))]
|
(let [response-to (:response-to (:content message))]
|
||||||
[react/view {:style (style/message-wrapper message)
|
[react/view {:style (style/message-wrapper message)
|
||||||
|
@ -320,12 +322,17 @@
|
||||||
[react/text
|
[react/text
|
||||||
{:style (merge
|
{:style (merge
|
||||||
{:padding-left 5
|
{:padding-left 5
|
||||||
:margin-top 2}
|
:margin-top 2}
|
||||||
(style/message-timestamp-text))
|
(style/message-timestamp-text))
|
||||||
:accessibility-label :message-timestamp}
|
:accessibility-label :message-timestamp}
|
||||||
timestamp-str]])
|
timestamp-str]])
|
||||||
;;MESSAGE CONTENT
|
;; MESSAGE CONTENT
|
||||||
content
|
;; TODO(yqrashawn): wait for system message component to display deleted for me UI
|
||||||
|
(if deleted-for-me?
|
||||||
|
[react/view {:style {:border-width 2
|
||||||
|
:border-color :red}}
|
||||||
|
content]
|
||||||
|
content)
|
||||||
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
||||||
; delivery status
|
; delivery status
|
||||||
[react/view (style/delivery-status)
|
[react/view (style/delivery-status)
|
||||||
|
@ -436,6 +443,13 @@
|
||||||
:label (i18n/label (if pinned :t/unpin-from-chat :t/pin-to-chat))
|
:label (i18n/label (if pinned :t/unpin-from-chat :t/pin-to-chat))
|
||||||
:icon :main-icons/pin-context20
|
:icon :main-icons/pin-context20
|
||||||
:id (if pinned :unpin :pin)}])
|
:id (if pinned :unpin :pin)}])
|
||||||
|
[{:type :danger
|
||||||
|
:on-press #(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 :main-icons/delete-context20
|
||||||
|
:id :delete-for-me}]
|
||||||
(when (and outgoing config/delete-message-enabled?)
|
(when (and outgoing config/delete-message-enabled?)
|
||||||
[{:type :danger
|
[{:type :danger
|
||||||
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||||
|
@ -581,6 +595,13 @@
|
||||||
:id :share
|
:id :share
|
||||||
:icon :main-icons/share-context20
|
:icon :main-icons/share-context20
|
||||||
:label (i18n/label :t/share-image)}]
|
:label (i18n/label :t/share-image)}]
|
||||||
|
[{:type :danger
|
||||||
|
:on-press #(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 :main-icons/delete-context20
|
||||||
|
:id :delete-for-me}]
|
||||||
(when (and outgoing config/delete-message-enabled?)
|
(when (and outgoing config/delete-message-enabled?)
|
||||||
[{:type :danger
|
[{:type :danger
|
||||||
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||||
|
@ -611,6 +632,13 @@
|
||||||
:label (i18n/label (if pinned :t/unpin-from-chat :t/pin-to-chat))
|
:label (i18n/label (if pinned :t/unpin-from-chat :t/pin-to-chat))
|
||||||
:icon :main-icons/pin-context20
|
:icon :main-icons/pin-context20
|
||||||
:id (if pinned :unpin :pin)}
|
:id (if pinned :unpin :pin)}
|
||||||
|
{:type :danger
|
||||||
|
:on-press #(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 :main-icons/delete-context20
|
||||||
|
:id :delete-for-me}
|
||||||
(when (and outgoing config/delete-message-enabled?)
|
(when (and outgoing config/delete-message-enabled?)
|
||||||
{:type :danger
|
{:type :danger
|
||||||
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||||
|
@ -712,4 +740,4 @@
|
||||||
[reaction-row/message-reactions message reactions nil on-emoji-press on-long-press] ;; TODO: pass on-open-drawer function
|
[reaction-row/message-reactions message reactions nil on-emoji-press on-long-press] ;; TODO: pass on-open-drawer function
|
||||||
(when pinned
|
(when pinned
|
||||||
[react/view {:style (style/pin-indicator-container)}
|
[react/view {:style (style/pin-indicator-container)}
|
||||||
[pinned-by-indicator display-photo? pinned-by]])]))
|
[pinned-by-indicator display-photo? pinned-by]])]))
|
||||||
|
|
|
@ -182,3 +182,5 @@
|
||||||
;; usable enough to replace the old one **in the new UI**.
|
;; usable enough to replace the old one **in the new UI**.
|
||||||
(def new-activity-center-enabled?
|
(def new-activity-center-enabled?
|
||||||
(atom false))
|
(atom false))
|
||||||
|
|
||||||
|
(def delete-message-for-me-undo-time-limit-ms 4000)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.110.3",
|
"version": "f47cb8572de921fb4cff5d0f8d87b7b92386a226",
|
||||||
"commit-sha1": "506921509e477445a95e1961a2557ef584d7caec",
|
"commit-sha1": "f47cb8572de921fb4cff5d0f8d87b7b92386a226",
|
||||||
"src-sha256": "1xmngbfl67n031rxhhbs7m14gzmfhgr1d34szclf1a6qxb9kw946"
|
"src-sha256": "0wbiwq6dh531crqsij836bdkggn8f1z9f121aqpyxwdgp1njzxjk"
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,6 +418,7 @@
|
||||||
"delete-chat-confirmation": "Are you sure you want to delete this chat?",
|
"delete-chat-confirmation": "Are you sure you want to delete this chat?",
|
||||||
"delete-category-confirmation": "Are you sure you want to delete this category?",
|
"delete-category-confirmation": "Are you sure you want to delete this category?",
|
||||||
"delete-confirmation": "Delete?",
|
"delete-confirmation": "Delete?",
|
||||||
|
"delete-for-me": "Delete for me",
|
||||||
"delete-mailserver": "Delete Status node",
|
"delete-mailserver": "Delete Status node",
|
||||||
"delete-mailserver-are-you-sure": "Are you sure you want to delete this Status node?",
|
"delete-mailserver-are-you-sure": "Are you sure you want to delete this Status node?",
|
||||||
"delete-mailserver-title": "Delete Status node",
|
"delete-mailserver-title": "Delete Status node",
|
||||||
|
|
Loading…
Reference in New Issue