From 16a52b38e8a1f1d880888e6eea97e98d791e03e7 Mon Sep 17 00:00:00 2001 From: flexsurfer Date: Thu, 14 Dec 2023 16:24:36 +0100 Subject: [PATCH] move input events (#18183) --- src/status_im/chat/models/input_test.cljs | 10 - src/status_im/chat/models/mentions.cljs | 15 + src/status_im/events.cljs | 1 - .../contexts/chat/composer/actions/view.cljs | 2 +- .../contexts/chat/composer/events.cljs} | 268 ++++++------------ .../contexts/chat/composer/mentions/view.cljs | 2 +- src/status_im2/events.cljs | 1 + src/utils/emojilib.cljs | 19 ++ 8 files changed, 116 insertions(+), 202 deletions(-) delete mode 100644 src/status_im/chat/models/input_test.cljs rename src/{status_im/chat/models/input.cljs => status_im2/contexts/chat/composer/events.cljs} (56%) create mode 100644 src/utils/emojilib.cljs diff --git a/src/status_im/chat/models/input_test.cljs b/src/status_im/chat/models/input_test.cljs deleted file mode 100644 index 8599c5f664..0000000000 --- a/src/status_im/chat/models/input_test.cljs +++ /dev/null @@ -1,10 +0,0 @@ -(ns status-im.chat.models.input-test - (:require - [cljs.test :refer-macros [deftest is]] - [status-im.chat.models.input :as input])) - -(deftest text->emoji - (is (nil? (input/text->emoji nil))) - (is (= "" (input/text->emoji ""))) - (is (= "test" (input/text->emoji "test"))) - (is (= "word1 \uD83D\uDC4D word2" (input/text->emoji "word1 :+1: word2")))) diff --git a/src/status_im/chat/models/mentions.cljs b/src/status_im/chat/models/mentions.cljs index e4db634a91..65c75b9b82 100644 --- a/src/status_im/chat/models/mentions.cljs +++ b/src/status_im/chat/models/mentions.cljs @@ -161,3 +161,18 @@ :on-error #(log/error "Error while calling wakuext_chatMentionClearMentions" {:error %})}]} (clear-suggestions)))) + +(rf/defn select-mention + {:events [:chat.ui/select-mention]} + [{:keys [db]} {:keys [primary-name searched-text match public-key] :as user}] + (let [chat-id (:current-chat-id db) + text (get-in db [:chat/inputs chat-id :input-text]) + method "wakuext_chatMentionSelectMention" + params [chat-id text primary-name public-key]] + {:json-rpc/call [{:method method + :params params + :on-success #(rf/dispatch [:mention/on-select-mention-success % + primary-name match searched-text public-key]) + :on-error #(rf/dispatch [:mention/on-error + {:method method + :params params} %])}]})) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 89c095dd9c..de010514ad 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -10,7 +10,6 @@ status-im.bootnodes.core status-im.browser.core status-im.browser.permissions - status-im.chat.models.input status-im.chat.models.loading status-im.contact.block status-im.currency.core diff --git a/src/status_im2/contexts/chat/composer/actions/view.cljs b/src/status_im2/contexts/chat/composer/actions/view.cljs index 15585bd895..970b792f8c 100644 --- a/src/status_im2/contexts/chat/composer/actions/view.cljs +++ b/src/status_im2/contexts/chat/composer/actions/view.cljs @@ -32,7 +32,7 @@ (js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300) - (rf/dispatch [:chat.ui/send-current-message]) + (rf/dispatch [:chat.ui/replace-mentions-and-send-current-message]) (rf/dispatch [:chat.ui/set-input-maximized false]) (rf/dispatch [:chat.ui/set-input-content-height comp-constants/input-height]) (rf/dispatch [:chat.ui/set-chat-input-text nil]) diff --git a/src/status_im/chat/models/input.cljs b/src/status_im2/contexts/chat/composer/events.cljs similarity index 56% rename from src/status_im/chat/models/input.cljs rename to src/status_im2/contexts/chat/composer/events.cljs index cea8ebb682..81343ca910 100644 --- a/src/status_im/chat/models/input.cljs +++ b/src/status_im2/contexts/chat/composer/events.cljs @@ -1,41 +1,25 @@ -(ns status-im.chat.models.input - (:require - ["emojilib" :as emojis] - [clojure.string :as string] - [goog.object :as object] - [re-frame.core :as re-frame] - [status-im.chat.models.mentions :as mentions] - [status-im.data-store.messages :as data-store-messages] - [status-im2.constants :as constants] - [status-im2.contexts.chat.composer.link-preview.events :as link-preview] - [status-im2.contexts.chat.messages.transport.events :as messages.transport] - [taoensso.timbre :as log] - [utils.i18n :as i18n] - [utils.re-frame :as rf] - [utils.string :as utils.string])) - -(defn text->emoji - "Replaces emojis in a specified `text`" - [text] - (utils.string/safe-replace text - #":([a-z_\-+0-9]*):" - (fn [[original emoji-id]] - (if-let [emoji-map (object/get (.-lib emojis) emoji-id)] - (.-char ^js emoji-map) - original)))) - -;; effects +(ns status-im2.contexts.chat.composer.events + (:require [clojure.string :as string] + [status-im.chat.models.mentions :as mentions] + [status-im.data-store.messages :as data-store-messages] + [status-im2.constants :as constants] + [status-im2.contexts.chat.composer.link-preview.events :as link-preview] + [status-im2.contexts.chat.messages.transport.events :as messages.transport] + [taoensso.timbre :as log] + [utils.emojilib :as emoji] + [utils.i18n :as i18n] + [utils.re-frame :as rf] + utils.string)) (rf/defn set-chat-input-text - "Set input text for current-chat. Takes db and input text and cofx - as arguments and returns new fx. Always clear all validation messages." {:events [:chat.ui/set-chat-input-text]} [{:keys [db] :as cofx} new-input chat-id] (let [current-chat-id (or chat-id (:current-chat-id db))] - (rf/merge cofx - {:db (assoc-in db [:chat/inputs current-chat-id :input-text] (text->emoji new-input))} - (when (empty? new-input) - (mentions/clear-mentions))))) + (rf/merge + cofx + {:db (assoc-in db [:chat/inputs current-chat-id :input-text] (emoji/text->emoji new-input))} + (when (empty? new-input) + (mentions/clear-mentions))))) (rf/defn set-input-content-height {:events [:chat.ui/set-input-content-height]} @@ -66,27 +50,6 @@ [{db :db} recording?] {:db (assoc db :chats/recording? recording?)}) -(rf/defn select-mention - {:events [:chat.ui/select-mention]} - [{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}] - (let [chat-id (:current-chat-id db) - text (get-in db [:chat/inputs chat-id :input-text]) - method "wakuext_chatMentionSelectMention" - params [chat-id text primary-name public-key]] - {:json-rpc/call [{:method method - :params params - :on-success #(rf/dispatch [:mention/on-select-mention-success % - primary-name match searched-text public-key]) - :on-error #(rf/dispatch [:mention/on-error - {:method method - :params params} %])}]})) - -(rf/defn disable-chat-cooldown - "Turns off chat cooldown (protection against message spamming)" - {:events [:chat/disable-cooldown]} - [{:keys [db]}] - {:db (assoc db :chat/cooldown-enabled? false)}) - (rf/defn reply-to-message "Sets reference to previous chat message and focuses on input" {:events [:chat.ui/reply-to-message]} @@ -103,7 +66,7 @@ (rf/defn edit-message "Sets reference to previous chat message and focuses on input" {:events [:chat.ui/edit-message]} - [{:keys [db] :as cofx} message] + [{:keys [db]} message] (let [current-chat-id (:current-chat-id db) text (get-in message [:content :text])] {:db (-> db @@ -116,21 +79,6 @@ :dispatch-n [[:chat.ui/set-chat-input-text nil current-chat-id] [:mention/to-input-field text current-chat-id]]})) -(rf/defn show-contact-request-input - "Sets reference to previous chat message and focuses on input" - {:events [:chat.ui/send-contact-request]} - [{:keys [db]}] - (let [current-chat-id (:current-chat-id db)] - {:db (-> db - (assoc-in [:chat/inputs current-chat-id :metadata :sending-contact-request] - current-chat-id) - (assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] - nil) - (assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil) - (update-in [:chat/inputs current-chat-id :metadata] - dissoc - :sending-image))})) - (rf/defn cancel-message-reply "Cancels stage message reply" {:events [:chat.ui/cancel-message-reply]} @@ -138,49 +86,6 @@ (let [current-chat-id (:current-chat-id db)] {:db (assoc-in db [:chat/inputs current-chat-id :metadata :responding-to-message] nil)})) -(defn emoji-only-content? - "Determines if text is just an emoji" - [{:keys [text response-to]}] - (and (not response-to) - (string? text) - (re-matches constants/regx-emoji text))) - -(defn build-text-message - [{:keys [db]} input-text current-chat-id] - (when-not (string/blank? input-text) - (let [{:keys [message-id]} - (get-in db [:chat/inputs current-chat-id :metadata :responding-to-message]) - preferred-name (get-in db [:profile/profile :preferred-name]) - emoji? (emoji-only-content? {:text input-text - :response-to message-id})] - {:chat-id current-chat-id - :content-type (if emoji? - constants/content-type-emoji - constants/content-type-text) - :text input-text - :response-to message-id - :ens-name preferred-name - :link-previews (map #(select-keys % [:url :title :description :thumbnail]) - (get-in db [:chat/link-previews :unfurled]))}))) - -(defn build-image-messages - [{db :db} chat-id input-text] - (let [images (get-in db [:chat/inputs chat-id :metadata :sending-image]) - {:keys [message-id]} (get-in db [:chat/inputs chat-id :metadata :responding-to-message]) - album-id (str (random-uuid))] - (mapv (fn [[_ {:keys [resized-uri width height]}]] - {:chat-id chat-id - :album-id album-id - :content-type constants/content-type-image - :image-path (utils.string/safe-replace resized-uri #"file://" "") - :image-width width - :image-height height - :text input-text - :link-previews (map #(select-keys % [:url :title :description :thumbnail]) - (get-in db [:chat/link-previews :unfurled])) - :response-to message-id}) - images))) - (rf/defn clean-input [{:keys [db] :as cofx} current-chat-id] (rf/merge cofx @@ -201,6 +106,50 @@ (link-preview/reset-unfurled) (mentions/clear-mentions)))) + +(defn emoji-only-content? + "Determines if text is just an emoji" + [{:keys [text response-to]}] + (and (not response-to) + (string? text) + (re-matches constants/regx-emoji text))) + +(defn build-image-messages + [{db :db} chat-id input-text] + (let [images (get-in db [:chat/inputs chat-id :metadata :sending-image]) + {:keys [message-id]} (get-in db [:chat/inputs chat-id :metadata :responding-to-message]) + album-id (str (random-uuid))] + (mapv (fn [[_ {:keys [resized-uri width height]}]] + {:chat-id chat-id + :album-id album-id + :content-type constants/content-type-image + :image-path (utils.string/safe-replace resized-uri #"file://" "") + :image-width width + :image-height height + :text input-text + :link-previews (map #(select-keys % [:url :title :description :thumbnail]) + (get-in db [:chat/link-previews :unfurled])) + :response-to message-id}) + images))) + +(defn build-text-message + [{:keys [db]} input-text current-chat-id] + (when-not (string/blank? input-text) + (let [{:keys [message-id]} + (get-in db [:chat/inputs current-chat-id :metadata :responding-to-message]) + preferred-name (get-in db [:profile/profile :preferred-name]) + emoji? (emoji-only-content? {:text input-text + :response-to message-id})] + {:chat-id current-chat-id + :content-type (if emoji? + constants/content-type-emoji + constants/content-type-text) + :text input-text + :response-to message-id + :ens-name preferred-name + :link-previews (map #(select-keys % [:url :title :description :thumbnail]) + (get-in db [:chat/link-previews :unfurled]))}))) + (rf/defn send-messages [{:keys [db] :as cofx} input-text current-chat-id] (let [image-messages (build-image-messages cofx current-chat-id input-text) @@ -214,8 +163,10 @@ (messages.transport/send-chat-messages messages))))) (rf/defn send-audio-message - [{:keys [db] :as cofx} audio-path duration current-chat-id] - (let [{:keys [message-id]} + {:events [:chat/send-audio]} + [{:keys [db] :as cofx} audio-path duration] + (let [{:keys [current-chat-id]} db + {:keys [message-id]} (get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])] (when-not (string/blank? audio-path) (rf/merge @@ -230,17 +181,6 @@ (when message-id {:response-to message-id}))]))))) -(rf/defn send-sticker-message - [cofx {:keys [hash packID pack]} current-chat-id] - (when-not (or (string/blank? hash) (and (string/blank? packID) (string/blank? pack))) - (messages.transport/send-chat-messages - cofx - [{:chat-id current-chat-id - :content-type constants/content-type-sticker - :sticker {:hash hash - :pack (int (if (string/blank? packID) pack packID))} - :text (i18n/label :t/update-to-see-sticker {"locale" "en"})}]))) - (rf/defn send-edited-message [{:keys [db] :as cofx} text {:keys [message-id quoted-message chat-id]}] @@ -262,79 +202,29 @@ :js-response true :on-error #(log/error "failed to edit message " %) :on-success (fn [result] - (re-frame/dispatch [:sanitize-messages-and-process-response - result]))}]} + (rf/dispatch [:sanitize-messages-and-process-response + result]))}]} (link-preview/reset-unfurled) (cancel-message-edit))) -(rf/defn send-current-message +(rf/defn replace-mentions-and-send-current-message "Sends message from current chat input" - {:events [:chat.ui/send-current-message]} - [{{:keys [current-chat-id] :as db} :db :as cofx}] - (let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id]) - editing-message (:editing-message metadata) - method "wakuext_chatMentionReplaceWithPublicKey" - params [current-chat-id input-text]] - {:json-rpc/call [{:method method - :params params - :on-error #(rf/dispatch [:mention/on-error {:method method :params params} %]) - :on-success #(rf/dispatch [:mention/on-replace-with-public-key-success + {:events [:chat.ui/replace-mentions-and-send-current-message]} + [{{:keys [current-chat-id] :as db} :db}] + (let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])] + {:json-rpc/call [{:method "wakuext_chatMentionReplaceWithPublicKey" + :params [current-chat-id input-text] + :on-error #(log/error "[wakuext_chatMentionReplaceWithPublicKey] on-error" %) + :on-success #(rf/dispatch [:chat.ui/send-current-message-with-mentions current-chat-id - editing-message + (:editing-message metadata) input-text %])}]})) -(rf/defn on-replace-with-public-key-success - {:events [:mention/on-replace-with-public-key-success]} +(rf/defn send-current-message-with-mentions + {:events [:chat.ui/send-current-message-with-mentions]} [{:keys [db] :as cofx} current-chat-id editing-message input-text new-text] - (log/debug "[mentions] on-replace-with-public-key-success" - {:chat-id current-chat-id - :editing-message editing-message - :input-text input-text - :new-text new-text}) (rf/merge cofx (if editing-message (send-edited-message new-text editing-message) (send-messages new-text current-chat-id)))) - -(rf/defn send-contact-request - {:events [:contacts/send-contact-request]} - [{:keys [db] :as cofx} public-key message] - (rf/merge cofx - {:chat.ui/clear-inputs nil - :json-rpc/call [{:method "wakuext_sendContactRequest" - :js-response true - :params [{:id public-key :message message}] - :on-error #(log/warn "failed to send a contact request" %) - :on-success #(re-frame/dispatch [:transport/message-sent %])}]} - (mentions/clear-mentions) - (clean-input (:current-chat-id db)))) - -(rf/defn cancel-contact-request - "Cancels contact request" - {:events [:chat.ui/cancel-contact-request]} - [{:keys [db] :as cofx}] - (let [current-chat-id (:current-chat-id db)] - (rf/merge cofx - {:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-contact-request] nil)} - (mentions/clear-mentions) - (clean-input (:current-chat-id db))))) - -(rf/defn chat-send-sticker - {:events [:chat/send-sticker]} - [{{:keys [current-chat-id] :as db} :db :as cofx} {:keys [hash packID pack] :as sticker}] - (rf/merge - cofx - {:db (update db - :stickers/recent-stickers - (fn [recent] - (conj (remove #(= hash (:hash %)) recent) sticker))) - :json-rpc/call [{:method "stickers_addRecent" - :params [(int (if (string/blank? packID) pack packID)) hash] - :on-success #()}]} - (send-sticker-message sticker current-chat-id))) - -(rf/defn chat-send-audio - {:events [:chat/send-audio]} - [{{:keys [current-chat-id] :as db} :db :as cofx} audio-path duration] - (send-audio-message cofx audio-path duration current-chat-id)) diff --git a/src/status_im2/contexts/chat/composer/mentions/view.cljs b/src/status_im2/contexts/chat/composer/mentions/view.cljs index 56f2abbcd9..e4ad797e0b 100644 --- a/src/status_im2/contexts/chat/composer/mentions/view.cljs +++ b/src/status_im2/contexts/chat/composer/mentions/view.cljs @@ -25,7 +25,7 @@ [user _ _ render-data] [contact-list-item/contact-list-item {:on-press (fn [] - (rf/dispatch [:chat.ui/select-mention nil user]) + (rf/dispatch [:chat.ui/select-mention user]) (update-cursor user render-data))} user]) diff --git a/src/status_im2/events.cljs b/src/status_im2/events.cljs index 6e489561d5..2f58b45fd8 100644 --- a/src/status_im2/events.cljs +++ b/src/status_im2/events.cljs @@ -11,6 +11,7 @@ status-im2.common.theme.events [status-im2.common.toasts.events] [status-im2.contexts.add-new-contact.events] + status-im2.contexts.chat.composer.events status-im2.contexts.chat.events status-im2.contexts.chat.photo-selector.events status-im2.contexts.communities.overview.events diff --git a/src/utils/emojilib.cljs b/src/utils/emojilib.cljs new file mode 100644 index 0000000000..1b86698815 --- /dev/null +++ b/src/utils/emojilib.cljs @@ -0,0 +1,19 @@ +(ns utils.emojilib + (:require ["emojilib" :as emojis] + [goog.object :as object] + utils.string)) + +(def lib (.-lib emojis)) + +(defn get-char + [emoji-id] + (when-let [emoji-map (object/get lib emoji-id)] + (.-char ^js emoji-map))) + +(defn text->emoji + "Replaces emojis in a specified `text`" + [text] + (utils.string/safe-replace text + #":([a-z_\-+0-9]*):" + (fn [[original emoji-id]] + (or (get-char emoji-id) original))))