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

@ -17,4 +17,5 @@
;; https://github.com/borkdude/clj-kondo/issues/867 ;; https://github.com/borkdude/clj-kondo/issues/867
:unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY :unresolved-symbol {:exclude [PersistentPriorityMap.EMPTY
number number
status-im.test-helpers/restore-app-db]}}} 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] [taoensso.timbre :as log]
[status-im.multiaccounts.model :as multiaccounts.model] [status-im.multiaccounts.model :as multiaccounts.model]
[status-im.chat.models.message-list :as message-list] [status-im.chat.models.message-list :as message-list]
[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.delete-message-for-me :as delete-for-me] [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.data-store.chats :as chats-store]
[status-im.mailserver.core :as mailserver] [status-im.mailserver.core :as mailserver]
[status-im.data-store.contacts :as contacts-store] [status-im.data-store.contacts :as contacts-store]

View File

@ -2,7 +2,7 @@
(:require [clojure.string :as string] (:require [clojure.string :as string]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.chat.models :as chat-model] [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.loading :as chat.loading]
[status-im.chat.models.mentions :as mentions] [status-im.chat.models.mentions :as mentions]
[status-im.chat.models.message-list :as message-list] [status-im.chat.models.message-list :as message-list]

View File

@ -186,7 +186,7 @@
(array-seq (.-values message-list)) (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 (fx/defn rebuild-message-list
[{:keys [db]} chat-id] [{:keys [db]} chat-id]
{:db (assoc-in db [:message-lists chat-id] {:db (assoc-in db [:message-lists chat-id]

View File

@ -6,6 +6,9 @@
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[taoensso.timbre :as log])) [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 (defn on-error-retry
[call-method {:keys [method number-of-retries delay on-error] :as arg}] [call-method {:keys [method number-of-retries delay on-error] :as arg}]
(if (pos? number-of-retries) (if (pos? number-of-retries)

View File

@ -5,7 +5,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[status-im.ui.components.react :as react] [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.ui.components.chat-icon.screen :as chat-icon]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.icons.icons :as icons] [status-im.ui.components.icons.icons :as icons]
@ -14,10 +14,6 @@
[status-im.communities.core :as communities] [status-im.communities.core :as communities]
[quo.components.animated.pressable :as animation])) [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] (defn request-actions [community-id request-id]
[react/view {:flex-direction :row} [react/view {:flex-direction :row}
[animation/pressable {:on-press #(re-frame/dispatch [:communities.ui/accept-request-to-join-pressed community-id request-id])} [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} :after :main-icons/next}
(i18n/label (if creating-backup? :t/next :t/choose-storage))]}]])) (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 [] (defn keycard-upsell-banner []
[react/view {:background-color (if (colors/dark?) "#2C5955" "#DDF8F4") [react/view {:background-color (if (colors/dark?) "#2C5955" "#DDF8F4")
:border-radius 16 :padding-left 12 :padding-right 50 :margin 16} :border-radius 16 :padding-left 12 :padding-right 50 :margin 16}

View File

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

View File

@ -10,8 +10,8 @@
[quo2.foundations.typography :as typography] [quo2.foundations.typography :as typography]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.chat.models.delete-message] [status-im2.contexts.chat.messages.message.delete-message.events]
[status-im.chat.models.delete-message-for-me] [status-im2.contexts.chat.messages.message.delete-message-for-me.events]
[status-im.chat.models.images :as images] [status-im.chat.models.images :as images]
[status-im.chat.models.reactions :as models.reactions] [status-im.chat.models.reactions :as models.reactions]
[status-im.constants :as constants] [status-im.constants :as constants]

View File

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

View File

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

View File

@ -2,6 +2,9 @@
(:refer-clojure :exclude [js->clj]) (:refer-clojure :exclude [js->clj])
(:require [cljs-bean.core :as clj-bean])) (: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] (defn to-string [s]
(if (keyword? s) (if (keyword? s)
(name 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 (ns status-im2.contexts.activity-center.events
(:require [re-frame.core :as rf] (:require [re-frame.core :as rf]
[status-im.data-store.activities :as data-store.activities] [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-im.utils.fx :as fx]
[status-im2.contexts.activity-center.notification-types :as types] [status-im2.contexts.activity-center.notification-types :as types]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))

View File

@ -3,7 +3,7 @@
[day8.re-frame.test :as rf-test] [day8.re-frame.test :as rf-test]
[re-frame.core :as rf] [re-frame.core :as rf]
[status-im.constants :as constants] [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.events
[status-im.test-helpers :as h] [status-im.test-helpers :as h]
[status-im2.contexts.activity-center.events :as activity-center] [status-im2.contexts.activity-center.events :as activity-center]

View File

@ -1,11 +1,12 @@
(ns status-im.chat.models.delete-message (ns status-im2.contexts.chat.messages.message.delete-message.events
(:require [re-frame.core :as re-frame] (:require
;; TODO move to status-im2
[status-im.chat.models.message-list :as message-list] [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.datetime :as datetime]
[status-im.utils.fx :as fx]
[taoensso.encore :as enc] [status-im2.common.json-rpc.events :as json-rpc]
[taoensso.timbre :as log])) [taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn- update-db-clear-undo-timer (defn- update-db-clear-undo-timer
[db chat-id message-id] [db chat-id message-id]
@ -46,7 +47,7 @@
(when (get-in db [:messages chat-id message-id]) (when (get-in db [:messages chat-id message-id])
(update-in db [:messages chat-id message-id] assoc :deleted? true))) (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" "Delete message now locally and broadcast after undo time limit timeout"
{:events [:chat.ui/delete-message]} {:events [:chat.ui/delete-message]}
[{:keys [db]} {:keys [chat-id message-id]} undo-time-limit-ms] [{:keys [db]} {:keys [chat-id message-id]} undo-time-limit-ms]
@ -55,12 +56,13 @@
(message-list/rebuild-message-list (message-list/rebuild-message-list
{:db (update-db-delete-locally db chat-id message-id undo-time-limit-ms)} {:db (update-db-delete-locally db chat-id message-id undo-time-limit-ms)}
chat-id) chat-id)
:utils/dispatch-later [{:dispatch [:chat.ui/delete-message-and-send :utils/dispatch-later
[{:dispatch [:chat.ui/delete-message-and-send
{:chat-id chat-id {:chat-id chat-id
:message-id message-id}] :message-id message-id}]
:ms undo-time-limit-ms}]))) :ms undo-time-limit-ms}])))
(fx/defn undo (rf/defn undo
{:events [:chat.ui/undo-delete-message]} {:events [:chat.ui/undo-delete-message]}
[{:keys [db]} {:keys [chat-id message-id]}] [{:keys [db]} {:keys [chat-id message-id]}]
(when (get-in db [:messages 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)} {:db (update-db-undo-locally db chat-id message-id)}
chat-id))) chat-id)))
(fx/defn delete-and-send (rf/defn delete-and-send
{:events [:chat.ui/delete-message-and-send]} {:events [:chat.ui/delete-message-and-send]}
[{:keys [db]} {:keys [message-id chat-id]}] [{:keys [db]} {:keys [message-id chat-id]}]
(when-let [message (get-in db [:messages chat-id message-id])] (when-let [message (get-in db [:messages chat-id message-id])]
(enc/assoc-when (cond-> {:db (update-db-clear-undo-timer db chat-id message-id)
{:db (update-db-clear-undo-timer db chat-id message-id)
::json-rpc/call [{:method "wakuext_deleteMessageAndSend" ::json-rpc/call [{:method "wakuext_deleteMessageAndSend"
:params [message-id] :params [message-id]
:js-response true :js-response true
:on-error #(log/error "failed to delete message " {:message-id message-id :error %}) :on-error #(log/error "failed to delete message "
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]} {:message-id message-id :error %})
:dispatch (and (get-in db [:pin-messages chat-id message-id]) :on-success #(rf/dispatch [:sanitize-messages-and-process-response
[:pin-message/send-pin-message {:chat-id chat-id :message-id message-id :pinned false}])))) %])}]}
(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 (defn- filter-pending-send-messages
"traverse all messages find not yet synced deleted? 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)})) (map (fn [message] {:chat-id chat-id :message-id (first message)}))
(concat acc))) (concat acc)))
(fx/defn send-all (rf/defn send-all
"Get all deleted messages that not yet synced with status-go and send them" "Get all deleted messages that not yet synced with status-go and send them"
{:events [:chat.ui/send-all-deleted-messages]} {:events [:chat.ui/send-all-deleted-messages]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [pending-send-messages (reduce-kv filter-pending-send-messages [] (:messages db))] (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" "Mark messages :deleted? localy in client"
{:events [:chat.ui/delete-messages-localy]} {:events [:chat.ui/delete-messages-localy]}
[{:keys [db]} messages chat-id] [{:keys [db]} messages chat-id]
(let [new-db (->> messages (let [new-db (->> messages
(filter #(get-in db [:messages chat-id (:message-id %)])) (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 (when new-db
(message-list/rebuild-message-list {:db new-db} chat-id)))) (message-list/rebuild-message-list {:db new-db} chat-id))))

View File

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

View File

@ -1,10 +1,12 @@
(ns status-im.chat.models.delete-message-for-me (ns status-im2.contexts.chat.messages.message.delete-message-for-me.events
(:require [re-frame.core :as re-frame] (:require
;; TODO move to status-im2
[status-im.chat.models.message-list :as message-list] [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.datetime :as datetime]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log])) [status-im2.common.json-rpc.events :as json-rpc]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
(defn- update-db-clear-undo-timer (defn- update-db-clear-undo-timer
[db chat-id message-id] [db chat-id message-id]
@ -39,7 +41,7 @@
:deleted-for-me-undoable-till) :deleted-for-me-undoable-till)
(update-db-clear-undo-timer db chat-id message-id)))) (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" "Delete message for me now locally and broadcast after undo time limit timeout"
{:events [:chat.ui/delete-message-for-me]} {:events [:chat.ui/delete-message-for-me]}
[{:keys [db]} {:keys [chat-id message-id]} undo-time-limit-ms] [{:keys [db]} {:keys [chat-id message-id]} undo-time-limit-ms]
@ -48,12 +50,13 @@
(message-list/rebuild-message-list (message-list/rebuild-message-list
{:db (update-db-delete-locally db chat-id message-id undo-time-limit-ms)} {:db (update-db-delete-locally db chat-id message-id undo-time-limit-ms)}
chat-id) chat-id)
:utils/dispatch-later [{:dispatch [:chat.ui/delete-message-for-me-and-sync :utils/dispatch-later
[{:dispatch [:chat.ui/delete-message-for-me-and-sync
{:chat-id chat-id {:chat-id chat-id
:message-id message-id}] :message-id message-id}]
:ms undo-time-limit-ms}]))) :ms undo-time-limit-ms}])))
(fx/defn undo (rf/defn undo
{:events [:chat.ui/undo-delete-message-for-me]} {:events [:chat.ui/undo-delete-message-for-me]}
[{:keys [db]} {:keys [chat-id message-id]}] [{:keys [db]} {:keys [chat-id message-id]}]
(when (get-in db [:messages 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)} {:db (update-db-undo-locally db chat-id message-id)}
chat-id))) chat-id)))
(fx/defn delete-and-sync (rf/defn delete-and-sync
{:events [:chat.ui/delete-message-for-me-and-sync]} {:events [:chat.ui/delete-message-for-me-and-sync]}
[{:keys [db]} {:keys [message-id chat-id]}] [{:keys [db]} {:keys [message-id chat-id]}]
(when (get-in db [:messages chat-id message-id]) (when (get-in db [:messages chat-id message-id])
@ -69,20 +72,22 @@
::json-rpc/call [{:method "wakuext_deleteMessageForMeAndSync" ::json-rpc/call [{:method "wakuext_deleteMessageForMeAndSync"
:params [chat-id message-id] :params [chat-id message-id]
:js-response true :js-response true
:on-error #(log/error "failed to delete message for me, message id: " {:message-id message-id :error %}) :on-error #(log/error "failed to delete message for me, message id: "
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})) {:message-id message-id :error %})
:on-success #(rf/dispatch [:sanitize-messages-and-process-response %])}]}))
(defn- filter-pending-sync-messages (defn- filter-pending-sync-messages
"traverse all messages find not yet synced deleted-for-me? messages" "traverse all messages find not yet synced deleted-for-me? messages"
[acc chat-id messages] [acc chat-id messages]
(->> 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)})) (map (fn [message] {:chat-id chat-id :message-id (first message)}))
(concat acc))) (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" "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]} {:events [:chat.ui/sync-all-deleted-for-me-messages]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(let [pending-sync-messages (reduce-kv filter-pending-sync-messages [] (:messages db))] (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]] (:require [cljs.test :refer-macros [deftest is testing]]
[status-im.chat.models.delete-message-for-me :as [status-im.utils.datetime :as datetime]
delete-message-for-me] [status-im2.common.json-rpc.events :as json-rpc]
[status-im.utils.datetime :as datetime])) [status-im2.contexts.chat.messages.message.delete-message-for-me.events :as
delete-message-for-me]))
(def mid "message-id") (def mid "message-id")
(def cid "chat-id") (def cid "chat-id")
@ -45,7 +46,8 @@
assoc assoc
:deleted-for-me? true :deleted-for-me? true
:deleted-for-me-undoable-till (- (datetime/timestamp) 1000)) :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 (= (:id result-message) mid))
(is (nil? (:deleted-for-me-undoable-till result-message))) (is (nil? (:deleted-for-me-undoable-till result-message)))
(is (true? (:deleted-for-me? result-message))))) (is (true? (:deleted-for-me? result-message)))))
@ -62,7 +64,7 @@
(let [expected-db {:messages {cid {mid {:id mid}}}} (let [expected-db {:messages {cid {mid {:id mid}}}}
effects (delete-message-for-me/delete-and-sync {:db db} message) effects (delete-message-for-me/delete-and-sync {:db db} message)
result-db (:db effects) 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 (= result-db expected-db))
(is (= (count rpc-calls) 1)) (is (= (count rpc-calls) 1))
(is (= (-> rpc-calls (is (= (-> rpc-calls

View File

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