diff --git a/src/status_im/chat/handlers/commands.cljs b/src/status_im/chat/handlers/commands.cljs index 25b6319706..f3ecf9839b 100644 --- a/src/status_im/chat/handlers/commands.cljs +++ b/src/status_im/chat/handlers/commands.cljs @@ -1,13 +1,15 @@ (ns status-im.chat.handlers.commands - (:require [re-frame.core :refer [enrich after dispatch]] + (:require [cljs.reader :as reader] + [clojure.string :as str] + [re-frame.core :refer [enrich after dispatch]] + [status-im.data-store.messages :as messages] [status-im.utils.handlers :as handlers] [status-im.components.status :as status] [status-im.chat.constants :as const] [status-im.commands.utils :as cu] [status-im.i18n :as i18n] [status-im.utils.platform :as platform] - [taoensso.timbre :as log] - [clojure.string :as str])) + [taoensso.timbre :as log])) (defn generate-context [{:keys [contacts current-account-id chats] :as db} chat-id to] (merge {:platform platform/platform @@ -38,11 +40,15 @@ params {:parameters params :context (generate-context db chat-id to)} callback #(let [result (get-in % [:result :returned]) - result (if (:markup result) + result' (if (:markup result) (update result :markup cu/generate-hiccup) - result)] - (dispatch [:set-in [:message-data data-type message-id] result]) - (when on-requested (on-requested result)))] + result)] + (dispatch [:set-in [:message-data data-type message-id] result']) + (when (= :preview data-type) + ;; update message in realm with serialized preview + (messages/update {:message-id message-id + :preview (prn-str result)})) + (when on-requested (on-requested result')))] ;chat-id path params callback lock? type (status/call-jail {:jail-id jail-id' :path path @@ -64,4 +70,12 @@ (fn [db [_ {:keys [message-id] :as message}]] (let [previews (get-in db [:message-data :preview])] (when-not (contains? previews message-id) - (dispatch [:request-command-data message :preview])))))) + (let [{serialized-preview :preview} (messages/get-by-id message-id)] + ;; if preview is already cached in db, do not request it from jail + ;; and write it directly to message-data path + (if serialized-preview + (dispatch [:set-in [:message-data :preview message-id] + (-> serialized-preview + reader/read-string + (update :markup cu/generate-hiccup))]) + (dispatch [:request-command-data message :preview])))))))) diff --git a/src/status_im/data_store/messages.cljs b/src/status_im/data_store/messages.cljs index b7b168354b..b67f0e5214 100644 --- a/src/status_im/data_store/messages.cljs +++ b/src/status_im/data_store/messages.cljs @@ -2,6 +2,7 @@ (:require [status-im.data-store.realm.messages :as data-store] [clojure.string :refer [join split]] [status-im.utils.random :refer [timestamp]] + [status-im.utils.utils :refer [update-if-present]] [clojure.walk :refer [stringify-keys keywordize-keys]] [cljs.reader :refer [read-string]] [status-im.constants :as c]) @@ -111,10 +112,10 @@ :timestamp (timestamp)})] (data-store/save message')))) -(defn update +(defn update [{:keys [message-id] :as message}] (when (data-store/exists? message-id) - (let [message (clojure.core/update message :user-statuses vals)] + (let [message (update-if-present message :user-statuses vals)] (data-store/save message)))) (defn delete-by-chat-id [chat-id] diff --git a/src/status_im/utils/utils.cljs b/src/status_im/utils/utils.cljs index 47cc149e94..d107363d23 100644 --- a/src/status_im/utils/utils.cljs +++ b/src/status_im/utils/utils.cljs @@ -20,11 +20,11 @@ (.alert (.-Alert rn-dependencies/react-native) title content - ; Styles are only relevant on iOS. On Android first button is 'neutral' and second is 'positive' + ;; Styles are only relevant on iOS. On Android first button is 'neutral' and second is 'positive' (clj->js - (vector (merge {:text (label :t/cancel) :style "cancel"} - (when on-cancel {:onPress on-cancel})) - {:text (or s "OK") :onPress on-accept :style "destructive"}))))) + (vector (merge {:text (label :t/cancel) :style "cancel"} + (when on-cancel {:onPress on-cancel})) + {:text (or s "OK") :onPress on-accept :style "destructive"}))))) (defn http-post ([action data on-success] @@ -49,7 +49,7 @@ (defn http-get ([url on-success on-error] - (http-get url nil on-success on-error)) + (http-get url nil on-success on-error)) ([url valid-response? on-success on-error] (-> (.fetch js/window url (clj->js {:method "GET" :headers {"Cache-Control" "no-cache"}})) @@ -72,9 +72,13 @@ (fn [error] (show-popup "Error" (str error)))))))) -(defn truncate-str [s max] - (if (and (< max (count s)) s) - (str (subs s 0 (- max 3)) "...") +(defn truncate-str + "Given string and max threshold, trims the string to threshold length with `...` + appended to end if length of the string exceeds max threshold, returns the same + string if threshold is not exceeded" + [s threshold] + (if (and s (< threshold (count s))) + (str (subs s 0 (- threshold 3)) "...") s)) (defn clean-text [s] @@ -84,14 +88,13 @@ (str/trim))) (defn first-index - [cond coll] - (loop [index 0 - cond cond - coll coll] - (when (seq coll) - (if (cond (first coll)) - index - (recur (inc index) cond (next coll)))))) + "Returns first index in coll where predicate on coll element is truthy" + [pred coll] + (->> coll + (keep-indexed (fn [idx e] + (when (pred e) + idx))) + first)) (defn hash-tag? [s] (= \# (first s))) @@ -105,3 +108,11 @@ (vreset! called? true) (apply f args) nil)))) + +(defn update-if-present + "Like regular `clojure.core/update` but returns original map if update key is not present" + [m k f & args] + (if (contains? m k) + (apply update m k f args) + m)) + diff --git a/test/cljs/status_im/test/utils/utils.cljs b/test/cljs/status_im/test/utils/utils.cljs index 8dd53f526a..90d33401cb 100644 --- a/test/cljs/status_im/test/utils/utils.cljs +++ b/test/cljs/status_im/test/utils/utils.cljs @@ -1,6 +1,6 @@ (ns status-im.test.utils.utils - (:require [cljs.test :refer-macros [deftest is]] - [status-im.utils.utils :as u])) + (:require [cljs.test :refer-macros [deftest is]] + [status-im.utils.utils :as u])) (deftest wrap-as-call-once-test (let [count (atom 0)] @@ -9,4 +9,30 @@ (is (nil? (f))) (is (= 1 @count)) (is (nil? (f))) - (is (= 1 @count)))))) \ No newline at end of file + (is (= 1 @count)))))) + +(deftest truncate-str-test + (is (= (u/truncate-str "Long string" 7) "Long...")) ; threshold is less then string length + (is (= (u/truncate-str "Long string" 11) "Long string")) ; threshold is the same as string length + (is (= (u/truncate-str "Long string" 20) "Long string"))) ; threshold is more then string length + +(deftest clean-text-test + (is (= (u/clean-text "Hello! \n\r") "Hello!") + (= (u/clean-text "Hello!") "Hello!"))) + +(deftest first-index-test + (is (= 2 (u/first-index (partial = :test) + '(:a :b :test :c :test)))) + (is (= nil (u/first-index (partial = :test) + '(:a :b :c))))) + +(deftest hash-tag?-test + (is (u/hash-tag? "#clojure")) + (is (not (u/hash-tag? "clojure"))) + (is (not (u/hash-tag? "clo#jure"))) + (is (not (u/hash-tag? "clojure#")))) + +(deftest update-if-present-test + (is (= {:a 1} (u/update-if-present {:a 0} :a inc))) + (is (= {:a 2} (u/update-if-present {:a 0} :a + 2))) + (is (= {:a 0} (u/update-if-present {:a 0} :b inc))))