[Fixes: #12607] Edit messages
Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
9ba0960d71
commit
45b9fd4b91
|
@ -6,7 +6,7 @@ pipeline {
|
||||||
options {
|
options {
|
||||||
timestamps()
|
timestamps()
|
||||||
/* Prevent Jenkins jobs from running forever */
|
/* Prevent Jenkins jobs from running forever */
|
||||||
timeout(time: 20, unit: 'MINUTES')
|
timeout(time: 30, unit: 'MINUTES')
|
||||||
/* Limit builds retained */
|
/* Limit builds retained */
|
||||||
buildDiscarder(logRotator(
|
buildDiscarder(logRotator(
|
||||||
numToKeepStr: '10',
|
numToKeepStr: '10',
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
(ns status-im.chat.models.input
|
(ns status-im.chat.models.input
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[goog.object :as object]
|
[goog.object :as object]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
[status-im.chat.constants :as chat.constants]
|
[status-im.chat.constants :as chat.constants]
|
||||||
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
[status-im.chat.models :as chat]
|
[status-im.chat.models :as chat]
|
||||||
[status-im.chat.models.message :as chat.message]
|
[status-im.chat.models.message :as chat.message]
|
||||||
[status-im.chat.models.message-content :as message-content]
|
[status-im.chat.models.message-content :as message-content]
|
||||||
|
@ -112,9 +115,25 @@
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
|
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
|
||||||
message)
|
message)
|
||||||
|
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
|
||||||
(update-in [:chat/inputs current-chat-id :metadata]
|
(update-in [:chat/inputs current-chat-id :metadata]
|
||||||
dissoc :sending-image))})))
|
dissoc :sending-image))})))
|
||||||
|
|
||||||
|
(fx/defn edit-message
|
||||||
|
"Sets reference to previous chat message and focuses on input"
|
||||||
|
{:events [:chat.ui/edit-message]}
|
||||||
|
[{:keys [db] :as cofx} message]
|
||||||
|
(let [current-chat-id (:current-chat-id db)
|
||||||
|
|
||||||
|
text (get-in message [:content :text])]
|
||||||
|
{:dispatch [:chat.ui.input/set-chat-input-text text current-chat-id]
|
||||||
|
:db (-> db
|
||||||
|
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
|
||||||
|
message)
|
||||||
|
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
|
||||||
|
(update-in [:chat/inputs current-chat-id :metadata]
|
||||||
|
dissoc :sending-image))}))
|
||||||
|
|
||||||
(fx/defn cancel-message-reply
|
(fx/defn cancel-message-reply
|
||||||
"Cancels stage message reply"
|
"Cancels stage message reply"
|
||||||
{:events [:chat.ui/cancel-message-reply]}
|
{:events [:chat.ui/cancel-message-reply]}
|
||||||
|
@ -152,16 +171,28 @@
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc-in [:chat/inputs current-chat-id :metadata :sending-image] nil)
|
(assoc-in [:chat/inputs current-chat-id :metadata :sending-image] nil)
|
||||||
|
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
|
||||||
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil))}
|
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil))}
|
||||||
(set-chat-input-text nil current-chat-id)))
|
(set-chat-input-text nil current-chat-id)))
|
||||||
|
|
||||||
|
(fx/defn cancel-message-edit
|
||||||
|
"Cancels stage message edit"
|
||||||
|
{:events [:chat.ui/cancel-message-edit]}
|
||||||
|
[{:keys [db] :as cofx}]
|
||||||
|
(let [current-chat-id (:current-chat-id db)]
|
||||||
|
(fx/merge cofx
|
||||||
|
{:set-input-text [current-chat-id ""]}
|
||||||
|
(clean-input current-chat-id)
|
||||||
|
(mentions/clear-mentions)
|
||||||
|
(mentions/clear-cursor))))
|
||||||
|
|
||||||
(fx/defn send-messages [{:keys [db] :as cofx} input-text current-chat-id]
|
(fx/defn send-messages [{:keys [db] :as cofx} input-text current-chat-id]
|
||||||
(let [image-messages (build-image-messages cofx current-chat-id)
|
(let [image-messages (build-image-messages cofx current-chat-id)
|
||||||
text-message (build-text-message cofx input-text current-chat-id)
|
text-message (build-text-message cofx input-text current-chat-id)
|
||||||
messages (keep identity (conj image-messages text-message))]
|
messages (keep identity (conj image-messages text-message))]
|
||||||
(when (seq messages)
|
(when (seq messages)
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
(clean-input cofx (:current-chat-id db))
|
(clean-input (:current-chat-id db))
|
||||||
(process-cooldown)
|
(process-cooldown)
|
||||||
(chat.message/send-messages messages)))))
|
(chat.message/send-messages messages)))))
|
||||||
|
|
||||||
|
@ -197,14 +228,28 @@
|
||||||
:pack pack}
|
:pack pack}
|
||||||
:text (i18n/label :t/update-to-see-sticker)})))
|
:text (i18n/label :t/update-to-see-sticker)})))
|
||||||
|
|
||||||
|
(fx/defn send-edited-message [{:keys [db] :as cofx} text {:keys [message-id]}]
|
||||||
|
(fx/merge
|
||||||
|
cofx
|
||||||
|
{::json-rpc/call [{:method "wakuext_editMessage"
|
||||||
|
:params [{:id message-id :text text}]
|
||||||
|
:js-response true
|
||||||
|
:on-error #(log/error "failed to edit message " %)
|
||||||
|
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}
|
||||||
|
(clean-input (:current-chat-id db))
|
||||||
|
(process-cooldown)))
|
||||||
|
|
||||||
(fx/defn send-current-message
|
(fx/defn send-current-message
|
||||||
"Sends message from current chat input"
|
"Sends message from current chat input"
|
||||||
{:events [:chat.ui/send-current-message]}
|
{:events [:chat.ui/send-current-message]}
|
||||||
[{{:keys [current-chat-id] :as db} :db :as cofx}]
|
[{{:keys [current-chat-id] :as db} :db :as cofx}]
|
||||||
(let [{:keys [input-text]} (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)
|
||||||
input-text-with-mentions (mentions/check-mentions cofx input-text)]
|
input-text-with-mentions (mentions/check-mentions cofx input-text)]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
(send-messages input-text-with-mentions current-chat-id)
|
(if editing-message
|
||||||
|
(send-edited-message input-text-with-mentions editing-message)
|
||||||
|
(send-messages input-text-with-mentions current-chat-id))
|
||||||
(mentions/clear-mentions)
|
(mentions/clear-mentions)
|
||||||
(mentions/clear-cursor))))
|
(mentions/clear-cursor))))
|
||||||
|
|
||||||
|
|
|
@ -516,8 +516,8 @@
|
||||||
{:keys [new-text at-idxs start end] :as state}
|
{:keys [new-text at-idxs start end] :as state}
|
||||||
(get-in db [:chats/mentions chat-id :mentions])
|
(get-in db [:chats/mentions chat-id :mentions])
|
||||||
new-text (or new-text text)]
|
new-text (or new-text text)]
|
||||||
(log/debug "[mentions] calculate suggestions"
|
(log/info "[mentions] calculate suggestions"
|
||||||
"state" state)
|
"state" state)
|
||||||
(if-not (seq at-idxs)
|
(if-not (seq at-idxs)
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(assoc-in [:chats/mention-suggestions chat-id] nil)
|
(assoc-in [:chats/mention-suggestions chat-id] nil)
|
||||||
|
@ -646,3 +646,144 @@
|
||||||
(update user :searchable-phrases (fnil concat []) new-words))))
|
(update user :searchable-phrases (fnil concat []) new-words))))
|
||||||
user
|
user
|
||||||
[alias name nickname]))
|
[alias name nickname]))
|
||||||
|
|
||||||
|
(defn is-valid-terminating-character? [c]
|
||||||
|
(case c
|
||||||
|
"\t" true ; tab
|
||||||
|
"\n" true ; newline
|
||||||
|
"\f" true ; new page
|
||||||
|
"\r" true ; carriage return
|
||||||
|
" " true ; whitespace
|
||||||
|
"," true
|
||||||
|
"." true
|
||||||
|
":" true
|
||||||
|
";" true
|
||||||
|
false))
|
||||||
|
|
||||||
|
(def hex-reg #"[0-9a-f]")
|
||||||
|
|
||||||
|
(defn is-public-key-character? [c]
|
||||||
|
(.test hex-reg c))
|
||||||
|
|
||||||
|
(def mention-length 133)
|
||||||
|
|
||||||
|
(defn ->input-field
|
||||||
|
"->input-field takes a string with mentions in the @0xpk format
|
||||||
|
and retuns a list in the format
|
||||||
|
[{:type :text :text text} {:type :mention :text 0xpk}...]"
|
||||||
|
[text]
|
||||||
|
(let [{:keys [text
|
||||||
|
current-mention-length
|
||||||
|
current-text
|
||||||
|
current-mention]}
|
||||||
|
(reduce (fn [{:keys [text
|
||||||
|
current-text
|
||||||
|
current-mention
|
||||||
|
current-mention-length]} character]
|
||||||
|
(let [is-pk-character (is-public-key-character? character)
|
||||||
|
is-termination-character (is-valid-terminating-character? character)]
|
||||||
|
(cond
|
||||||
|
;; It's a valid mention.
|
||||||
|
;; Add any text that is before if present
|
||||||
|
;; and add the mention.
|
||||||
|
;; Set the text to the new termination character
|
||||||
|
(and (= current-mention-length mention-length)
|
||||||
|
is-termination-character)
|
||||||
|
{:current-mention-length 0
|
||||||
|
:current-mention ""
|
||||||
|
:current-text character
|
||||||
|
:text (cond-> text
|
||||||
|
(seq current-text)
|
||||||
|
(conj [:text current-text])
|
||||||
|
:always
|
||||||
|
(conj [:mention current-mention]))}
|
||||||
|
|
||||||
|
|
||||||
|
;; It's either a pk character, or the `x` in the pk
|
||||||
|
;; in this case add the text to the mention and continue
|
||||||
|
|
||||||
|
|
||||||
|
(or
|
||||||
|
(and is-pk-character
|
||||||
|
(pos? current-mention-length))
|
||||||
|
(and (= 2 current-mention-length)
|
||||||
|
(= "x" character)))
|
||||||
|
{:current-mention-length (inc current-mention-length)
|
||||||
|
:current-text current-text
|
||||||
|
:current-mention (str current-mention character)
|
||||||
|
:text text}
|
||||||
|
|
||||||
|
|
||||||
|
;; The beginning of a mention, discard the @ sign
|
||||||
|
;; and start following a mention
|
||||||
|
|
||||||
|
|
||||||
|
(= "@" character)
|
||||||
|
{:current-mention-length 1
|
||||||
|
:current-mention ""
|
||||||
|
:current-text current-text
|
||||||
|
:text text}
|
||||||
|
|
||||||
|
;; Not a mention character, but we were following a mention
|
||||||
|
;; discard everything up to know an count as text
|
||||||
|
(and (not is-pk-character)
|
||||||
|
(pos? current-mention-length))
|
||||||
|
{:current-mention-length 0
|
||||||
|
:current-text (str current-text "@" current-mention character)
|
||||||
|
:current-mention ""
|
||||||
|
:text text}
|
||||||
|
|
||||||
|
;; Just a normal text character
|
||||||
|
:else
|
||||||
|
{:current-mention-length 0
|
||||||
|
:current-mention ""
|
||||||
|
:current-text (str current-text character)
|
||||||
|
:text text})))
|
||||||
|
{:current-mention-length 0
|
||||||
|
:current-text ""
|
||||||
|
:current-mention ""
|
||||||
|
:text []}
|
||||||
|
text)]
|
||||||
|
;; Process any remaining mention/text
|
||||||
|
(cond-> text
|
||||||
|
(seq current-text)
|
||||||
|
(conj [:text current-text])
|
||||||
|
(= current-mention-length mention-length)
|
||||||
|
(conj [:mention current-mention]))))
|
||||||
|
|
||||||
|
(defn ->info
|
||||||
|
"->info convert a input-field representation of mentions to
|
||||||
|
a db based representation used to indicate where mentions are placed in the
|
||||||
|
input string"
|
||||||
|
[m]
|
||||||
|
(reduce (fn [{:keys [start end at-idxs at-sign-idx mention-end]} [t text]]
|
||||||
|
(if (= :mention t)
|
||||||
|
(let [new-mention {:checked? true
|
||||||
|
:mention? true
|
||||||
|
:from mention-end
|
||||||
|
:to (+ start (count text))}
|
||||||
|
has-previous? (seq at-idxs)]
|
||||||
|
{:new-text (last text)
|
||||||
|
:previous-text ""
|
||||||
|
:start (+ start (count text))
|
||||||
|
:end (+ end (count text))
|
||||||
|
:at-idxs (cond-> at-idxs
|
||||||
|
has-previous?
|
||||||
|
(-> pop
|
||||||
|
(conj (assoc (peek at-idxs) :next-at-idx mention-end)))
|
||||||
|
:always
|
||||||
|
(conj new-mention))
|
||||||
|
:at-sign-idx mention-end
|
||||||
|
:mention-end (+ mention-end (count text))})
|
||||||
|
{:new-text (last text)
|
||||||
|
:previous-text ""
|
||||||
|
:start (+ start (count text))
|
||||||
|
:end (+ end (count text))
|
||||||
|
:at-idxs at-idxs
|
||||||
|
:at-sign-idx at-sign-idx
|
||||||
|
:mention-end (+ mention-end (count text))}))
|
||||||
|
{:start -1
|
||||||
|
:end -1
|
||||||
|
:at-idxs []
|
||||||
|
:mention-end 0}
|
||||||
|
m))
|
||||||
|
|
|
@ -3,6 +3,60 @@
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[cljs.test :as test :include-macros true]))
|
[cljs.test :as test :include-macros true]))
|
||||||
|
|
||||||
|
(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
|
(test/deftest test-replace-mentions
|
||||||
(let [users {"User Number One"
|
(let [users {"User Number One"
|
||||||
{:name "User Number One"
|
{:name "User Number One"
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
(-> message
|
(-> message
|
||||||
(clojure.set/rename-keys {:id :message-id
|
(clojure.set/rename-keys {:id :message-id
|
||||||
:whisperTimestamp :whisper-timestamp
|
:whisperTimestamp :whisper-timestamp
|
||||||
|
:editedAt :edited-at
|
||||||
:commandParameters :command-parameters
|
:commandParameters :command-parameters
|
||||||
:gapParameters :gap-parameters
|
:gapParameters :gap-parameters
|
||||||
:messageType :message-type
|
:messageType :message-type
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
"waku_markTrustedPeer" {}
|
"waku_markTrustedPeer" {}
|
||||||
"wakuext_post" {}
|
"wakuext_post" {}
|
||||||
"wakuext_requestAllHistoricMessages" {}
|
"wakuext_requestAllHistoricMessages" {}
|
||||||
|
"wakuext_editMessage" {}
|
||||||
"wakuext_fillGaps" {}
|
"wakuext_fillGaps" {}
|
||||||
"wakuext_syncChatFromSyncedFrom" {}
|
"wakuext_syncChatFromSyncedFrom" {}
|
||||||
"wakuext_createPublicChat" {}
|
"wakuext_createPublicChat" {}
|
||||||
|
|
|
@ -1074,6 +1074,12 @@
|
||||||
(fn [{:keys [metadata]}]
|
(fn [{:keys [metadata]}]
|
||||||
(:responding-to-message metadata)))
|
(:responding-to-message metadata)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:chats/edit-message
|
||||||
|
:<- [:chats/current-chat-inputs]
|
||||||
|
(fn [{:keys [metadata]}]
|
||||||
|
(:editing-message metadata)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/sending-image
|
:chats/sending-image
|
||||||
:<- [:chats/current-chat-inputs]
|
:<- [:chats/current-chat-inputs]
|
||||||
|
@ -1095,19 +1101,23 @@
|
||||||
:<- [:current-chat/one-to-one-chat?]
|
:<- [:current-chat/one-to-one-chat?]
|
||||||
:<- [:current-chat/metadata]
|
:<- [:current-chat/metadata]
|
||||||
:<- [:chats/reply-message]
|
:<- [:chats/reply-message]
|
||||||
(fn [[disconnected? {:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply]]
|
:<- [:chats/edit-message]
|
||||||
|
(fn [[disconnected? {:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply edit]]
|
||||||
(let [sending-image (seq sending-image)]
|
(let [sending-image (seq sending-image)]
|
||||||
{:send (and (not (or processing disconnected?)))
|
{:send (and (not (or processing disconnected?)))
|
||||||
:stickers (and mainnet?
|
:stickers (and mainnet?
|
||||||
(not sending-image)
|
(not sending-image)
|
||||||
(not reply))
|
(not reply))
|
||||||
:image (and (not reply)
|
:image (and (not reply)
|
||||||
|
(not edit)
|
||||||
(not public?))
|
(not public?))
|
||||||
:extensions (and one-to-one-chat?
|
:extensions (and one-to-one-chat?
|
||||||
(or config/commands-enabled? mainnet?)
|
(or config/commands-enabled? mainnet?)
|
||||||
|
(not edit)
|
||||||
(not reply))
|
(not reply))
|
||||||
:audio (and (not sending-image)
|
:audio (and (not sending-image)
|
||||||
(not reply)
|
(not reply)
|
||||||
|
(not edit)
|
||||||
(not public?))
|
(not public?))
|
||||||
:sending-image sending-image})))
|
:sending-image sending-image})))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
(ns status-im.ui.screens.chat.components.edit
|
||||||
|
(:require [quo.core :as quo]
|
||||||
|
[quo.react :as quo.react]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as quo.colors]
|
||||||
|
[status-im.i18n.i18n :as i18n]
|
||||||
|
[quo.components.animated.pressable :as pressable]
|
||||||
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
|
[status-im.ui.screens.chat.components.style :as styles]
|
||||||
|
[re-frame.core :as re-frame]))
|
||||||
|
|
||||||
|
(defn input-focus [text-input-ref]
|
||||||
|
(some-> ^js (quo.react/current-ref text-input-ref) .focus))
|
||||||
|
|
||||||
|
(defn edit-message []
|
||||||
|
[rn/view {:style {:flex-direction :row}}
|
||||||
|
[rn/view {}
|
||||||
|
[icons/icon :tiny-icons/tiny-edit {:container-style {:margin-top 5}}]]
|
||||||
|
[rn/view {:style (styles/reply-content)}
|
||||||
|
[quo/text {:weight :medium
|
||||||
|
:number-of-lines 1}
|
||||||
|
(i18n/label :t/editing-message)]]
|
||||||
|
[rn/view
|
||||||
|
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-message-edit])
|
||||||
|
:accessibility-label :cancel-message-reply}
|
||||||
|
[icons/icon :main-icons/close-circle {:container-style (styles/close-button)
|
||||||
|
:color (:icon-02 @quo.colors/theme)}]]]])
|
||||||
|
|
||||||
|
(defn focus-input-on-edit [edit had-edit text-input-ref]
|
||||||
|
;;when we show edit we focus input
|
||||||
|
(when-not (= edit @had-edit)
|
||||||
|
(reset! had-edit edit)
|
||||||
|
(when edit
|
||||||
|
(js/setTimeout #(input-focus text-input-ref) 250))))
|
||||||
|
|
||||||
|
(defn edit-message-wrapper [edit]
|
||||||
|
[rn/view {:style {:padding-horizontal 15
|
||||||
|
:border-top-width 1
|
||||||
|
:border-top-color (:ui-01 @quo.colors/theme)
|
||||||
|
:padding-vertical 8}}
|
||||||
|
[edit-message edit]])
|
||||||
|
|
||||||
|
(defn edit-message-auto-focus-wrapper [text-input-ref]
|
||||||
|
(let [had-edit (atom nil)]
|
||||||
|
(fn []
|
||||||
|
(let [edit @(re-frame/subscribe [:chats/edit-message])]
|
||||||
|
(focus-input-on-edit edit had-edit text-input-ref)
|
||||||
|
(when edit
|
||||||
|
[edit-message-wrapper])))))
|
|
@ -6,7 +6,9 @@
|
||||||
[quo.components.text :as text]
|
[quo.components.text :as text]
|
||||||
[quo.design-system.colors :as colors]
|
[quo.design-system.colors :as colors]
|
||||||
[status-im.ui.screens.chat.components.style :as styles]
|
[status-im.ui.screens.chat.components.style :as styles]
|
||||||
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.ui.screens.chat.components.reply :as reply]
|
[status-im.ui.screens.chat.components.reply :as reply]
|
||||||
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.chat.constants :as chat.constants]
|
[status-im.chat.constants :as chat.constants]
|
||||||
[status-im.utils.utils :as utils.utils]
|
[status-im.utils.utils :as utils.utils]
|
||||||
[quo.components.animated.pressable :as pressable]
|
[quo.components.animated.pressable :as pressable]
|
||||||
|
@ -109,6 +111,13 @@
|
||||||
|
|
||||||
(defonce input-texts (atom {}))
|
(defonce input-texts (atom {}))
|
||||||
(defonce mentions-enabled (reagent/atom {}))
|
(defonce mentions-enabled (reagent/atom {}))
|
||||||
|
(defonce chat-input-key (reagent/atom 1))
|
||||||
|
|
||||||
|
(defn force-text-input-update!
|
||||||
|
"force-text-input-update! forces the
|
||||||
|
input to re-render, necessary when we are setting value"
|
||||||
|
[]
|
||||||
|
(swap! chat-input-key inc))
|
||||||
|
|
||||||
(defn show-send [{:keys [actions-ref send-ref sticker-ref]}]
|
(defn show-send [{:keys [actions-ref send-ref sticker-ref]}]
|
||||||
(quo.react/set-native-props actions-ref #js {:width 0 :left -88})
|
(quo.react/set-native-props actions-ref #js {:width 0 :left -88})
|
||||||
|
@ -165,6 +174,37 @@
|
||||||
(when platform/ios?
|
(when platform/ios?
|
||||||
(re-frame/dispatch [::mentions/calculate-suggestions mentionable-users]))))
|
(re-frame/dispatch [::mentions/calculate-suggestions mentionable-users]))))
|
||||||
|
|
||||||
|
(re-frame/reg-fx
|
||||||
|
:set-input-text
|
||||||
|
(fn [[chat-id text]]
|
||||||
|
;; We enable mentions
|
||||||
|
(swap! mentions-enabled assoc chat-id true)
|
||||||
|
(on-text-change text chat-id)
|
||||||
|
;; We update the key so that we force a refresh of the text input, as those
|
||||||
|
;; are not ratoms
|
||||||
|
(force-text-input-update!)))
|
||||||
|
|
||||||
|
(fx/defn set-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.input/set-chat-input-text]}
|
||||||
|
[{:keys [db] :as cofx} text chat-id]
|
||||||
|
(let [text-with-mentions (mentions/->input-field text)
|
||||||
|
contacts (:contacts db)
|
||||||
|
hydrated-mentions (map (fn [[t mention :as e]]
|
||||||
|
(if (= t :mention)
|
||||||
|
[:mention (str "@" (multiaccounts/displayed-name
|
||||||
|
(or (get contacts mention)
|
||||||
|
{:public-key mention})))]
|
||||||
|
e)) text-with-mentions)
|
||||||
|
info (mentions/->info hydrated-mentions)]
|
||||||
|
{:set-input-text [chat-id 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 [mentionable-users chat-id args]
|
(defn on-text-input [mentionable-users 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)
|
||||||
|
@ -193,6 +233,7 @@
|
||||||
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)]
|
||||||
|
|
||||||
[rn/text-input
|
[rn/text-input
|
||||||
{:style (styles/text-input)
|
{:style (styles/text-input)
|
||||||
:ref (:text-input-ref refs)
|
:ref (:text-input-ref refs)
|
||||||
|
@ -281,21 +322,6 @@
|
||||||
(defn on-chat-toolbar-layout [^js ev]
|
(defn on-chat-toolbar-layout [^js ev]
|
||||||
(reset! chat-toolbar-height (-> ev .-nativeEvent .-layout .-height)))
|
(reset! chat-toolbar-height (-> ev .-nativeEvent .-layout .-height)))
|
||||||
|
|
||||||
(defn focus-input-on-reply [reply had-reply text-input-ref]
|
|
||||||
;;when we show reply we focus input
|
|
||||||
(when-not (= reply @had-reply)
|
|
||||||
(reset! had-reply reply)
|
|
||||||
(when reply
|
|
||||||
(js/setTimeout #(input-focus text-input-ref) 250))))
|
|
||||||
|
|
||||||
(defn reply-message [text-input-ref]
|
|
||||||
(let [had-reply (atom nil)]
|
|
||||||
(fn []
|
|
||||||
(let [reply @(re-frame/subscribe [:chats/reply-message])]
|
|
||||||
(focus-input-on-reply reply had-reply text-input-ref)
|
|
||||||
(when reply
|
|
||||||
[reply/reply-message reply])))))
|
|
||||||
|
|
||||||
(defn send-image []
|
(defn send-image []
|
||||||
(let [sending-image @(re-frame/subscribe [:chats/sending-image])]
|
(let [sending-image @(re-frame/subscribe [:chats/sending-image])]
|
||||||
(when (seq sending-image)
|
(when (seq sending-image)
|
||||||
|
@ -331,10 +357,9 @@
|
||||||
show-send (or sending-image (seq (get @input-texts chat-id)))]
|
show-send (or sending-image (seq (get @input-texts chat-id)))]
|
||||||
[rn/view {:style (styles/toolbar)
|
[rn/view {:style (styles/toolbar)
|
||||||
:on-layout on-chat-toolbar-layout}
|
:on-layout on-chat-toolbar-layout}
|
||||||
;;EXTENSIONS and IMAGE buttons
|
;;EXTENSIONS and IMAGE buttons
|
||||||
[actions extensions image show-send actions-ref active-panel set-active-panel]
|
[actions extensions image show-send actions-ref active-panel set-active-panel]
|
||||||
[rn/view {:style (styles/input-container)}
|
[rn/view {:style (styles/input-container)}
|
||||||
[reply-message text-input-ref]
|
|
||||||
[send-image]
|
[send-image]
|
||||||
[rn/view {:style styles/input-row}
|
[rn/view {:style styles/input-row}
|
||||||
[text-input {:chat-id chat-id
|
[text-input {:chat-id chat-id
|
||||||
|
@ -348,17 +373,18 @@
|
||||||
(re-frame/dispatch [:chat.ui/send-current-message]))])]
|
(re-frame/dispatch [:chat.ui/send-current-message]))])]
|
||||||
|
|
||||||
;;STICKERS and AUDIO buttons
|
;;STICKERS and AUDIO buttons
|
||||||
[rn/view {:style (merge {:flex-direction :row} (when show-send {:width 0 :right -100}))
|
(when-not @(re-frame/subscribe [:chats/edit-message])
|
||||||
:ref sticker-ref}
|
[rn/view {:style (merge {:flex-direction :row} (when show-send {:width 0 :right -100}))
|
||||||
(when stickers
|
:ref sticker-ref}
|
||||||
[touchable-stickers-icon {:panel :stickers
|
(when stickers
|
||||||
:accessibility-label :show-stickers-icon
|
[touchable-stickers-icon {:panel :stickers
|
||||||
:active active-panel
|
:accessibility-label :show-stickers-icon
|
||||||
:input-focus #(input-focus text-input-ref)
|
:active active-panel
|
||||||
:set-active set-active-panel}])
|
:input-focus #(input-focus text-input-ref)
|
||||||
(when audio
|
:set-active set-active-panel}])
|
||||||
[touchable-audio-icon {:panel :audio
|
(when audio
|
||||||
:accessibility-label :show-audio-message-icon
|
[touchable-audio-icon {:panel :audio
|
||||||
:active active-panel
|
:accessibility-label :show-audio-message-icon
|
||||||
:input-focus #(input-focus text-input-ref)
|
:active active-panel
|
||||||
:set-active set-active-panel}])]]]]))))
|
:input-focus #(input-focus text-input-ref)
|
||||||
|
:set-active set-active-panel}])])]]]))))
|
||||||
|
|
|
@ -1,30 +1,34 @@
|
||||||
(ns status-im.ui.screens.chat.components.reply
|
(ns status-im.ui.screens.chat.components.reply
|
||||||
(:require [quo.core :as quo]
|
(:require [quo.core :as quo]
|
||||||
|
[quo.react :as quo.react]
|
||||||
[quo.react-native :as rn]
|
[quo.react-native :as rn]
|
||||||
|
[quo.design-system.colors :as quo.colors]
|
||||||
[status-im.i18n.i18n :as i18n]
|
[status-im.i18n.i18n :as i18n]
|
||||||
[quo.design-system.colors :as colors]
|
|
||||||
[quo.components.animated.pressable :as pressable]
|
[quo.components.animated.pressable :as pressable]
|
||||||
[status-im.ui.components.icons.icons :as icons]
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
[status-im.ethereum.stateofus :as stateofus]
|
[status-im.ethereum.stateofus :as stateofus]
|
||||||
[status-im.ui.screens.chat.components.style :as styles]
|
[status-im.ui.screens.chat.components.style :as styles]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.ui.components.react :as react]
|
|
||||||
[clojure.string :as string]))
|
[clojure.string :as string]))
|
||||||
|
|
||||||
(def ^:private reply-symbol "↪ ")
|
(def ^:private reply-symbol "↪ ")
|
||||||
|
|
||||||
|
(defn input-focus [text-input-ref]
|
||||||
|
(some-> ^js (quo.react/current-ref text-input-ref) .focus))
|
||||||
|
|
||||||
(defn format-author [contact-name]
|
(defn format-author [contact-name]
|
||||||
(if (or (= (aget contact-name 0) "@")
|
(let [author (if (or (= (aget contact-name 0) "@")
|
||||||
;; in case of replies
|
;; in case of replies
|
||||||
(= (aget contact-name 1) "@"))
|
(= (aget contact-name 1) "@"))
|
||||||
(or (stateofus/username contact-name)
|
(or (stateofus/username contact-name)
|
||||||
(subs contact-name 0 81))
|
(subs contact-name 0 81))
|
||||||
contact-name))
|
contact-name)]
|
||||||
|
(i18n/label :replying-to {:author author})))
|
||||||
|
|
||||||
(defn format-reply-author [from username current-public-key]
|
(defn format-reply-author [from username current-public-key]
|
||||||
(or (and (= from current-public-key)
|
(or (and (= from current-public-key)
|
||||||
(str reply-symbol (i18n/label :t/You)))
|
(str reply-symbol (i18n/label :t/You)))
|
||||||
(format-author (str reply-symbol username))))
|
(str reply-symbol (format-author username))))
|
||||||
|
|
||||||
(defn get-quoted-text-with-mentions [parsed-text]
|
(defn get-quoted-text-with-mentions [parsed-text]
|
||||||
(string/join
|
(string/join
|
||||||
|
@ -43,36 +47,23 @@
|
||||||
literal))
|
literal))
|
||||||
parsed-text)))
|
parsed-text)))
|
||||||
|
|
||||||
(defn reply-message [{:keys [from content]}]
|
(defn reply-message [{:keys [from]}]
|
||||||
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])
|
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])
|
||||||
current-public-key @(re-frame/subscribe [:multiaccount/public-key])
|
current-public-key @(re-frame/subscribe [:multiaccount/public-key])]
|
||||||
{:keys [image parsed-text]} content]
|
[rn/view {:style {:flex-direction :row}}
|
||||||
[rn/view {:style (styles/reply-container false)}
|
|
||||||
[rn/view {:style (styles/reply-content)}
|
[rn/view {:style (styles/reply-content)}
|
||||||
[quo/text {:weight :medium
|
[quo/text {:weight :medium
|
||||||
:number-of-lines 1
|
:number-of-lines 1
|
||||||
:style {:line-height 18}
|
:style {:line-height 18}}
|
||||||
:size :small}
|
(format-reply-author from contact-name current-public-key)]]
|
||||||
(format-reply-author from contact-name current-public-key)]
|
|
||||||
(if image
|
|
||||||
[react/image {:style {:width 56
|
|
||||||
:height 56
|
|
||||||
:background-color :black
|
|
||||||
:margin-top 2
|
|
||||||
:border-radius 4}
|
|
||||||
:source {:uri image}}]
|
|
||||||
[quo/text {:size :small
|
|
||||||
:number-of-lines 1
|
|
||||||
:style {:line-height 18}}
|
|
||||||
(get-quoted-text-with-mentions parsed-text)])]
|
|
||||||
[rn/view
|
[rn/view
|
||||||
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])
|
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])
|
||||||
:accessibility-label :cancel-message-reply}
|
:accessibility-label :cancel-message-reply}
|
||||||
[icons/icon :main-icons/close-circle {:container-style (styles/close-button)
|
[icons/icon :main-icons/close-circle {:container-style (styles/close-button)
|
||||||
:color (:icon-01 @colors/theme)}]]]]))
|
:color (:icon-02 @quo.colors/theme)}]]]]))
|
||||||
|
|
||||||
(defn send-image [images]
|
(defn send-image [images]
|
||||||
[rn/view {:style (styles/reply-container true)}
|
[rn/view {:style (styles/reply-container-image)}
|
||||||
[rn/scroll-view {:horizontal true
|
[rn/scroll-view {:horizontal true
|
||||||
:style (styles/reply-content)}
|
:style (styles/reply-content)}
|
||||||
(for [{:keys [uri]} (vals images)]
|
(for [{:keys [uri]} (vals images)]
|
||||||
|
@ -86,4 +77,26 @@
|
||||||
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-sending-image])
|
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/cancel-sending-image])
|
||||||
:accessibility-label :cancel-send-image}
|
:accessibility-label :cancel-send-image}
|
||||||
[icons/icon :main-icons/close-circle {:container-style (styles/close-button)
|
[icons/icon :main-icons/close-circle {:container-style (styles/close-button)
|
||||||
:color colors/white}]]]])
|
:color quo.colors/white}]]]])
|
||||||
|
|
||||||
|
(defn focus-input-on-reply [reply had-reply text-input-ref]
|
||||||
|
;;when we show reply we focus input
|
||||||
|
(when-not (= reply @had-reply)
|
||||||
|
(reset! had-reply reply)
|
||||||
|
(when reply
|
||||||
|
(js/setTimeout #(input-focus text-input-ref) 250))))
|
||||||
|
|
||||||
|
(defn reply-message-wrapper [reply]
|
||||||
|
[rn/view {:style {:padding-horizontal 15
|
||||||
|
:border-top-width 1
|
||||||
|
:border-top-color (:ui-01 @quo.colors/theme)
|
||||||
|
:padding-vertical 8}}
|
||||||
|
[reply-message reply]])
|
||||||
|
|
||||||
|
(defn reply-message-auto-focus-wrapper [text-input-ref]
|
||||||
|
(let [had-reply (atom nil)]
|
||||||
|
(fn []
|
||||||
|
(let [reply @(re-frame/subscribe [:chats/reply-message])]
|
||||||
|
(focus-input-on-reply reply had-reply text-input-ref)
|
||||||
|
(when reply
|
||||||
|
[reply-message-wrapper reply])))))
|
||||||
|
|
|
@ -74,16 +74,17 @@
|
||||||
(:icon-04 @colors/theme)
|
(:icon-04 @colors/theme)
|
||||||
(:icon-02 @colors/theme))})
|
(:icon-02 @colors/theme))})
|
||||||
|
|
||||||
(defn reply-container [image]
|
(defn reply-container-image []
|
||||||
{:border-top-left-radius 14
|
{:border-top-left-radius 14
|
||||||
:border-top-right-radius 14
|
:border-top-right-radius 14
|
||||||
:border-bottom-right-radius 4
|
:border-bottom-right-radius 4
|
||||||
:border-bottom-left-radius 14
|
:border-bottom-left-radius 14
|
||||||
:margin 2
|
:margin 2
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:background-color (if image
|
:background-color (:ui-03 @colors/theme)})
|
||||||
(:ui-03 @colors/theme)
|
|
||||||
(:ui-02 @colors/theme))})
|
(defn reply-container []
|
||||||
|
{:flex-direction :row})
|
||||||
|
|
||||||
(defn reply-content []
|
(defn reply-content []
|
||||||
{:padding-vertical 6
|
{:padding-vertical 6
|
||||||
|
@ -91,7 +92,7 @@
|
||||||
:flex 1})
|
:flex 1})
|
||||||
|
|
||||||
(defn close-button []
|
(defn close-button []
|
||||||
{:padding 4})
|
{:margin-top 3})
|
||||||
|
|
||||||
(defn send-message-button []
|
(defn send-message-button []
|
||||||
{:margin-vertical 4
|
{:margin-vertical 4
|
||||||
|
|
|
@ -29,10 +29,12 @@
|
||||||
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||||
contact-name))
|
contact-name))
|
||||||
|
|
||||||
|
(def edited-at-text (str " ⌫ " (i18n/label :t/edited)))
|
||||||
|
|
||||||
(defn message-timestamp
|
(defn message-timestamp
|
||||||
([message]
|
([message]
|
||||||
[message-timestamp message false])
|
[message-timestamp message false])
|
||||||
([{:keys [timestamp-str outgoing content outgoing-status]} justify-timestamp?]
|
([{:keys [timestamp-str outgoing content outgoing-status edited-at]} justify-timestamp?]
|
||||||
[react/view (when justify-timestamp?
|
[react/view (when justify-timestamp?
|
||||||
{:align-self :flex-end
|
{:align-self :flex-end
|
||||||
:position :absolute
|
:position :absolute
|
||||||
|
@ -52,7 +54,9 @@
|
||||||
:color colors/white
|
:color colors/white
|
||||||
:accessibility-label (name outgoing-status)}])
|
:accessibility-label (name outgoing-status)}])
|
||||||
[react/text {:style (style/message-timestamp-text outgoing)}
|
[react/text {:style (style/message-timestamp-text outgoing)}
|
||||||
timestamp-str]]))
|
(str
|
||||||
|
timestamp-str
|
||||||
|
(when edited-at edited-at-text))]]))
|
||||||
|
|
||||||
(defview quoted-message
|
(defview quoted-message
|
||||||
[_ {:keys [from parsed-text image]} outgoing current-public-key public?]
|
[_ {:keys [from parsed-text image]} outgoing current-public-key public?]
|
||||||
|
@ -161,10 +165,10 @@
|
||||||
(defn render-parsed-text [message tree]
|
(defn render-parsed-text [message tree]
|
||||||
(reduce (fn [acc e] (render-block message acc e)) [:<>] tree))
|
(reduce (fn [acc e] (render-block message acc e)) [:<>] tree))
|
||||||
|
|
||||||
(defn render-parsed-text-with-timestamp [{:keys [timestamp-str outgoing] :as message} tree]
|
(defn render-parsed-text-with-timestamp [{:keys [timestamp-str outgoing edited-at] :as message} tree]
|
||||||
(let [elements (render-parsed-text message tree)
|
(let [elements (render-parsed-text message tree)
|
||||||
timestamp [react/text {:style (style/message-timestamp-placeholder)}
|
timestamp [react/text {:style (style/message-timestamp-placeholder)}
|
||||||
(str (if outgoing " " " ") timestamp-str)]
|
(str (if outgoing " " " ") timestamp-str (when edited-at edited-at-text))]
|
||||||
last-element (peek elements)]
|
last-element (peek elements)]
|
||||||
;; Using `nth` here as slightly faster than `first`, roughly 30%
|
;; Using `nth` here as slightly faster than `first`, roughly 30%
|
||||||
;; It's worth considering pure js structures for this code path as
|
;; It's worth considering pure js structures for this code path as
|
||||||
|
@ -334,6 +338,9 @@
|
||||||
(defn on-long-press-fn [on-long-press message content]
|
(defn on-long-press-fn [on-long-press message content]
|
||||||
(on-long-press
|
(on-long-press
|
||||||
(concat
|
(concat
|
||||||
|
(when (:outgoing message)
|
||||||
|
[{:on-press #(re-frame/dispatch [:chat.ui/edit-message message])
|
||||||
|
:label (i18n/label :t/edit)}])
|
||||||
(when (:show-input? message)
|
(when (:show-input? message)
|
||||||
[{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
[{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
||||||
:label (i18n/label :t/message-reply)}])
|
:label (i18n/label :t/message-reply)}])
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
[status-im.ui.components.connectivity.view :as connectivity]
|
[status-im.ui.components.connectivity.view :as connectivity]
|
||||||
[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.edit :as edit]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[quo.animated :as animated]
|
[quo.animated :as animated]
|
||||||
[quo.react-native :as rn]
|
[quo.react-native :as rn]
|
||||||
|
@ -348,14 +350,21 @@
|
||||||
[invitation-bar chat-id]])
|
[invitation-bar chat-id]])
|
||||||
[components/autocomplete-mentions text-input-ref max-bottom-space]
|
[components/autocomplete-mentions text-input-ref max-bottom-space]
|
||||||
(when show-input?
|
(when show-input?
|
||||||
|
;; NOTE: this only accepts two children
|
||||||
[accessory/view {:y position-y
|
[accessory/view {:y position-y
|
||||||
:pan-state pan-state
|
:pan-state pan-state
|
||||||
:has-panel (boolean @active-panel)
|
:has-panel (boolean @active-panel)
|
||||||
:on-close on-close
|
:on-close on-close
|
||||||
:on-update-inset on-update}
|
:on-update-inset on-update}
|
||||||
[components/chat-toolbar
|
[react/view
|
||||||
{:chat-id chat-id
|
[edit/edit-message-auto-focus-wrapper text-input-ref]
|
||||||
:active-panel @active-panel
|
[reply/reply-message-auto-focus-wrapper text-input-ref]
|
||||||
:set-active-panel set-active-panel
|
;; We set the key so we can force a re-render as
|
||||||
:text-input-ref text-input-ref}]
|
;; it does not rely on ratom but just atoms
|
||||||
|
^{:key (str @components/chat-input-key "chat-input")}
|
||||||
|
[components/chat-toolbar
|
||||||
|
{:chat-id chat-id
|
||||||
|
:active-panel @active-panel
|
||||||
|
:set-active-panel set-active-panel
|
||||||
|
:text-input-ref text-input-ref}]]
|
||||||
[bottom-sheet @active-panel]])]))})))
|
[bottom-sheet @active-panel]])]))})))
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
|
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.80.2",
|
"version": "v0.80.3",
|
||||||
"commit-sha1": "96d5683b3b1fa2b283c829e0bb351a2e2c0e34c5",
|
"commit-sha1": "45a8de8e2bd3d3cdb1350ebfd71e6bcaadff630e",
|
||||||
"src-sha256": "1hg1jkqbkmp0js5kdpxiz6b34gpmy84wpq0bybf8hbbqh84drrx7"
|
"src-sha256": "054r35mgckv2zzy21sxidqfh7f2jk1dkl3vzp4n1rlc8807fqybm"
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,9 @@
|
||||||
"request-access": "Request access",
|
"request-access": "Request access",
|
||||||
"membership-request-pending": "Membership request pending",
|
"membership-request-pending": "Membership request pending",
|
||||||
"create-community": "Create a community",
|
"create-community": "Create a community",
|
||||||
|
"edited": "Edited",
|
||||||
"edit-community": "Edit community",
|
"edit-community": "Edit community",
|
||||||
|
"editing-message": "Editing message",
|
||||||
"community-edit-title": "Edit community",
|
"community-edit-title": "Edit community",
|
||||||
"community-invite-title": "Invite",
|
"community-invite-title": "Invite",
|
||||||
"community-share-title": "Share",
|
"community-share-title": "Share",
|
||||||
|
@ -825,6 +827,7 @@
|
||||||
"message-not-sent": "Message not sent",
|
"message-not-sent": "Message not sent",
|
||||||
"message-options-cancel": "Cancel",
|
"message-options-cancel": "Cancel",
|
||||||
"message-reply": "Reply",
|
"message-reply": "Reply",
|
||||||
|
"replying-to": "Replying to {{author}}",
|
||||||
"data-syncing": "Data syncing",
|
"data-syncing": "Data syncing",
|
||||||
"messages": "Messages",
|
"messages": "Messages",
|
||||||
"chat-is-a-contact": "Contact",
|
"chat-is-a-contact": "Contact",
|
||||||
|
|
Loading…
Reference in New Issue