feat: delete for me logic without UI (#14007)

This commit is contained in:
yqrashawn 2022-10-12 21:21:20 +08:00 committed by GitHub
parent d6a8f912ea
commit bc050af9ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 239 additions and 26 deletions

View File

@ -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
%])}]}))

View File

@ -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)))))

View File

@ -31,6 +31,7 @@
:quotedMessage :quoted-message
:outgoingStatus :outgoing-status
:audioDurationMs :audio-duration-ms
:deletedForMe :deleted-for-me?
:new :new?})
(update :quoted-message clojure.set/rename-keys {:parsedText :parsed-text :communityId :community-id})

View File

@ -1,34 +1,35 @@
(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.i18n.i18n :as i18n]
[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.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.chat.models.reactions :as models.reactions]
[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.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.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.components.animation :as animation]
[status-im.chat.models.images :as images]
[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])
[status-im.utils.config :as config]
[status-im.utils.security :as security])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn message-timestamp-anim
@ -294,7 +295,8 @@
"Author, userpic and delivery wrapper"
[{:keys [last-in-group?
identicon
from in-popover? timestamp-str]
from in-popover? timestamp-str
deleted-for-me?]
:as message} content {:keys [modal close-modal]}]
(let [response-to (:response-to (:content message))]
[react/view {:style (style/message-wrapper message)
@ -324,8 +326,13 @@
(style/message-timestamp-text))
:accessibility-label :message-timestamp}
timestamp-str]])
;;MESSAGE CONTENT
content
;; MESSAGE 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]]]
; delivery status
[react/view (style/delivery-status)
@ -436,6 +443,13 @@
:label (i18n/label (if pinned :t/unpin-from-chat :t/pin-to-chat))
:icon :main-icons/pin-context20
: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?)
[{:type :danger
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
@ -581,6 +595,13 @@
:id :share
:icon :main-icons/share-context20
: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?)
[{:type :danger
: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))
:icon :main-icons/pin-context20
: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?)
{:type :danger
:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])

View File

@ -182,3 +182,5 @@
;; usable enough to replace the old one **in the new UI**.
(def new-activity-center-enabled?
(atom false))
(def delete-message-for-me-undo-time-limit-ms 4000)

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.110.3",
"commit-sha1": "506921509e477445a95e1961a2557ef584d7caec",
"src-sha256": "1xmngbfl67n031rxhhbs7m14gzmfhgr1d34szclf1a6qxb9kw946"
"version": "f47cb8572de921fb4cff5d0f8d87b7b92386a226",
"commit-sha1": "f47cb8572de921fb4cff5d0f8d87b7b92386a226",
"src-sha256": "0wbiwq6dh531crqsij836bdkggn8f1z9f121aqpyxwdgp1njzxjk"
}

View File

@ -418,6 +418,7 @@
"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-confirmation": "Delete?",
"delete-for-me": "Delete for me",
"delete-mailserver": "Delete Status node",
"delete-mailserver-are-you-sure": "Are you sure you want to delete this Status node?",
"delete-mailserver-title": "Delete Status node",