diff --git a/externs.js b/externs.js index dc8109442b..c17400716d 100644 --- a/externs.js +++ b/externs.js @@ -589,6 +589,8 @@ var TopLevel = { "prev": function() {}, "hasNext": function() {}, "hasPrev": function() {}, + "rtl": function() {}, + "lineCount": function() {}, "key": function() {}, "keys": function() {}, "values": function() {}, diff --git a/src/status_im/chat/models/input.cljs b/src/status_im/chat/models/input.cljs index 6b7fc42a9f..de4b6c918b 100644 --- a/src/status_im/chat/models/input.cljs +++ b/src/status_im/chat/models/input.cljs @@ -7,6 +7,7 @@ [status-im.chat.commands.sending :as commands.sending] [status-im.chat.constants :as chat.constants] [status-im.chat.models :as chat] + [status-im.chat.models.message-content :as message-content] [status-im.chat.models.message :as chat.message] [status-im.constants :as constants] [status-im.js-dependencies :as dependencies] @@ -125,11 +126,15 @@ (let [{:keys [message-id]} (get-in db [:chats current-chat-id :metadata :responding-to-message]) show-name? (get-in db [:multiaccount :show-name?]) - preferred-name (when show-name? (get-in db [:multiaccount :preferred-name]))] + preferred-name (when show-name? (get-in db [:multiaccount :preferred-name])) + emoji? (message-content/emoji-only-content? {:text input-text + :response-to message-id})] (fx/merge cofx {:db (assoc-in db [:chats current-chat-id :metadata :responding-to-message] nil)} (chat.message/send-message {:chat-id current-chat-id - :content-type constants/content-type-text + :content-type (if emoji? + constants/content-type-emoji + constants/content-type-text) :content (cond-> {:chat-id current-chat-id :text input-text} message-id @@ -140,15 +145,6 @@ (set-chat-input-text nil) (process-cooldown))))) -(defn send-plain-text-message-fx - "no command detected, when not empty, proceed by sending text message without command processing" - [{:keys [db] :as cofx} message-text current-chat-id] - (when-not (string/blank? message-text) - (chat.message/send-message cofx {:chat-id current-chat-id - :content-type constants/content-type-text - :content (cond-> {:chat-id current-chat-id - :text message-text})}))) - (fx/defn send-sticker-fx [{:keys [db] :as cofx} {:keys [hash pack]} current-chat-id] (when-not (string/blank? hash) diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 7cfe2eb21f..8886b7281e 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -2,6 +2,7 @@ (:require [re-frame.core :as re-frame] [status-im.multiaccounts.model :as multiaccounts.model] [status-im.chat.commands.receiving :as commands-receiving] + [status-im.ethereum.json-rpc :as json-rpc] [status-im.chat.db :as chat.db] [status-im.chat.models :as chat-model] [status-im.chat.models.loading :as chat-loading] @@ -37,17 +38,14 @@ (defn- prepare-message [{:keys [content content-type] :as message} chat-id current-chat?] - (let [emoji? (message-content/emoji-only-content? content)] - ;; TODO janherich: enable the animations again once we can do them more efficiently - (cond-> message - current-chat? - (assoc :seen true) + (cond-> message + current-chat? + (assoc :seen true) (and (= constants/content-type-text content-type) + (message-content/should-collapse? + (:text content) + (:line-count content))) - emoji? - (assoc :content-type constants/content-type-emoji) - - (and (= constants/content-type-text content-type) (not emoji?)) - (update :content message-content/enrich-content)))) + (assoc :should-collapse? true))) (defn system-message? [{:keys [message-type]}] (= :system-message message-type)) @@ -250,24 +248,46 @@ :message message :current-chat? (= (get-in cofx [:db :current-chat-id]) chat-id)}))) -(fx/defn upsert-and-send - [{:keys [now] :as cofx} {:keys [chat-id from] :as message}] - (let [message (remove-icon message) - send-record (protocol/map->Message (select-keys message transport-keys)) +(fx/defn prepare-message-content [cofx chat-id message] + {::json-rpc/call + [{:method "shhext_prepareContent" + :params [(:content message)] + :on-success #(re-frame/dispatch [::prepared-message chat-id message %]) + :on-failure #(log/error "failed to prepare content" %)}]}) + +(fx/defn prepared-message + {:events [::prepared-message]} + [{:keys [now] :as cofx} chat-id message content] + (let [message-with-content + (update message :content + assoc + :parsed-text (:parsedText content) + :line-count (:lineCount content) + :should-collapse? (message-content/should-collapse? + (:text content) + (:lineCount content)) + :rtl? (:rtl content)) + send-record (protocol/map->Message + (select-keys message-with-content transport-keys)) wrapped-record (if (= (:message-type send-record) :group-user-message) (wrap-group-message cofx chat-id send-record) - send-record) - message (assoc message :outgoing-status :sending)] - + send-record)] (fx/merge cofx (chat-model/upsert-chat {:chat-id chat-id :timestamp now - :last-message-timestamp (:timestamp message) - :last-message-content (:content message) - :last-message-content-type (:content-type message) - :last-clock-value (:clock-value message)}) - (send chat-id message wrapped-record)))) + :last-message-timestamp (:timestamp message-with-content) + :last-message-content (:content message-with-content) + :last-message-content-type (:content-type message-with-content) + :last-clock-value (:clock-value message-with-content)}) + (send chat-id message-with-content wrapped-record)))) + +(fx/defn upsert-and-send + [{:keys [now] :as cofx} {:keys [chat-id from] :as message}] + (let [message (remove-icon message) + message (assoc message :outgoing-status :sending)] + + (prepare-message-content cofx chat-id message))) (fx/defn update-message-status [{:keys [db] :as cofx} chat-id message-id status] diff --git a/src/status_im/chat/models/message_content.cljs b/src/status_im/chat/models/message_content.cljs index 20fda0f0e2..39a3658055 100644 --- a/src/status_im/chat/models/message_content.cljs +++ b/src/status_im/chat/models/message_content.cljs @@ -40,9 +40,9 @@ (and (seq text) (re-matches constants/regx-rtl-characters (first text)))) -(defn- should-collapse? [text] +(defn should-collapse? [text line-count] (or (<= constants/chars-collapse-threshold (count text)) - (<= constants/lines-collapse-threshold (inc (count (query-regex #"\n" text)))))) + (<= constants/lines-collapse-threshold (inc line-count)))) (defn- sorted-ranges [{:keys [metadata text]} metadata-keys] (->> (if metadata-keys @@ -81,28 +81,6 @@ (cond-> builder end-record (conj end-record)))))) -(defn enrich-content - "Enriches message content with `:metadata`, `:render-recipe` and `:rtl?` information. - Metadata map keys can by any of the `:link`, `:tag`, `:mention` actions - or `:bold` and `:italic` stylings. - Value for each key is sequence of tuples representing ranges in original - `:text` content. " - [{:keys [text] :as content}] - (let [[_ metadata] (reduce (fn [[text metadata] [type regex]] - (if-let [matches (query-regex regex text)] - [(clear-ranges matches text) (assoc metadata type matches)] - [text metadata])) - [text {}] - (if platform/desktop? - (into stylings actions) - actions))] - (cond-> content - (seq metadata) (as-> content - (assoc content :metadata metadata) - (assoc content :render-recipe (build-render-recipe content))) - (right-to-left-text? text) (assoc :rtl? true) - (should-collapse? text) (assoc :should-collapse? true)))) - (defn emoji-only-content? "Determines if text is just an emoji" [{:keys [text response-to]}] diff --git a/src/status_im/ethereum/json_rpc.cljs b/src/status_im/ethereum/json_rpc.cljs index 23d3436d31..f7a3317136 100644 --- a/src/status_im/ethereum/json_rpc.cljs +++ b/src/status_im/ethereum/json_rpc.cljs @@ -51,6 +51,7 @@ "shhext_chatMessages" {} "shhext_saveChat" {} "shhext_contacts" {} + "shhext_prepareContent" {} "shhext_blockContact" {} ;;TODO not used anywhere? "shhext_deleteChat" {} diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 88e70e433b..f4f20d0d87 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -616,11 +616,6 @@ {:db (assoc db :view-id view-id)} #(mark-messages-seen %)))) -(handlers/register-handler-fx - :chat/send-plain-text-message - (fn [{{:keys [current-chat-id]} :db :as cofx} [_ message-text]] - (chat.input/send-plain-text-message-fx cofx message-text current-chat-id))) - (handlers/register-handler-fx :chat/send-sticker (fn [{{:keys [current-chat-id multiaccount]} :db :as cofx} [_ {:keys [hash] :as sticker}]] diff --git a/src/status_im/group_chats/core.cljs b/src/status_im/group_chats/core.cljs index bdb85fe124..aba7602c69 100644 --- a/src/status_im/group_chats/core.cljs +++ b/src/status_im/group_chats/core.cljs @@ -3,7 +3,9 @@ (:require [clojure.set :as clojure.set] [clojure.spec.alpha :as spec] [clojure.string :as string] + [status-im.ethereum.json-rpc :as json-rpc] [re-frame.core :as re-frame] + [status-im.chat.models.message-content :as message-content] [status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.model :as multiaccounts.model] [status-im.utils.pairing :as pairing.utils] @@ -463,6 +465,43 @@ (transport.filters/upsert-group-chat-topics) (transport.filters/load-members members))))) +(fx/defn prepared-message + {:events [::prepared-message]} + [{:keys [now] :as cofx} + chat-id message + content + sender-signature + whisper-timestamp + metadata] + (let [message-with-content + (update message :content + assoc + :parsed-text (:parsedText content) + :line-count (:lineCount content) + :should-collapse? (message-content/should-collapse? + (:text content) + (:lineCount content)) + :rtl? (:rtl content))] + (protocol/receive message-with-content + chat-id + sender-signature + whisper-timestamp + (assoc cofx :metadata metadata)))) + +(fx/defn prepare-message-content + [cofx chat-id message sender-signature whisper-timestamp metadata] + {::json-rpc/call + [{:method "shhext_prepareContent" + :params [(:content message)] + :on-success #(re-frame/dispatch [::prepared-message + chat-id + message + % + sender-signature + whisper-timestamp + metadata]) + :on-failure #(log/error "failed to prepare content" %)}]}) + (fx/defn handle-membership-update "Upsert chat and receive message if valid" ;; Care needs to be taken here as chat-id is not coming from a whisper filter @@ -498,11 +537,13 @@ ;; don't allow anything but group messages (instance? protocol/Message message) (= :group-user-message (:message-type message))) - (protocol/receive message - chat-id - sender-signature - whisper-timestamp - (assoc % :metadata metadata)))))))) + (prepare-message-content + % + chat-id + message + sender-signature + whisper-timestamp + metadata))))))) (defn handle-sign-success "Upsert chat and send signed payload to group members" diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 2c2a2d7fb5..96bc9a1f59 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -505,9 +505,9 @@ (re-frame/reg-sub ::show-suggestions-view? :<- [:chats/current-chat-ui-prop :show-suggestions?] - :<- [:chats/current-chat] + :<- [:chats/current-chat-input-text] :<- [:chats/all-available-commands] - (fn [[show-suggestions? {:keys [input-text]} commands]] + (fn [[show-suggestions? input-text commands]] (and (or show-suggestions? (commands.input/starts-as-command? (string/trim (or input-text "")))) (seq commands)))) @@ -523,7 +523,7 @@ ::get-commands-for-chat :<- [:chats/id->command] :<- [::access-scope->command-id] - :<- [:chats/current-chat] + :<- [:chats/current-raw-chat] (fn [[id->command access-scope->command-id chat]] (commands/chat-commands id->command access-scope->command-id chat))) @@ -666,9 +666,21 @@ :messages)))) (re-frame/reg-sub - :chats/current-chat + :chats/current-raw-chat :<- [:chats/active-chats] :<- [:chats/current-chat-id] + (fn [[chats current-chat-id]] + (get chats current-chat-id))) + +(re-frame/reg-sub + :chats/current-chat-input-text + :<- [:chats/current-raw-chat] + (fn [chat] + (:input-text chat))) + +(re-frame/reg-sub + :chats/current-chat + :<- [:chats/current-raw-chat] :<- [:multiaccount/public-key] :<- [:mailserver/ranges] :<- [:chats/content-layout-height] @@ -677,27 +689,28 @@ :<- [:ethereum/chain-keyword] :<- [:prices] :<- [:wallet/currency] - (fn [[chats current-chat-id my-public-key ranges height + (fn [[{:keys [group-chat + chat-id + contact + messages] + :as current-chat} my-public-key ranges height input-height ttt-settings chain-keyword prices currency]] - (let [{:keys [group-chat contact messages] - :as current-chat} - (get chats current-chat-id)] - (when current-chat - (cond-> (enrich-current-chat current-chat ranges height input-height) - (empty? messages) - (assoc :universal-link - (links/generate-link :public-chat :external current-chat-id)) + (when current-chat + (cond-> (enrich-current-chat current-chat ranges height input-height) + (empty? messages) + (assoc :universal-link + (links/generate-link :public-chat :external chat-id)) - (chat.models/public-chat? current-chat) - (assoc :show-input? true) + (chat.models/public-chat? current-chat) + (assoc :show-input? true) - (and (chat.models/group-chat? current-chat) - (group-chats.db/joined? my-public-key current-chat)) - (assoc :show-input? true) + (and (chat.models/group-chat? current-chat) + (group-chats.db/joined? my-public-key current-chat)) + (assoc :show-input? true) - (not group-chat) - (enrich-current-one-to-one-chat my-public-key ttt-settings - chain-keyword prices currency)))))) + (not group-chat) + (enrich-current-one-to-one-chat my-public-key ttt-settings + chain-keyword prices currency))))) (re-frame/reg-sub :chats/current-chat-message @@ -798,10 +811,10 @@ (re-frame/reg-sub :chats/selected-chat-command - :<- [:chats/current-chat] + :<- [:chats/current-chat-input-text] :<- [:chats/current-chat-ui-prop :selection] :<- [::get-commands-for-chat] - (fn [[{:keys [input-text]} selection commands]] + (fn [[input-text selection commands]] (commands.input/selected-chat-command input-text selection commands))) (re-frame/reg-sub diff --git a/src/status_im/transport/db.cljs b/src/status_im/transport/db.cljs index 605393ca6d..85a25afcdd 100644 --- a/src/status_im/transport/db.cljs +++ b/src/status_im/transport/db.cljs @@ -59,6 +59,7 @@ (spec/def :message.content/params (spec/map-of keyword? any?)) (spec/def ::content-type #{constants/content-type-text constants/content-type-command + constants/content-type-emoji constants/content-type-command-request constants/content-type-sticker}) (spec/def ::message-type #{:group-user-message :public-group-user-message :user-message}) (spec/def ::clock-value (spec/and pos-int? diff --git a/src/status_im/transport/message/core.cljs b/src/status_im/transport/message/core.cljs index 1bc6c749bc..860b462047 100644 --- a/src/status_im/transport/message/core.cljs +++ b/src/status_im/transport/message/core.cljs @@ -12,6 +12,7 @@ [status-im.transport.message.transit :as transit] [status-im.transport.utils :as transport.utils] [status-im.tribute-to-talk.whitelist :as whitelist] + [cljs-bean.core :as clj-bean] [status-im.utils.config :as config] [status-im.utils.fx :as fx] [taoensso.timbre :as log] @@ -19,14 +20,20 @@ (def message-type-message 1) +(defn build-content [content-js] + {:text (.-text content-js) + :line-count (.-lineCount content-js) + :parsed-text (clj-bean/->clj (.-parsedText content-js)) + :name (.-name content-js) + :rtl? (.-rtl content-js) + :response-to (aget content-js "response-to") + :chat-id (.-chat_id content-js)}) + (defn build-message [parsed-message-js] (let [content (.-content parsed-message-js) built-message (protocol/Message. - {:text (.-text content) - :response-to (aget content "response-to") - :name (.-name content) - :chat-id (.-chat_id content)} + (build-content content) (.-content_type parsed-message-js) (keyword (.-message_type parsed-message-js)) (.-clock parsed-message-js) diff --git a/src/status_im/ui/components/colors.cljs b/src/status_im/ui/components/colors.cljs index 08507daf76..affa975ec3 100644 --- a/src/status_im/ui/components/colors.cljs +++ b/src/status_im/ui/components/colors.cljs @@ -25,7 +25,7 @@ (def black-transparent (alpha black 0.1)) ;; Used as background color for rounded button on dark background and as background color for containers like "Backup recovery phrase" (def black-transparent-20 (alpha black 0.2)) ; accounts divider (def black-transparent-40 (alpha black 0.4)) - +(def black-transparent-50 (alpha black 0.5)) (def black-light "#2d2d2d") ;; sign-with-keycard-button ;; DARK GREY diff --git a/src/status_im/ui/screens/chat/input/input.cljs b/src/status_im/ui/screens/chat/input/input.cljs index ef9c7cbee5..0c5e9129dd 100644 --- a/src/status_im/ui/screens/chat/input/input.cljs +++ b/src/status_im/ui/screens/chat/input/input.cljs @@ -24,7 +24,7 @@ [status-im.ui.screens.chat.stickers.views :as stickers])) (defview basic-text-input [{:keys [set-container-width-fn height single-line-input?]}] - (letsubs [{:keys [input-text]} [:chats/current-chat] + (letsubs [input-text [:chats/current-chat-input-text] cooldown-enabled? [:chats/cooldown-enabled?]] [react/text-input (merge @@ -91,7 +91,7 @@ {:placeholder (i18n/label :cooldown/text-input-disabled)}))])) (defview invisible-input [{:keys [set-layout-width-fn value]}] - (letsubs [{:keys [input-text]} [:chats/current-chat]] + (letsubs [input-text [:chats/current-chat-input-text]] [react/text {:style style/invisible-input-text :on-layout #(let [w (-> (.-nativeEvent %) (.-layout) @@ -184,7 +184,7 @@ (defview input-container [] (letsubs [margin [:chats/input-margin] mainnet? [:mainnet?] - {:keys [input-text]} [:chats/current-chat] + input-text [:chats/current-chat-input-text] result-box [:chats/current-chat-ui-prop :result-box] show-stickers? [:chats/current-chat-ui-prop :show-stickers?] state-text (reagent/atom "")] diff --git a/src/status_im/ui/screens/chat/message/message.cljs b/src/status_im/ui/screens/chat/message/message.cljs index c3f2ef4cf5..6d1131aee4 100644 --- a/src/status_im/ui/screens/chat/message/message.cljs +++ b/src/status_im/ui/screens/chat/message/message.cljs @@ -2,8 +2,11 @@ (:require [re-frame.core :as re-frame] [status-im.chat.commands.receiving :as commands-receiving] [status-im.constants :as constants] + [status-im.utils.http :as http] [status-im.i18n :as i18n] + [reagent.core :as reagent] [status-im.ui.components.colors :as colors] + [status-im.utils.security :as security] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.popup-menu.views :as desktop.pop-up] @@ -66,32 +69,89 @@ :on-press #(re-frame/dispatch [:chat.ui/message-expand-toggled chat-id message-id])} (i18n/label (if expanded? :show-less :show-more))]) +(defn render-inline [message-text outgoing acc {:keys [type literal destination] :as node}] + (case type + "" + (conj acc literal) + + "code" + (conj acc [react/text-class style/inline-code-style literal]) + + "emph" + (conj acc [react/text-class (style/emph-style outgoing) literal]) + + "strong" + (conj acc [react/text-class (style/strong-style outgoing) literal]) + + "link" + (conj acc + [react/text-class + {:style + {:color (if outgoing colors/white colors/blue) + :text-decoration-line :underline} + :on-press + #(when (and (security/safe-link? destination) + (security/safe-link-text? message-text)) + (if platform/desktop? + (.openURL react/linking (http/normalize-url destination)) + (re-frame/dispatch + [:browser.ui/message-link-pressed destination])))} + destination]) + + "status-tag" + (conj acc [react/text-class + {:style {:color (if outgoing colors/white colors/blue) + :text-decoration-line :underline} + :on-press + #(re-frame/dispatch + [:chat.ui/start-public-chat literal {:navigation-reset? true}])} + "#" + literal]) + + (conj acc literal))) + +(defn render-block [{:keys [chat-id message-id content + timestamp-str group-chat outgoing + current-public-key expanded?] :as message} + acc + {:keys [type literal children]}] + (case type + + "paragraph" + (conj acc (reduce + (fn [acc e] (render-inline (:text content) outgoing acc e)) + [react/text-class (style/text-style outgoing)] + children)) + + "blockquote" + (conj acc [react/view (style/blockquote-style outgoing) + [react/text-class (style/blockquote-text-style outgoing) + (.substring literal 0 (dec (.-length literal)))]]) + + "codeblock" + (conj acc [react/view style/codeblock-style + [react/text-class style/codeblock-text-style + (.substring literal 0 (dec (.-length literal)))]]) + + acc)) + +(defn render-parsed-text [{:keys [timestamp-str + outgoing] :as message} + + tree] + (conj (reduce (fn [acc e] (render-block message acc e)) [react/view {}] tree) + [react/text {:style (style/message-timestamp-placeholder outgoing)} + (str " " timestamp-str)])) + (defn text-message [{:keys [chat-id message-id content timestamp-str group-chat outgoing current-public-key expanded?] :as message}] [message-view message - (let [response-to (:response-to content) - collapsible? (and (:should-collapse? content) group-chat)] + (let [response-to (:response-to content)] [react/view - (when response-to + (when (seq response-to) [quoted-message response-to (:quoted-message message) outgoing current-public-key]) - (apply react/nested-text - (cond-> {:style (style/text-message collapsible? outgoing) - :text-break-strategy :balanced - :parseBasicMarkdown true - :markdownCodeBackgroundColor colors/black - :markdownCodeForegroundColor colors/green} - - (and collapsible? (not expanded?)) - (assoc :number-of-lines constants/lines-collapse-threshold)) - (conj (if-let [render-recipe (:render-recipe content)] - (chat.utils/render-chunks render-recipe message) - [(:text content)]) - [{:style (style/message-timestamp-placeholder outgoing)} - (str " " timestamp-str)])) - - (when collapsible? - [expand-button expanded? chat-id message-id])]) + [render-parsed-text message (:parsed-text content)]]) {:justify-timestamp? true}]) (defn emoji-message diff --git a/src/status_im/ui/screens/chat/styles/message/message.cljs b/src/status_im/ui/screens/chat/styles/message/message.cljs index 5dda21444b..91671fc2bd 100644 --- a/src/status_im/ui/screens/chat/styles/message/message.cljs +++ b/src/status_im/ui/screens/chat/styles/message/message.cljs @@ -1,8 +1,10 @@ (ns status-im.ui.screens.chat.styles.message.message (:require [status-im.constants :as constants] [status-im.ui.components.colors :as colors] + [status-im.ui.components.react :as react] [status-im.ui.screens.chat.styles.photos :as photos] [status-im.utils.platform :as platform] + [status-im.ui.components.typography :as typography] [status-im.utils.styles :as styles])) (defn style-message-text @@ -216,3 +218,98 @@ :color (if outgoing colors/white-transparent-70 colors/gray)}) + +;; Markdown styles + +(def default-text-style + {:max-font-size-multiplier react/max-font-size-multiplier + :style (assoc typography/default-style + :line-height 22)}) + +(def outgoing-text-style + (update default-text-style :style + assoc :color colors/white)) + +(defn text-style [outgoing] + (if outgoing + outgoing-text-style + default-text-style)) + +(def emph-text-style + (update default-text-style :style + assoc :font-style :italic)) + +(def outgoing-emph-text-style + (update emph-text-style :style + assoc :color colors/white)) + +(defn emph-style [outgoing] + (if outgoing + outgoing-emph-text-style + emph-text-style)) + +(def strong-text-style + (update default-text-style :style + assoc :font-weight "700")) + +(def outgoing-strong-text-style + (update strong-text-style :style + assoc :color colors/white)) + +(defn strong-style [outgoing] + (if outgoing + outgoing-strong-text-style + strong-text-style)) + +(def monospace-fonts (if platform/ios? "Courier" "monospace")) + +(def code-block-background "#2E386B") + +(def inline-code-style + (update default-text-style :style + assoc + :font-family monospace-fonts + :color colors/white + :background-color code-block-background)) + +(def codeblock-style {:style {:padding 10 + :background-color code-block-background + :border-radius 4}}) + +(def codeblock-text-style + (update default-text-style :style + assoc + :font-family monospace-fonts + :color colors/white)) + +(def default-blockquote-style + {:style {:border-left-width 2 + :padding-left 3 + :border-left-color colors/gray-transparent-40}}) + +(def outgoing-blockquote-style + (update default-blockquote-style :style + assoc + :border-left-color colors/white-transparent)) + +(defn blockquote-style [outgoing] + (if outgoing + outgoing-blockquote-style + default-blockquote-style)) + +(def default-blockquote-text-style + (update default-text-style :style + assoc + :line-height 19 + :font-size 14 + :color colors/black-transparent-50)) + +(def outgoing-blockquote-text-style + (update default-blockquote-text-style :style + assoc + :color colors/white-transparent-70)) + +(defn blockquote-text-style [outgoing] + (if outgoing + outgoing-blockquote-text-style + default-blockquote-text-style)) diff --git a/src/status_im/utils/security.cljs b/src/status_im/utils/security.cljs index 897b70a375..8705e22d91 100644 --- a/src/status_im/utils/security.cljs +++ b/src/status_im/utils/security.cljs @@ -24,7 +24,7 @@ data)) ;; Links starting with javascript:// should not be handled at all -(def javascript-link-regex #"javascript://.*") +(def javascript-link-regex #"(?i)javascript://.*") ;; Anything with rtlo character we don't handle as it might be a spoofed url (def rtlo-link-regex #".*\u202e.*") diff --git a/status-go-version.json b/status-go-version.json index 18d4e71595..d3b569d8f9 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -2,7 +2,7 @@ "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead", "owner": "status-im", "repo": "status-go", - "version": "v0.34.0-beta.7", - "commit-sha1": "89659f85b49b48f4409ed9f522397b99728b214b", - "src-sha256": "0kyk3r2wl3qxz28ifgnk2r8lh5116q8s58pk9x044dsrl0zvn5qv" + "version": "v0.34.0-beta.8", + "commit-sha1": "9d7c570593b1f88e9688204d8e1041d57b98da1f", + "src-sha256": "1kwxf0h80vdj493c7s3lpmdjpbc72plbll0rj1vv7kzf8a84ff2k" } diff --git a/test/appium/tests/atomic/chats/test_one_to_one.py b/test/appium/tests/atomic/chats/test_one_to_one.py index 492d7cd89d..a63c4dee7b 100644 --- a/test/appium/tests/atomic/chats/test_one_to_one.py +++ b/test/appium/tests/atomic/chats/test_one_to_one.py @@ -207,7 +207,7 @@ class TestMessagesOneToOneChatMultiple(MultipleDeviceTestCase): home_2.home_button.click() chat_1 = home_1.add_contact(public_key_2) - url_message = 'status.im' + url_message = 'http://status.im' chat_1.chat_message_input.send_keys(url_message) chat_1.send_message_button.click() chat_1.get_back_to_home_view() diff --git a/test/cljs/status_im/test/chat/models/message_content.cljs b/test/cljs/status_im/test/chat/models/message_content.cljs deleted file mode 100644 index eb36221e5d..0000000000 --- a/test/cljs/status_im/test/chat/models/message_content.cljs +++ /dev/null @@ -1,45 +0,0 @@ -(ns status-im.test.chat.models.message-content - (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.utils.platform :as platform] - [status-im.chat.models.message-content :as message-content])) - -(deftest enrich-string-content-test - (if platform/desktop? - (testing "Text content of the message is enriched correctly" - (is (not (:metadata (message-content/enrich-content {:text "Plain message"})))) - (is (= {:bold [[5 14]]} - (:metadata (message-content/enrich-content {:text "Some *styling* present"})))) - (is (= {:bold [[5 14]] - :tag [[28 33] [38 43]]} - (:metadata (message-content/enrich-content {:text "Some *styling* present with #tag1 and #tag2 as well"})))))) - - (testing "right to left is correctly identified" - (is (not (:rtl? (message-content/enrich-content {:text "You are lucky today!"})))) - (is (not (:rtl? (message-content/enrich-content {:text "42"})))) - (is (not (:rtl? (message-content/enrich-content {:text "You are lucky today! أنت محظوظ اليوم!"})))) - (is (not (:rtl? (message-content/enrich-content {:text "۱۲۳۴۵۶۷۸۹"})))) - (is (not (:rtl? (message-content/enrich-content {:text "۱۲۳۴۵۶۷۸۹أنت محظوظ اليوم!"})))) - (is (:rtl? (message-content/enrich-content {:text "أنت محظوظ اليوم!"}))) - (is (:rtl? (message-content/enrich-content {:text "أنت محظوظ اليوم! You are lucky today"}))) - (is (:rtl? (message-content/enrich-content {:text "יש לך מזל היום!"}))))) - -(deftest build-render-recipe-test - (testing "Render tree is build from text" - (is (not (:render-recipe (message-content/enrich-content {:text "Plain message"})))) - (is (= (if platform/desktop? - '(["Test " :text] - ["#status" :tag] - [" one three " :text] - ["#core-chat (@developer)!" :bold] - [" By the way, " :text] - ["nice link(https://link.com)" :italic]) - '(["Test " :text] - ["#status" :tag] - [" one three *" :text] - ["#core-chat" :tag] - [" (" :text] - ["@developer" :mention] - [")!* By the way, ~nice link(" :text] - ["https://link.com" :link] - [")~" :text])) - (:render-recipe (message-content/enrich-content {:text "Test #status one three *#core-chat (@developer)!* By the way, ~nice link(https://link.com)~"})))))) diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index 9b177fd79b..d977c317d1 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -7,7 +7,6 @@ [status-im.test.chat.commands.input] [status-im.test.chat.db] [status-im.test.chat.models.input] - [status-im.test.chat.models.message-content] [status-im.test.chat.models.message] [status-im.test.chat.models.message-list] [status-im.test.chat.models] @@ -87,7 +86,6 @@ 'status-im.test.chat.models.input 'status-im.test.chat.models.message 'status-im.test.chat.models.message-list - 'status-im.test.chat.models.message-content 'status-im.test.chat.views.photos 'status-im.test.transport.filters.core 'status-im.test.contacts.db diff --git a/test/cljs/status_im/test/utils/security.cljs b/test/cljs/status_im/test/utils/security.cljs index 8a28739b36..08eafd2a8b 100644 --- a/test/cljs/status_im/test/utils/security.cljs +++ b/test/cljs/status_im/test/utils/security.cljs @@ -16,6 +16,10 @@ (deftest safe-link-test-exceptions (testing "a javascript link" (is (not (security/safe-link? "javascript://anything")))) + (testing "a javascript link mixed cases" + (is (not (security/safe-link? "JaVasCrIpt://anything")))) + (testing "a javascript link upper cases" + (is (not (security/safe-link? "JAVASCRIPT://anything")))) (testing "rtlo links" (is (not (security/safe-link? rtlo-link)))))