Move mentions logic to status-go (#15428)

This commit is contained in:
frank 2023-04-07 17:01:13 +08:00 committed by GitHub
parent c3ed15f30d
commit 9da9427488
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 291 additions and 1238 deletions

View File

@ -41,36 +41,19 @@
(rf/defn select-mention (rf/defn select-mention
{:events [:chat.ui/select-mention]} {:events [:chat.ui/select-mention]}
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match] :as user}] [{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}]
(let [chat-id (:current-chat-id db) (let [chat-id (:current-chat-id db)
new-text (mentions/new-input-text-with-mention cofx user) text (get-in db [:chat/inputs chat-id :input-text])
at-sign-idx (get-in db [:chats/mentions chat-id :mentions :at-sign-idx]) method "wakuext_chatMentionNewInputTextWithMention"
cursor (+ at-sign-idx (count primary-name) 2)] params [chat-id text primary-name]]
(rf/merge {:json-rpc/call [{:method method
cofx :params params
{:db (-> db :on-success #(rf/dispatch [:mention/on-new-input-text-with-mentions-success %
(assoc-in [:chats/cursor chat-id] cursor) primary-name text-input-ref match searched-text
(assoc-in [:chats/mention-suggestions chat-id] nil)) public-key])
:set-text-input-value [chat-id new-text text-input-ref]} :on-error #(rf/dispatch [:mention/on-error
(set-chat-input-text new-text chat-id) {:method method
;; NOTE(rasom): Some keyboards do not react on selection property passed to :params params} %])}]}))
;; text input (specifically Samsung keyboard with predictive text set on).
;; In this case, if the user continues typing after the programmatic change,
;; the new text is added to the last known cursor position before
;; programmatic change. By calling `reset-text-input-cursor` we force the
;; keyboard's cursor position to be changed before the next input.
(mentions/reset-text-input-cursor text-input-ref cursor)
;; NOTE(roman): on-text-input event is not dispatched when we change input
;; programmatically, so we have to call `on-text-input` manually
(mentions/on-text-input
(let [match-len (count match)
start (inc at-sign-idx)
end (+ start match-len)]
{:new-text match
:previous-text searched-text
:start start
:end end}))
(mentions/recheck-at-idxs {primary-name user}))))
(rf/defn disable-chat-cooldown (rf/defn disable-chat-cooldown
"Turns off chat cooldown (protection against message spamming)" "Turns off chat cooldown (protection against message spamming)"
@ -182,8 +165,7 @@
(rf/merge cofx (rf/merge cofx
{:set-text-input-value [current-chat-id ""]} {:set-text-input-value [current-chat-id ""]}
(clean-input current-chat-id) (clean-input current-chat-id)
(mentions/clear-mentions) (mentions/clear-mentions))))
(mentions/clear-cursor))))
(rf/defn send-messages (rf/defn send-messages
[{:keys [db] :as cofx} input-text current-chat-id] [{:keys [db] :as cofx} input-text current-chat-id]
@ -251,13 +233,29 @@
[{{:keys [current-chat-id] :as db} :db :as cofx}] [{{:keys [current-chat-id] :as db} :db :as cofx}]
(let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id]) (let [{:keys [input-text metadata]} (get-in db [:chat/inputs current-chat-id])
editing-message (:editing-message metadata) editing-message (:editing-message metadata)
input-text-with-mentions (mentions/check-mentions cofx input-text)] method "wakuext_chatMentionCheckMentions"
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-check-mentions-success
current-chat-id
editing-message
input-text
%])}]}))
(rf/defn on-check-mentions-success
{:events [:mention/on-check-mentions-success]}
[{:keys [db] :as cofx} current-chat-id editing-message input-text new-text]
(log/debug "[mentions] on-check-mentions-success"
{:chat-id current-chat-id
:editing-message editing-message
:input-text input-text
:new-text new-text})
(rf/merge cofx (rf/merge cofx
(if editing-message (if editing-message
(send-edited-message input-text-with-mentions editing-message) (send-edited-message new-text editing-message)
(send-messages input-text-with-mentions current-chat-id)) (send-messages new-text current-chat-id))))
(mentions/clear-mentions)
(mentions/clear-cursor))))
(rf/defn send-contact-request (rf/defn send-contact-request
{:events [:contacts/send-contact-request]} {:events [:contacts/send-contact-request]}
@ -271,7 +269,6 @@
:on-error #(log/warn "failed to send a contact request" %) :on-error #(log/warn "failed to send a contact request" %)
:on-success #(re-frame/dispatch [:transport/message-sent %])}]} :on-success #(re-frame/dispatch [:transport/message-sent %])}]}
(mentions/clear-mentions) (mentions/clear-mentions)
(mentions/clear-cursor)
(clean-input (:current-chat-id db)))) (clean-input (:current-chat-id db))))
(rf/defn cancel-contact-request (rf/defn cancel-contact-request
@ -282,7 +279,6 @@
(rf/merge cofx (rf/merge cofx
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-contact-request] nil)} {:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-contact-request] nil)}
(mentions/clear-mentions) (mentions/clear-mentions)
(mentions/clear-cursor)
(clean-input (:current-chat-id db))))) (clean-input (:current-chat-id db)))))
(rf/defn chat-send-sticker (rf/defn chat-send-sticker

File diff suppressed because it is too large Load Diff

View File

@ -1,323 +0,0 @@
(ns status-im.chat.models.mentions-test
(:require [cljs.test :as test]
[clojure.string :as string]
[status-im.chat.models.mentions :as mentions]))
(def ->info-input
[[:text "H."]
[:mention
"@helpinghand.eth"]
[:text
" "]])
(def ->info-expected
{:at-sign-idx 2
:mention-end 19
:new-text " "
:previous-text ""
:start 18
:end 18
:at-idxs [{:mention? true
:from 2
:to 17
:checked? true}]})
(test/deftest test->info
(test/testing "->info base case"
(test/is (= ->info-expected (mentions/->info ->info-input)))))
;; No mention
(def mention-text-1 "parse-text")
(def mention-text-result-1 [[:text "parse-text"]])
;; Mention in the middle
(def mention-text-2
"hey @0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073 he")
(def mention-text-result-2
[[:text "hey "]
[:mention
"0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"]
[:text " he"]])
;; Mention at the beginning
(def mention-text-3
"@0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073 he")
(def mention-text-result-3
[[:mention
"0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"]
[:text " he"]])
;; Mention at the end
(def mention-text-4
"hey @0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")
(def mention-text-result-4
[[:text "hey "]
[:mention
"0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"]])
;; Invalid mention
(def mention-text-5
"invalid @0x04fBce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")
(def mention-text-result-5
[[:text
"invalid @0x04fBce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073"]])
(test/deftest test-to-input
(test/testing "only text"
(test/is (= mention-text-result-1 (mentions/->input-field mention-text-1))))
(test/testing "in the middle"
(test/is (= mention-text-result-2 (mentions/->input-field mention-text-2))))
(test/testing "at the beginning"
(test/is (= mention-text-result-3 (mentions/->input-field mention-text-3))))
(test/testing "at the end"
(test/is (= mention-text-result-4 (mentions/->input-field mention-text-4))))
(test/testing "invalid"
(test/is (= mention-text-result-5 (mentions/->input-field mention-text-5)))))
(test/deftest test-replace-mentions
(let [users {"User Number One"
{:primary-name "User Number One"
:public-key "0xpk1"}
"User Number Two"
{:primary-name "user2"
:secondary-name "User Number Two"
:public-key "0xpk2"}
"User Number Three"
{:primary-name "user3"
:secondary-name "User Number Three"
:public-key "0xpk3"}}]
(test/testing "empty string"
(let [text ""
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "no text"
(let [text nil
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "incomlepte mention 1"
(let [text "@"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "incomplete mention 2"
(let [text "@r"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "no mentions"
(let [text "foo bar @buzz kek @foo"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "starts with mention"
(let [text "@User Number One"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk1") (pr-str text))))
(test/testing "starts with mention, comma after mention"
(let [text "@User Number One,"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk1,") (pr-str text))))
(test/testing "starts with mention but no space after"
(let [text "@User Number Onefoo"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "starts with mention, some text after mention"
(let [text "@User Number One foo"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk1 foo") (pr-str text))))
(test/testing "starts with some text, then mention"
(let [text "text @User Number One"
result (mentions/replace-mentions text users)]
(test/is (= result "text @0xpk1") (pr-str text))))
(test/testing "starts with some text, then mention, then more text"
(let [text "text @User Number One foo"
result (mentions/replace-mentions text users)]
(test/is (= result "text @0xpk1 foo") (pr-str text))))
(test/testing "no space before mention"
(let [text "text@User Number One"
result (mentions/replace-mentions text users)]
(test/is (= result "text@0xpk1") (pr-str text))))
(test/testing "two different mentions"
(let [text "@User Number One @User Number two"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk1 @0xpk2") (pr-str text))))
(test/testing "two different mentions, separated with comma"
(let [text "@User Number One,@User Number two"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk1,@0xpk2") (pr-str text))))
(test/testing "two different mentions inside text"
(let [text "foo@User Number One bar @User Number two baz"
result (mentions/replace-mentions text users)]
(test/is (= result "foo@0xpk1 bar @0xpk2 baz") (pr-str text))))
(test/testing "ens mention"
(let [text "@user2"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk2") (pr-str text))))
(test/testing "multiple mentions"
(let [text (string/join
" "
(repeat 1000 "@User Number One @User Number two"))
result (mentions/replace-mentions text users)
exprected-result (string/join
" "
(repeat 1000 "@0xpk1 @0xpk2"))]
(test/is (= exprected-result result))))
(test/testing "markdown"
(test/testing "single * case 1"
(let [text "*@user2*"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "single * case 2"
(let [text "*@user2 *"
result (mentions/replace-mentions text users)]
(test/is (= result "*@0xpk2 *") (pr-str text))))
(test/testing "single * case 3"
(let [text "a*@user2*"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "single * case 4"
(let [text "*@user2 foo*foo"
result (mentions/replace-mentions text users)]
(test/is (= result "*@0xpk2 foo*foo") (pr-str text))))
(test/testing "single * case 5"
(let [text "a *@user2*"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "single * case 6"
(let [text "*@user2 foo*"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "single * case 7"
(let [text "@user2 *@user2 foo* @user2"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk2 *@user2 foo* @0xpk2") (pr-str text))))
(test/testing "single * case 8"
(let [text "*@user2 foo**@user2 foo*"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "single * case 9"
(let [text "*@user2 foo***@user2 foo* @user2"
result (mentions/replace-mentions text users)]
(test/is (= result "*@user2 foo***@user2 foo* @0xpk2") (pr-str text))))
(test/testing "double * case 1"
(let [text "**@user2**"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "double * case 2"
(let [text "**@user2 **"
result (mentions/replace-mentions text users)]
(test/is (= result "**@0xpk2 **") (pr-str text))))
(test/testing "double * case 3"
(let [text "a**@user2**"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "double * case 4"
(let [text "**@user2 foo**foo"
result (mentions/replace-mentions text users)]
(test/is (= result "**@user2 foo**foo") (pr-str text))))
(test/testing "double * case 5"
(let [text "a **@user2**"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "double * case 6"
(let [text "**@user2 foo**"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "double * case 7"
(let [text "@user2 **@user2 foo** @user2"
result (mentions/replace-mentions text users)]
(test/is (= result "@0xpk2 **@user2 foo** @0xpk2") (pr-str text))))
(test/testing "double * case 8"
(let [text "**@user2 foo****@user2 foo**"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "double * case 9"
(let [text "**@user2 foo*****@user2 foo** @user2"
result (mentions/replace-mentions text users)]
(test/is (= result "**@user2 foo*****@user2 foo** @0xpk2") (pr-str text))))
(test/testing "tripple * case 1"
(let [text "***@user2 foo***@user2 foo*"
result (mentions/replace-mentions text users)]
(test/is (= result "***@user2 foo***@0xpk2 foo*") (pr-str text))))
(test/testing "tripple ~ case 1"
(let [text "~~~@user2 foo~~~@user2 foo~"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "quote case 1"
(let [text ">@user2"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "quote case 2"
(let [text "\n>@user2"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "quote case 3"
(let [text "\n> @user2 \n \n @user2"
result (mentions/replace-mentions text users)]
(test/is (= result "\n> @user2 \n \n @0xpk2") (pr-str text))))
(test/testing "quote case 4"
(let [text ">@user2\n\n>@user2"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "quote case 5"
(let [text "***hey\n\n>@user2\n\n@user2 foo***"
result (mentions/replace-mentions text users)]
(test/is (= result "***hey\n\n>@user2\n\n@0xpk2 foo***")
(pr-str text))))
(test/testing "code case 1"
(let [text "` @user2 `"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "code case 2"
(let [text "` @user2 `"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "code case 3"
(let [text "``` @user2 ```"
result (mentions/replace-mentions text users)]
(test/is (= result text) (pr-str text))))
(test/testing "code case 4"
(let [text "` ` @user2 ``"
result (mentions/replace-mentions text users)]
(test/is (= result "` ` @0xpk2 ``") (pr-str text)))))))

View File

@ -10,9 +10,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.constants :as chat.constants] [status-im2.constants :as chat.constants]
[status-im.chat.models.mentions :as mentions]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.icons.icons :as icons] [status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.screens.chat.components.reply :as reply] [status-im.ui.screens.chat.components.reply :as reply]
@ -95,7 +93,7 @@
:color (styles/send-icon-color)}])]]) :color (styles/send-icon-color)}])]])
(defn on-selection-change (defn on-selection-change
[timeout-id last-text-change mentionable-users args] [timeout-id last-text-change args]
(let [selection (.-selection ^js (.-nativeEvent ^js args)) (let [selection (.-selection ^js (.-nativeEvent ^js args))
start (.-start selection) start (.-start selection)
end (.-end selection)] end (.-end selection)]
@ -106,10 +104,9 @@
(reset! (reset!
timeout-id timeout-id
(utils.utils/set-timeout (utils.utils/set-timeout
#(re-frame/dispatch [::mentions/on-selection-change #(re-frame/dispatch [:mention/on-selection-change
{:start start {:start start
:end end} :end end}])
mentionable-users])
50))) 50)))
;; NOTE(rasom): on Android we dispatch event only in case if there ;; NOTE(rasom): on Android we dispatch event only in case if there
;; was no text changes during last 50ms. `on-selection-change` is ;; was no text changes during last 50ms. `on-selection-change` is
@ -118,10 +115,9 @@
(when (and platform/android? (when (and platform/android?
(or (not @last-text-change) (or (not @last-text-change)
(< 50 (- (js/Date.now) @last-text-change)))) (< 50 (- (js/Date.now) @last-text-change))))
(re-frame/dispatch [::mentions/on-selection-change (re-frame/dispatch [:mention/on-selection-change
{:start start {:start start
:end end} :end end}]))))
mentionable-users]))))
(defonce input-texts (atom {})) (defonce input-texts (atom {}))
(defonce mentions-enabled (reagent/atom {})) (defonce mentions-enabled (reagent/atom {}))
@ -183,7 +179,7 @@
(re-frame/dispatch [:chat.ui/set-chat-input-text val])) (re-frame/dispatch [:chat.ui/set-chat-input-text val]))
(defn on-change (defn on-change
[last-text-change timeout-id mentionable-users refs chat-id sending-image args] [last-text-change timeout-id refs chat-id sending-image args]
(let [text (.-text ^js (.-nativeEvent ^js args)) (let [text (.-text ^js (.-nativeEvent ^js args))
prev-text (get @input-texts chat-id)] prev-text (get @input-texts chat-id)]
(when (and (seq prev-text) (empty? text) (not sending-image)) (when (and (seq prev-text) (empty? text) (not sending-image))
@ -206,46 +202,24 @@
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`, ;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
;; that's why mention suggestions are calculated on `on-change` ;; that's why mention suggestions are calculated on `on-change`
(when platform/ios? (when platform/ios?
(re-frame/dispatch [::mentions/calculate-suggestions mentionable-users])))) (re-frame/dispatch [:mention/calculate-suggestions]))))
(rf/defn set-input-text (rf/defn set-input-text
"Set input text for current-chat. Takes db and input text and cofx "Set input text for current-chat. Takes db and input text and cofx
as arguments and returns new fx. Always clear all validation messages." as arguments and returns new fx. Always clear all validation messages."
{:events [:chat.ui.input/set-chat-input-text]} {:events [:chat.ui.input/set-chat-input-text]}
[{:keys [db]} text chat-id] [{:keys [db]} text chat-id]
(let [text-with-mentions (mentions/->input-field text) (let [params [chat-id text]
all-contacts (:contacts/contacts db) method "wakuext_chatMentionToInputField"]
chat (get-in db [:chats chat-id]) {:json-rpc/call [{:method method
current-multiaccount (:multiaccount db) :params params
community-members (when (= (:chat-type chat) chat.constants/community-chat-type) :on-success #(rf/dispatch [:mention/on-to-input-field-success %])
(get-in db [:communities (:community-id chat) :members])) :on-error #(rf/dispatch [:mention/on-error
mentionable-users (mentions/get-mentionable-users {:method method
chat :params params} %])}]}))
all-contacts
current-multiaccount
community-members)
hydrated-mentions (map
(fn [[t mention :as e]]
(if (= t :mention)
(let [mention (multiaccounts/displayed-name
(get mentionable-users mention))]
[:mention
(if (string/starts-with? mention "@")
mention
(str "@" mention))])
e))
text-with-mentions)
info (mentions/->info hydrated-mentions)
new-text (string/join (map second hydrated-mentions))]
{:set-text-input-value [chat-id new-text]
:db
(-> db
(assoc-in [:chats/cursor chat-id] (:mention-end info))
(assoc-in [:chat/inputs-with-mentions chat-id] hydrated-mentions)
(assoc-in [:chats/mentions chat-id :mentions] info))}))
(defn on-text-input (defn on-text-input
[mentionable-users chat-id args] [chat-id args]
(let [native-event (.-nativeEvent ^js args) (let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event) text (.-text ^js native-event)
previous-text (.-previousText ^js native-event) previous-text (.-previousText ^js native-event)
@ -256,7 +230,7 @@
(swap! mentions-enabled assoc chat-id true)) (swap! mentions-enabled assoc chat-id true))
(re-frame/dispatch (re-frame/dispatch
[::mentions/on-text-input [:mention/on-text-input
{:new-text text {:new-text text
:previous-text previous-text :previous-text previous-text
:start start :start start
@ -265,12 +239,11 @@
;; `on-change`, that's why mention suggestions are calculated ;; `on-change`, that's why mention suggestions are calculated
;; on `on-change` ;; on `on-change`
(when platform/android? (when platform/android?
(re-frame/dispatch [::mentions/calculate-suggestions mentionable-users])))) (re-frame/dispatch [:mention/calculate-suggestions]))))
(defn text-input (defn text-input
[{:keys [set-active-panel refs chat-id sending-image]}] [{:keys [set-active-panel refs chat-id sending-image]}]
(let [cooldown-enabled? @(re-frame/subscribe [:chats/current-chat-cooldown-enabled?]) (let [cooldown-enabled? @(re-frame/subscribe [:chats/current-chat-cooldown-enabled?])
mentionable-users @(re-frame/subscribe [:chats/mentionable-users])
timeout-id (atom nil) timeout-id (atom nil)
last-text-change (atom nil) last-text-change (atom nil)
mentions-enabled (get @mentions-enabled chat-id) mentions-enabled (get @mentions-enabled chat-id)
@ -296,11 +269,10 @@
:auto-capitalize :sentences :auto-capitalize :sentences
:on-selection-change (partial on-selection-change :on-selection-change (partial on-selection-change
timeout-id timeout-id
last-text-change last-text-change)
mentionable-users)
:on-change :on-change
(partial on-change last-text-change timeout-id mentionable-users refs chat-id sending-image) (partial on-change last-text-change timeout-id refs chat-id sending-image)
:on-text-input (partial on-text-input mentionable-users chat-id)} :on-text-input (partial on-text-input chat-id)}
(if mentions-enabled (if mentions-enabled
(for [[idx [type text]] (map-indexed (for [[idx [type text]] (map-indexed
(fn [idx item] (fn [idx item]

View File

@ -5,7 +5,6 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im2.constants :as chat.constants] [status-im2.constants :as chat.constants]
[status-im.chat.models.mentions :as mentions]
[utils.i18n :as i18n] [utils.i18n :as i18n]
[utils.re-frame :as rf] [utils.re-frame :as rf]
[utils.transforms :as transforms] [utils.transforms :as transforms]
@ -93,7 +92,7 @@
(rf/dispatch [:chat.ui/set-chat-input-text val])) (rf/dispatch [:chat.ui/set-chat-input-text val]))
(defn on-selection-change (defn on-selection-change
[timeout-id last-text-change mentionable-users args] [timeout-id last-text-change args]
(let [selection (.-selection ^js (.-nativeEvent ^js args)) (let [selection (.-selection ^js (.-nativeEvent ^js args))
start (.-start selection) start (.-start selection)
end (.-end selection)] end (.-end selection)]
@ -104,10 +103,9 @@
(reset! (reset!
timeout-id timeout-id
(background-timer/set-timeout (background-timer/set-timeout
#(rf/dispatch [::mentions/on-selection-change #(rf/dispatch [:mention/on-selection-change
{:start start {:start start
:end end} :end end}])
mentionable-users])
50))) 50)))
;; NOTE(rasom): on Android we dispatch event only in case if there ;; NOTE(rasom): on Android we dispatch event only in case if there
;; was no text changes during last 50ms. `on-selection-change` is ;; was no text changes during last 50ms. `on-selection-change` is
@ -116,13 +114,12 @@
(when (and platform/android? (when (and platform/android?
(or (not @last-text-change) (or (not @last-text-change)
(< 50 (- (js/Date.now) @last-text-change)))) (< 50 (- (js/Date.now) @last-text-change))))
(rf/dispatch [::mentions/on-selection-change (rf/dispatch [:mention/on-selection-change
{:start start {:start start
:end end} :end end}]))))
mentionable-users]))))
(defn on-change (defn on-change
[last-text-change timeout-id mentionable-users refs chat-id sending-image args] [last-text-change timeout-id refs chat-id sending-image args]
(let [text (.-text ^js (.-nativeEvent ^js args)) (let [text (.-text ^js (.-nativeEvent ^js args))
prev-text (get @input-texts chat-id)] prev-text (get @input-texts chat-id)]
(when (and (seq prev-text) (empty? text) (not sending-image)) (when (and (seq prev-text) (empty? text) (not sending-image))
@ -147,10 +144,10 @@
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`, ;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
;; that's why mention suggestions are calculated on `on-change` ;; that's why mention suggestions are calculated on `on-change`
(when platform/ios? (when platform/ios?
(rf/dispatch [::mentions/calculate-suggestions mentionable-users])))) (rf/dispatch [:mention/calculate-suggestions]))))
(defn on-text-input (defn on-text-input
[mentionable-users chat-id args] [chat-id args]
(let [native-event (.-nativeEvent ^js args) (let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event) text (.-text ^js native-event)
previous-text (.-previousText ^js native-event) previous-text (.-previousText ^js native-event)
@ -161,7 +158,7 @@
(swap! mentions-enabled? assoc chat-id true)) (swap! mentions-enabled? assoc chat-id true))
(rf/dispatch (rf/dispatch
[::mentions/on-text-input [:mention/on-text-input
{:new-text text {:new-text text
:previous-text previous-text :previous-text previous-text
:start start :start start
@ -170,7 +167,7 @@
;; `on-change`, that's why mention suggestions are calculated ;; `on-change`, that's why mention suggestions are calculated
;; on `on-change` ;; on `on-change`
(when platform/android? (when platform/android?
(rf/dispatch [::mentions/calculate-suggestions mentionable-users])))) (rf/dispatch [:mention/calculate-suggestions]))))
(defn text-input-style (defn text-input-style
[chat-id] [chat-id]
@ -193,7 +190,6 @@
(defn text-input (defn text-input
[{:keys [refs chat-id sending-image on-content-size-change]}] [{:keys [refs chat-id sending-image on-content-size-change]}]
(let [cooldown-enabled? (rf/sub [:chats/current-chat-cooldown-enabled?]) (let [cooldown-enabled? (rf/sub [:chats/current-chat-cooldown-enabled?])
mentionable-users (rf/sub [:chats/mentionable-users])
timeout-id (reagent/atom nil) timeout-id (reagent/atom nil)
last-text-change (reagent/atom nil) last-text-change (reagent/atom nil)
mentions-enabled? (get @mentions-enabled? chat-id) mentions-enabled? (get @mentions-enabled? chat-id)
@ -220,18 +216,17 @@
:on-content-size-change on-content-size-change :on-content-size-change on-content-size-change
:on-selection-change (partial on-selection-change :on-selection-change (partial on-selection-change
timeout-id timeout-id
last-text-change last-text-change)
mentionable-users)
:on-change :on-change
(partial on-change last-text-change timeout-id mentionable-users refs chat-id sending-image) (partial on-change last-text-change timeout-id refs chat-id sending-image)
:on-text-input (partial on-text-input mentionable-users chat-id)} :on-text-input (partial on-text-input chat-id)}
input-with-mentions (rf/sub [:chat/input-with-mentions]) input-with-mentions (rf/sub [:chat/input-with-mentions])
children (fn [] children (fn []
(if mentions-enabled? (if mentions-enabled?
(map-indexed (map-indexed
(fn [index [_ text]] (fn [index [mention-type text]]
^{:key (str index "_" type "_" text)} ^{:key (str index "_" mention-type "_" text)}
[rn/text (when (= type :mention) {:style {:color colors/primary-50}}) [rn/text (when (= mention-type :mention) {:style {:color colors/primary-50}})
text]) text])
input-with-mentions) input-with-mentions)
(get @input-texts chat-id)))] (get @input-texts chat-id)))]

View File

@ -3,7 +3,6 @@
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.add-new.db :as db] [status-im.add-new.db :as db]
[status-im.chat.models.mentions :as mentions]
[status-im.communities.core :as communities] [status-im.communities.core :as communities]
[status-im.group-chats.core :as group-chat] [status-im.group-chats.core :as group-chat]
[status-im.group-chats.db :as group-chats.db] [status-im.group-chats.db :as group-chats.db]
@ -438,26 +437,6 @@
(fn [[current-chat pk]] (fn [[current-chat pk]]
(group-chat/member-removed? current-chat pk))) (group-chat/member-removed? current-chat pk)))
(re-frame/reg-sub
:chats/mentionable-users
:<- [:chats/current-chat]
:<- [:contacts/blocked-set]
:<- [:contacts/contacts]
:<- [:multiaccount]
:<- [:communities/current-community-members]
(fn
[[{:keys [users] :as chat}
blocked
all-contacts
{:keys [public-key] :as current-multiaccount}
community-members]]
(let [mentionable-users (mentions/get-mentionable-users chat
all-contacts
current-multiaccount
community-members)
members-left (into #{} (filter #(group-chat/member-removed? chat %) (keys users)))]
(apply dissoc mentionable-users (conj (concat blocked members-left) public-key)))))
(re-frame/reg-sub (re-frame/reg-sub
:chat/mention-suggestions :chat/mention-suggestions
:<- [:chats/current-chat-id] :<- [:chats/current-chat-id]

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>", "_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.143.0", "version": "v0.143.1",
"commit-sha1": "39be3c081ce80178f0daa1f38c00aebb87c1a574", "commit-sha1": "ee01fe4e0c14f03fb32dda15365da3c73470cde0",
"src-sha256": "0hdz740p0n6dk384cdqgpc7pv3a8fz558q20k4iji98bk9m5qjs1" "src-sha256": "0l5rld1p5nsvfahn8iymyn87a8h6wrllcx2jngcy7pxffbgk3619"
} }