refactor: delete message related code (#14548)

This commit is contained in:
yqrashawn 2022-12-20 21:42:50 +08:00 committed by GitHub
parent c0c0742687
commit 01660765b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 309 additions and 218 deletions

View File

@ -1,20 +1,21 @@
{:lint-as {status-im.utils.views/defview clojure.core/defn
status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
status-im.utils.styles/def clojure.core/def
status-im.utils.styles/defn clojure.core/defn
status-im.test-helpers/deftest-sub clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
:linters {:consistent-alias {:level :error
:aliases {clojure.string string
taoensso.timbre log}}
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
;; TODO remove number when this is fixed
;; https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number
status-im.test-helpers/restore-app-db]}}}
{:lint-as {status-im.utils.views/defview clojure.core/defn
status-im.utils.views/letsubs clojure.core/let
reagent.core/with-let clojure.core/let
status-im.utils.fx/defn clj-kondo.lint-as/def-catch-all
utils.re-frame/defn clj-kondo.lint-as/def-catch-all
quo.react/with-deps-check clojure.core/fn
quo.previews.preview/list-comp clojure.core/for
status-im.utils.styles/def clojure.core/def
status-im.utils.styles/defn clojure.core/defn
status-im.test-helpers/deftest-sub clojure.core/defn
taoensso.tufte/defnp clojure.core/defn}
:linters {:consistent-alias {:level :error
:aliases {clojure.string string
taoensso.timbre log}}
:invalid-arity {:skip-args [status-im.utils.fx/defn utils.re-frame/defn]}
;; TODO remove number when this is fixed
;; https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number
status-im.test-helpers/restore-app-db]}}
:config-in-ns {mocks.js-dependencies {:linters {:clojure-lsp/unused-public-var {:level :off}}}}}

View File

View File

@ -3,8 +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-im2.contexts.chat.messages.message.delete-message.events :as delete-message]
[status-im2.contexts.chat.messages.message.delete-message-for-me.events :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]

View File

@ -2,7 +2,7 @@
(: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-im2.contexts.chat.messages.message.delete-message.events :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]

View File

@ -186,7 +186,7 @@
(array-seq (.-values message-list))
[]))
;;TODO this is too expensive, probably we could mark message somehow and just hide it in the UI
;; NOTE(performance): this is too expensive, probably we could mark message somehow and just hide it in the UI
(fx/defn rebuild-message-list
[{:keys [db]} chat-id]
{:db (assoc-in db [:message-lists chat-id]

View File

@ -6,6 +6,9 @@
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
;; NOTE(19/12/22 yqrashawn) this namespace has been moved to the
;; status-im2.common.json-rpc.events namespace,
;; we keep this only for old (status 1.0) code, can be removed with old code later
(defn on-error-retry
[call-method {:keys [method number-of-retries delay on-error] :as arg}]
(if (pos? number-of-retries)

View File

@ -5,7 +5,7 @@
[re-frame.core :as re-frame]
[quo.design-system.colors :as colors]
[status-im.ui.components.react :as react]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.utils.handlers :refer [<sub]]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.icons.icons :as icons]
@ -14,10 +14,6 @@
[status-im.communities.core :as communities]
[quo.components.animated.pressable :as animation]))
(defn hide-sheet-and-dispatch [event]
(>evt [:bottom-sheet/hide])
(>evt event))
(defn request-actions [community-id request-id]
[react/view {:flex-direction :row}
[animation/pressable {:on-press #(re-frame/dispatch [:communities.ui/accept-request-to-join-pressed community-id request-id])}

View File

@ -127,19 +127,6 @@
:after :main-icons/next}
(i18n/label (if creating-backup? :t/next :t/choose-storage))]}]]))
(defn keycard-subtitle []
[react/view
[react/text {:style {:color colors/gray}} (i18n/label :t/empty-keycard-required)]
[react/view {:flex-direction :row
:align-items :center}
[react/text {:style {:color colors/blue}
:accessibility-label :learn-more
:on-press #(js/alert :press)}
(i18n/label :learn-more)]
[icons/icon :main-icons/tiny-external {:color colors/blue
:width 16
:height 16}]]])
(defn keycard-upsell-banner []
[react/view {:background-color (if (colors/dark?) "#2C5955" "#DDF8F4")
:border-radius 16 :padding-left 12 :padding-right 50 :margin 16}

View File

@ -15,7 +15,7 @@
[quo.react]
["react-native" :as react-native]
[status-im.ui.components.react :as react]
[status-im.utils.types :as types]
[utils.transforms :as transforms]
[oops.core :as oops]))
(defonce input-texts (atom {}))
@ -322,7 +322,7 @@
(reset! selection-event nil))))
on-selection (fn [event]
(let [native-event (.-nativeEvent event)
native-event (types/js->clj native-event)
native-event (transforms/js->clj native-event)
{:keys [eventType content selectionStart selectionEnd]} native-event
full-text (:input-text (<sub [:chats/current-chat-inputs]))]
(on-menu-item-touched {:first-level first-level

View File

@ -10,8 +10,8 @@
[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-im2.contexts.chat.messages.message.delete-message.events]
[status-im2.contexts.chat.messages.message.delete-message-for-me.events]
[status-im.chat.models.images :as images]
[status-im.chat.models.reactions :as models.reactions]
[status-im.constants :as constants]

View File

@ -1,74 +1,66 @@
(ns status-im.utils.datetime
(:require [re-frame.core :as re-frame]
[cljs-time.core :as t :refer [plus minus days hours before?]]
[cljs-time.coerce :refer [from-long]]
[cljs-time.format :refer [formatters
formatter
unparse]]
[status-im.i18n.i18n :refer [label label-pluralize]]
[status-im.native-module.core :as status]
(:require [cljs-time.coerce :as t.coerce]
[cljs-time.core :as t]
[cljs-time.format :as t.format]
[clojure.string :as string]
[status-im.goog.i18n :as goog.18n]))
[i18n.i18n :as i18n]
[re-frame.core :as re-frame]
[status-im.goog.i18n :as goog.18n]
[status-im.native-module.core :as status]))
;;;; Datetime constants
(defn now []
(t/now))
(defn now [] (t/now))
(def one-second 1000)
(def minute (* 60 one-second))
(defn minutes [m]
(* m minute))
(defn minutes [m] (* m minute))
(def hour (* 60 minute))
(def day (* 24 hour))
(def week (* 7 day))
(defn weeks [w]
(* w week))
(def units [{:name :t/datetime-second-short :limit 60 :in-second 1}
{:name :t/datetime-minute-short :limit 3600 :in-second 60}
{:name :t/datetime-hour-short :limit 86400 :in-second 3600}
{:name :t/datetime-day-short :limit nil :in-second 86400}])
(defn weeks [w] (* w week))
(def units
[{:name :t/datetime-second-short :limit 60 :in-second 1}
{:name :t/datetime-minute-short :limit 3600 :in-second 60}
{:name :t/datetime-hour-short :limit 86400 :in-second 3600}
{:name :t/datetime-day-short :limit nil :in-second 86400}])
(def time-zone-offset (hours (- (/ (.getTimezoneOffset ^js (js/Date.)) 60))))
(def time-zone-offset (t/hours (- (/ (.getTimezoneOffset ^js (js/Date.)) 60))))
;;;; Utilities
(defn- is24Hour-locsym
(defn- is-24-hour-locsym
"Detects if given locale symbols timeformat generates AM/PM ('a')."
[^js locsym]
(not (string/includes?
(nth (.-TIMEFORMATS locsym) 2)
"a")))
(defn- is24Hour
(defn- is-24-hour
"Returns is24Hour from device or from given locale symbols. Whenever we get
non-nil value use it, else calculate it from the given locale symbol."
[^js locsym]
(if-some [fromdev (status/is24Hour)]
fromdev
(is24Hour-locsym locsym)))
(is-24-hour-locsym locsym)))
;;;; Time formats
(defn- short-time-format
[^js locsym]
(if (is24Hour locsym)
(if (is-24-hour locsym)
"HH:mm"
"h:mm a"))
(defn- time-format
[^js locsym]
(if (is24Hour locsym)
(if (is-24-hour locsym)
"HH:mm:ss"
"h:mm:ss a"))
;;;; Date formats
(defn- short-date-format [_] "dd MMM")
(defn- datetime-within-one-week-format
[^js locsym]
(if (is24Hour locsym)
(if (is-24-hour locsym)
"E HH:mm"
"E h:mm a"))
@ -78,16 +70,17 @@
(nth (.-DATEFORMATS locsym) 2))
;;;; Datetime formats
(defn- medium-date-time-format [locsym]
(defn- medium-date-time-format
[locsym]
(str (medium-date-format locsym) ", " (time-format locsym)))
(defn get-formatter-fn [format]
(defn get-formatter-fn
[format]
(let [formatter (atom nil)]
(fn []
(or @formatter
(reset! formatter
(goog.18n/mk-fmt status-im.i18n.i18n/locale format))))))
(goog.18n/mk-fmt i18n/locale format))))))
(def date-time-fmt (get-formatter-fn medium-date-time-format))
(def date-fmt (get-formatter-fn medium-date-format))
@ -96,7 +89,6 @@
(def datetime-within-one-week-fmt (get-formatter-fn datetime-within-one-week-format))
;;;; Utilities
(defn previous-years?
[datetime]
(< (t/year datetime) (t/year (t/now))))
@ -121,37 +113,41 @@
(t/within? start end datetime)))
;;;; Timestamp formatters
(defn- to-str [ms old-fmt-fn yesterday-fmt-fn today-fmt-fn]
(let [date (from-long ms)
local (plus date time-zone-offset) ; this is wrong, it uses the current timezone offset, regardless of DST
today (minus (t/today-at-midnight) time-zone-offset)
yesterday (plus today (days -1))]
(defn- to-str
[ms old-fmt-fn yesterday-fmt-fn today-fmt-fn]
(let [date (t.coerce/from-long ms)
local (t/plus date time-zone-offset) ; NOTE(edge-case): this is wrong, it uses the current timezone offset,
; regardless of DST
today (t/minus (t/today-at-midnight) time-zone-offset)
yesterday (t/plus today (t/days -1))]
(cond
(before? date yesterday) (old-fmt-fn local)
(before? date today) (yesterday-fmt-fn local)
:else (today-fmt-fn local))))
(t/before? date yesterday) (old-fmt-fn local)
(t/before? date today) (yesterday-fmt-fn local)
:else (today-fmt-fn local))))
(defn to-short-str [ms]
(defn to-short-str
[ms]
(to-str ms
#(.format ^js (date-fmt) %)
#(label :t/datetime-yesterday)
#(i18n/label :t/datetime-yesterday)
#(.format ^js (time-fmt) %)))
(defn day-relative [ms]
(defn day-relative
[ms]
(to-str ms
#(.format ^js (date-fmt) %)
#(label :t/datetime-yesterday)
#(label :t/datetime-today)))
#(i18n/label :t/datetime-yesterday)
#(i18n/label :t/datetime-today)))
(defn timestamp->relative [ms]
(let [datetime (from-long ms)]
(defn timestamp->relative
[ms]
(let [datetime (t.coerce/from-long ms)]
(cond
(today? datetime)
(.format ^js (time-fmt) datetime)
(within-last-n-days? datetime 1)
(str (string/capitalize (label :t/datetime-yesterday))
(str (string/capitalize (i18n/label :t/datetime-yesterday))
" "
(.format ^js (time-fmt) datetime))
@ -164,40 +160,52 @@
(previous-years? datetime)
(.format ^js (date-fmt) datetime))))
(defn timestamp->mini-date [ms]
(.format ^js (short-date-fmt) (-> ms
from-long
(plus time-zone-offset))))
(defn timestamp->mini-date
[ms]
(.format ^js (short-date-fmt)
(-> ms
t.coerce/from-long
(t/plus time-zone-offset))))
(defn timestamp->time [ms]
(.format ^js (time-fmt) (-> ms
from-long
(plus time-zone-offset))))
(defn timestamp->time
[ms]
(.format ^js (time-fmt)
(-> ms
t.coerce/from-long
(t/plus time-zone-offset))))
(defn timestamp->date-key [ms]
(keyword (unparse (formatter "YYYYMMDD") (-> ms
from-long
(plus time-zone-offset)))))
(defn timestamp->date-key
[ms]
(keyword (t.format/unparse (t.format/formatter "YYYYMMDD")
(-> ms
t.coerce/from-long
(t/plus time-zone-offset)))))
(defn timestamp->long-date [ms]
(.format ^js (date-time-fmt) (-> ms
from-long
(plus time-zone-offset))))
(defn timestamp->long-date
[ms]
(.format ^js (date-time-fmt)
(-> ms
t.coerce/from-long
(t/plus time-zone-offset))))
(defn format-time-ago [diff unit]
(let [name (label-pluralize diff (:name unit))]
(defn format-time-ago
[diff unit]
(let [name (i18n/label-pluralize diff (:name unit))]
(if (= :t/datetime-second-short (:name unit))
(label :t/now)
(label :t/datetime-ago-format-short {:ago (label :t/datetime-ago)
:number diff
:time-intervals name}))))
(defn seconds-ago [time]
(i18n/label :t/now)
(i18n/label :t/datetime-ago-format-short
{:ago (i18n/label :t/datetime-ago)
:number diff
:time-intervals name}))))
(defn seconds-ago
[time]
(let [now (t/now)]
(if (<= (.getTime ^js time) (.getTime ^js now))
(t/in-seconds (t/interval time now))
0)))
(defn time-ago [time]
(defn time-ago
[time]
(let [diff (seconds-ago time)
unit (first (drop-while #(and (>= diff (:limit %))
(:limit %))
@ -207,36 +215,43 @@
int
(format-time-ago unit))))
(defn time-ago-long [time]
(defn time-ago-long
[time]
(let [seconds-ago (seconds-ago time)
unit (first (drop-while #(and (>= seconds-ago (:limit %))
(:limit %))
units))
diff (-> (/ seconds-ago (:in-second unit))
Math/floor
int)
unit (first (drop-while #(and (>= seconds-ago (:limit %))
(:limit %))
units))
diff (-> (/ seconds-ago (:in-second unit))
Math/floor
int)
name (label-pluralize diff (:name unit))]
(label :t/datetime-ago-format {:ago (label :t/datetime-ago)
:number diff
:time-intervals name})))
name (i18n/label-pluralize diff (:name unit))]
(i18n/label :t/datetime-ago-format
{:ago (i18n/label :t/datetime-ago)
:number diff
:time-intervals name})))
(defn to-date [ms]
(from-long ms))
(defn to-date
[ms]
(t.coerce/from-long ms))
(defn timestamp []
(defn timestamp
[]
(inst-ms (js/Date.)))
(defn timestamp-sec []
(defn timestamp-sec
[]
(int (/ (timestamp) 1000)))
(defn timestamp->year-month-day-date [ms]
(unparse (:year-month-day formatters) (to-date ms)))
(defn timestamp->year-month-day-date
[ms]
(t.format/unparse (:year-month-day t.format/formatters) (to-date ms)))
(re-frame/reg-cofx
:now
(fn [coeffects _]
(assoc coeffects :now (timestamp))))
(defn to-ms [sec]
(defn to-ms
[sec]
(* 1000 sec))

View File

@ -23,14 +23,14 @@
;; 1970-01-03 00:00:00 UTC
(def epoch-plus-3d 172800000)
(deftest is24Hour-locale-en-test
(is (= (#'status-im.utils.datetime/is24Hour-locsym (i18n/locale-symbols "en")) false)))
(deftest is-24-hour-locale-en-test
(is (= (#'status-im.utils.datetime/is-24-hour-locsym (i18n/locale-symbols "en")) false)))
(deftest is24Hour-locale-it-test
(is (= (#'status-im.utils.datetime/is24Hour-locsym (i18n/locale-symbols "it")) true)))
(deftest is-24-hour-locale-it-test
(is (= (#'status-im.utils.datetime/is-24-hour-locsym (i18n/locale-symbols "it")) true)))
(deftest is24Hour-locale-nb-test
(is (= (#'status-im.utils.datetime/is24Hour-locsym (i18n/locale-symbols "nb-NO")) true)))
(deftest is-24-hour-locale-nb-test
(is (= (#'status-im.utils.datetime/is-24-hour-locsym (i18n/locale-symbols "nb-NO")) true)))
(deftest to-short-str-today-test
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
@ -40,14 +40,14 @@
#_((deftest to-short-str-today-force-24H-test
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
d/is24Hour (constantly true)
d/is-24-hour (constantly true)
d/time-fmt (i18n-module/mk-fmt "us" d/short-time-format)
d/time-zone-offset (t/period :hours 0)]
(is (= (d/to-short-str epoch-plus-3d) "00:00"))))
(deftest to-short-str-today-force-AMPM-test
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
d/is24Hour (constantly false)
d/is-24-hour (constantly false)
d/time-fmt (i18n-module/mk-fmt "it" d/short-time-format)
d/time-zone-offset (t/period :hours 0)]
(is (= (d/to-short-str epoch-plus-3d) "12:00 AM")))))
@ -135,7 +135,7 @@
;; Today is Monday, 1975-03-10 15:15:45Z
(with-redefs [t/*ms-fn* (constantly 163696545000)
d/time-zone-offset (t/period :hours 0)
d/is24Hour (constantly false)]
d/is-24-hour (constantly false)]
(testing "formats previous years"
;; 1974-12-31 23:59:59Z
(is (= "Dec 31, 1974" (d/timestamp->relative 157766399000)))
@ -165,14 +165,14 @@
#_((deftest day-relative-before-yesterday-force-24H-test
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
d/is24Hour (constantly true)
d/is-24-hour (constantly true)
d/time-zone-offset (t/period :hours 0)
d/date-fmt (i18n-module/mk-fmt "us" #'status-im.utils.datetime/medium-date-time-format)]
(is (= (d/day-relative epoch) "Jan 1, 1970, 00:00:00"))))
(deftest day-relative-before-yesterday-force-AMPM-test
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
d/is24Hour (constantly false)
d/is-24-hour (constantly false)
d/time-zone-offset (t/period :hours 0)
d/date-fmt (i18n-module/mk-fmt "it" #'status-im.utils.datetime/medium-date-time-format)]
(is (= (d/day-relative epoch) "01 gen 1970, 12:00:00 AM")))))

View File

@ -2,6 +2,9 @@
(:refer-clojure :exclude [js->clj])
(:require [cljs-bean.core :as clj-bean]))
;; NOTE(19/12/22 yqrashawn) this namespace has been moved to the utils.transforms namespace,
;; we keep this only for old (status 1.0) code, can be removed with old code later
(defn to-string [s]
(if (keyword? s)
(name s)

View File

@ -0,0 +1,51 @@
(ns status-im2.common.json-rpc.events
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[react-native.background-timer :as background-timer]
[status-im.native-module.core :as status]
[taoensso.timbre :as log]
[utils.transforms :as transforms]))
(defn on-error-retry
[call-method {:keys [method number-of-retries delay on-error] :as arg}]
(if (pos? number-of-retries)
(fn [error]
(let [updated-delay (if delay
(min 2000 (* 2 delay))
50)]
(log/debug "[on-error-retry]" method
"number-of-retries" number-of-retries
"delay" delay
"error" error)
(background-timer/set-timeout #(call-method (-> arg
(update :number-of-retries dec)
(assoc :delay updated-delay)))
updated-delay)))
on-error))
(defn call
[{:keys [method params on-success on-error js-response] :as arg}]
(let [params (or params [])
on-error (or on-error
(on-error-retry call arg)
#(log/warn :json-rpc/error method :error % :params params))]
(status/call-private-rpc
(transforms/clj->json {:jsonrpc "2.0"
:id 1
:method method
:params params})
(fn [response]
(if (string/blank? response)
(on-error {:message "Blank response"})
(let [response-js (transforms/json->js response)]
(if (.-error response-js)
(on-error (transforms/js->clj (.-error response-js)))
(on-success (if js-response
(.-result response-js)
(transforms/js->clj (.-result response-js)))))))))))
(re-frame/reg-fx
::call
(fn [params]
(doseq [param params]
(call param))))

View File

@ -1,7 +1,7 @@
(ns status-im2.contexts.activity-center.events
(:require [re-frame.core :as rf]
[status-im.data-store.activities :as data-store.activities]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im2.common.json-rpc.events :as json-rpc]
[status-im.utils.fx :as fx]
[status-im2.contexts.activity-center.notification-types :as types]
[taoensso.timbre :as log]))

View File

@ -3,7 +3,7 @@
[day8.re-frame.test :as rf-test]
[re-frame.core :as rf]
[status-im.constants :as constants]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im2.common.json-rpc.events :as json-rpc]
status-im.events
[status-im.test-helpers :as h]
[status-im2.contexts.activity-center.events :as activity-center]

View File

@ -1,11 +1,12 @@
(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.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]))
(ns status-im2.contexts.chat.messages.message.delete-message.events
(:require
;; TODO move to status-im2
[status-im.chat.models.message-list :as message-list]
[status-im.utils.datetime :as datetime]
[status-im2.common.json-rpc.events :as json-rpc]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn- update-db-clear-undo-timer
[db chat-id message-id]
@ -22,7 +23,7 @@
(update-in db
[:messages chat-id message-id]
assoc
:deleted? true
:deleted? true
:deleted-undoable-till (+ (datetime/timestamp)
undo-time-limit-ms))))
@ -46,7 +47,7 @@
(when (get-in db [:messages chat-id message-id])
(update-in db [:messages chat-id message-id] assoc :deleted? true)))
(fx/defn delete
(rf/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]
@ -55,12 +56,13 @@
(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}])))
: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
(rf/defn undo
{:events [:chat.ui/undo-delete-message]}
[{:keys [db]} {:keys [chat-id message-id]}]
(when (get-in db [:messages chat-id message-id])
@ -68,19 +70,22 @@
{:db (update-db-undo-locally db chat-id message-id)}
chat-id)))
(fx/defn delete-and-send
(rf/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])
[:pin-message/send-pin-message {:chat-id chat-id :message-id message-id :pinned false}]))))
(cond-> {: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 #(rf/dispatch [:sanitize-messages-and-process-response
%])}]}
(get-in db [:pin-messages chat-id message-id])
(assoc :dispatch
[: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"
@ -90,19 +95,20 @@
(map (fn [message] {:chat-id chat-id :message-id (first message)}))
(concat acc)))
(fx/defn send-all
(rf/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))))
(apply rf/merge cofx (map delete-and-send pending-send-messages))))
(fx/defn delete-messages-localy
(rf/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))]
(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))))

View File

@ -1,8 +1,8 @@
(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]))
(ns status-im2.contexts.chat.messages.message.delete-message.events-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.utils.datetime :as datetime]
[status-im2.common.json-rpc.events :as json-rpc]
[status-im2.contexts.chat.messages.message.delete-message.events :as delete-message]))
(def mid "message-id")
(def cid "chat-id")
@ -62,7 +62,7 @@
(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)]
rpc-calls (::json-rpc/call effects)]
(is (= result-db expected-db))
(is (= (count rpc-calls) 1))
(is (= (-> rpc-calls

View File

@ -1,10 +1,12 @@
(ns status-im.chat.models.delete-message-for-me
(:require [re-frame.core :as re-frame]
[status-im.chat.models.message-list :as message-list]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.datetime :as datetime]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]))
(ns status-im2.contexts.chat.messages.message.delete-message-for-me.events
(:require
;; TODO move to status-im2
[status-im.chat.models.message-list :as message-list]
[status-im.utils.datetime :as datetime]
[status-im2.common.json-rpc.events :as json-rpc]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn- update-db-clear-undo-timer
[db chat-id message-id]
@ -21,7 +23,7 @@
(update-in db
[:messages chat-id message-id]
assoc
:deleted-for-me? true
:deleted-for-me? true
:deleted-for-me-undoable-till (+ (datetime/timestamp)
undo-time-limit-ms))))
@ -39,7 +41,7 @@
:deleted-for-me-undoable-till)
(update-db-clear-undo-timer db chat-id message-id))))
(fx/defn delete
(rf/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]
@ -48,12 +50,13 @@
(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-for-me-and-sync
{:chat-id chat-id
:message-id message-id}]
:ms 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
(rf/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])
@ -61,7 +64,7 @@
{:db (update-db-undo-locally db chat-id message-id)}
chat-id)))
(fx/defn delete-and-sync
(rf/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])
@ -69,20 +72,22 @@
::json-rpc/call [{:method "wakuext_deleteMessageForMeAndSync"
:params [chat-id message-id]
:js-response true
: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 %])}]}))
:on-error #(log/error "failed to delete message for me, message id: "
{:message-id message-id :error %})
:on-success #(rf/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]
(->> messages
(filter (fn [[_ {:keys [deleted-for-me? deleted-for-me-undoable-till]}]] (and deleted-for-me? deleted-for-me-undoable-till)))
(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
(rf/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] :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))))
(apply rf/merge cofx (map delete-and-sync pending-sync-messages))))

View File

@ -1,8 +1,9 @@
(ns status-im.chat.models.delete-message-for-me-test
(ns status-im2.contexts.chat.messages.message.delete-message-for-me.events-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]))
[status-im.utils.datetime :as datetime]
[status-im2.common.json-rpc.events :as json-rpc]
[status-im2.contexts.chat.messages.message.delete-message-for-me.events :as
delete-message-for-me]))
(def mid "message-id")
(def cid "chat-id")
@ -30,7 +31,7 @@
(let [db (update-in db
[:messages cid mid]
assoc
:deleted-for-me? true
:deleted-for-me? true
:deleted-for-me-undoable-till
(+ (datetime/timestamp) 1000))
result-message (get-in (delete-message-for-me/undo {:db db} message)
@ -43,9 +44,10 @@
(let [db (update-in db
[:messages cid mid]
assoc
:deleted-for-me? true
: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])]
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)))))
@ -62,7 +64,7 @@
(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)]
rpc-calls (::json-rpc/call effects)]
(is (= result-db expected-db))
(is (= (count rpc-calls) 1))
(is (= (-> rpc-calls

View File

@ -3,6 +3,7 @@
[re-frame.interop :as interop]
[reagent.impl.batching :as batching]
[react-native.core :as rn]
[status-im.native-module.core :as status]
[react-native.platform :as platform]
[react-native.shake :as react-native-shake]
[react-native.languages :as react-native-languages]
@ -23,7 +24,6 @@
;; TODO (14/11/22 flexsurfer move to status-im2 namespace
status-im.events
[status-im.native-module.core :as status]
[status-im.notifications.local :as notifications]
[status-im.async-storage.core :as async-storage]
[status-im.utils.universal-links.core :as utils.universal-links]))

View File

@ -8,8 +8,8 @@
;; TODO (14/11/22 flexsurfer move to status-im2 namespace
[quo.theme :as quo.theme]
[status-im.multiaccounts.login.core :as multiaccounts.login]
[status-im.native-module.core :as status]
[status-im.multiaccounts.login.core :as multiaccounts.login]
[status-im.utils.keychain.core :as keychain]
[status-im2.navigation.events :as navigation]))

22
src/utils/transforms.cljs Normal file
View File

@ -0,0 +1,22 @@
(ns utils.transforms
(:refer-clojure :exclude [js->clj])
(:require [cljs-bean.core :as clj-bean]))
(defn js->clj [data] (cljs.core/js->clj data :keywordize-keys true))
(defn clj->pretty-json
[data spaces]
(.stringify js/JSON (clj-bean/->js data) nil spaces))
(defn clj->json [data] (clj->pretty-json data 0))
(defn json->clj
[json]
(when-not (= json "undefined")
(try (js->clj (.parse js/JSON json))
(catch js/Error _ (when (string? json) json)))))
(defn json->js
[json]
(when-not (= json "undefined")
(try (.parse js/JSON json) (catch js/Error _ (when (string? json) json)))))