Move mentions logic to status-go (#15428)
This commit is contained in:
parent
c3ed15f30d
commit
9da9427488
|
@ -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"
|
||||||
(rf/merge cofx
|
params [current-chat-id input-text]]
|
||||||
(if editing-message
|
{:json-rpc/call [{:method method
|
||||||
(send-edited-message input-text-with-mentions editing-message)
|
:params params
|
||||||
(send-messages input-text-with-mentions current-chat-id))
|
:on-error #(rf/dispatch [:mention/on-error {:method method :params params} %])
|
||||||
(mentions/clear-mentions)
|
:on-success #(rf/dispatch [:mention/on-check-mentions-success
|
||||||
(mentions/clear-cursor))))
|
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
|
||||||
|
(if editing-message
|
||||||
|
(send-edited-message new-text editing-message)
|
||||||
|
(send-messages new-text current-chat-id))))
|
||||||
|
|
||||||
(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
|
@ -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)))))))
|
|
|
@ -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]
|
||||||
|
|
|
@ -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)))]
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue