[Fixes: #10801] Send chat messages in order

Chat messages are now sent in order using a different endpoint
`sendChatMessages`.
Text should always be displayed after images.

This is not implementing a Caption field, that would require either a
protocol change or leverage the `text` in the message.
It applies for both normal chats and timelines.

Move also all inputs under `chat/inputs` so we avoid re-renders as
`chats` has changed.

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2020-12-01 15:11:15 +01:00
parent fd5be21207
commit f04042c643
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
10 changed files with 91 additions and 75 deletions

View File

@ -99,7 +99,7 @@
{:events [:chat.ui/image-captured]}
[{:keys [db]} uri]
(let [current-chat-id (:current-chat-id db)
images (get-in db [:chats current-chat-id :metadata :sending-image])]
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(when (and (< (count images) config/max-images-batch)
(not (get images uri)))
{::image-selected uri})))
@ -118,7 +118,7 @@
{:events [:chat.ui/clear-sending-images]}
[{:keys [db]}]
(let [current-chat-id (:current-chat-id db)]
{:db (update-in db [:chats current-chat-id :metadata] assoc :sending-image {})}))
{:db (update-in db [:chat/inputs current-chat-id :metadata] assoc :sending-image {})}))
(fx/defn cancel-sending-image
{:events [:chat.ui/cancel-sending-image]}
@ -129,19 +129,19 @@
{:events [:chat.ui/image-selected]}
[{:keys [db]} original uri]
(let [current-chat-id (:current-chat-id db)]
{:db (update-in db [:chats current-chat-id :metadata :sending-image original] merge {:uri uri})}))
{:db (update-in db [:chat/inputs current-chat-id :metadata :sending-image original] merge {:uri uri})}))
(fx/defn image-unselected
{:events [:chat.ui/image-unselected]}
[{:keys [db]} original]
(let [current-chat-id (:current-chat-id db)]
{:db (update-in db [:chats current-chat-id :metadata :sending-image] dissoc original)}))
{:db (update-in db [:chat/inputs current-chat-id :metadata :sending-image] dissoc original)}))
(fx/defn chat-open-image-picker
{:events [:chat.ui/open-image-picker]}
[{:keys [db]}]
(let [current-chat-id (:current-chat-id db)
images (get-in db [:chats current-chat-id :metadata :sending-image])]
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(when (< (count images) config/max-images-batch)
{::chat-open-image-picker nil})))
@ -149,7 +149,7 @@
{:events [:chat.ui/show-image-picker-camera]}
[{:keys [db]}]
(let [current-chat-id (:current-chat-id db)
images (get-in db [:chats current-chat-id :metadata :sending-image])]
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(when (< (count images) config/max-images-batch)
{::chat-open-image-picker-camera nil})))
@ -157,9 +157,9 @@
{:events [:chat.ui/camera-roll-pick]}
[{:keys [db]} uri]
(let [current-chat-id (:current-chat-id db)
images (get-in db [:chats current-chat-id :metadata :sending-image])]
images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(if (get-in db [:chats current-chat-id :timeline?])
{:db (assoc-in db [:chats current-chat-id :metadata :sending-image] {})
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :sending-image] {})
::image-selected uri}
(when (and (< (count images) config/max-images-batch)
(not (get images uri)))

View File

@ -49,7 +49,7 @@
;; 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
;; programmatically, so we have to call `on-text-input` manually
(mentions/on-text-input
(let [match-len (count match)
searched-text-len (count searched-text)
@ -99,51 +99,60 @@
(let [current-chat-id (:current-chat-id db)]
(fx/merge cofx
{:db (-> db
(assoc-in [:chats current-chat-id :metadata :responding-to-message]
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
message)
(update-in [:chats current-chat-id :metadata]
(update-in [:chat/inputs current-chat-id :metadata]
dissoc :sending-image))})))
(fx/defn cancel-message-reply
"Cancels stage message reply"
[{:keys [db]}]
(let [current-chat-id (:current-chat-id db)]
{:db (assoc-in db [:chats current-chat-id :metadata :responding-to-message] nil)}))
{:db (assoc-in db [:chat/inputs current-chat-id :metadata :responding-to-message] nil)}))
(fx/defn send-plain-text-message
"when not empty, proceed by sending text message"
[{:keys [db] :as cofx} input-text current-chat-id]
(defn build-text-message
[{:keys [db]} input-text current-chat-id]
(when-not (string/blank? input-text)
(let [{:keys [message-id]}
(get-in db [:chats current-chat-id :metadata :responding-to-message])
(get-in db [:chat/inputs current-chat-id :metadata :responding-to-message])
preferred-name (get-in db [:multiaccount :preferred-name])
emoji? (message-content/emoji-only-content? {:text input-text
:response-to message-id})]
(fx/merge cofx
{:db (assoc-in db [:chats current-chat-id :metadata :responding-to-message] nil)}
(chat.message/send-message {:chat-id current-chat-id
:content-type (if emoji?
constants/content-type-emoji
constants/content-type-text)
:text input-text
:response-to message-id
:ens-name preferred-name})
(set-chat-input-text nil)
(process-cooldown)))))
{:chat-id current-chat-id
:content-type (if emoji?
constants/content-type-emoji
constants/content-type-text)
:text input-text
:response-to message-id
:ens-name preferred-name})))
(fx/defn send-image
[{{:keys [current-chat-id] :as db} :db :as cofx} chat-id]
(let [images (get-in db [:chats current-chat-id :metadata :sending-image])]
(defn build-image-messages
[{{:keys [current-chat-id] :as db} :db} chat-id]
(let [images (get-in db [:chat/inputs current-chat-id :metadata :sending-image])]
(mapv (fn [[_ {:keys [uri]}]]
{:chat-id chat-id
:content-type constants/content-type-image
:image-path (utils/safe-replace uri #"file://" "")
:text (i18n/label :t/update-to-see-image)})
images)))
(fx/defn clean-input [{:keys [db] :as cofx}]
(let [current-chat-id (:current-chat-id db)]
(fx/merge cofx
;; NOTE(Ferossgp): Ideally here and for all other types of message we should dissoc on success only
{:db (update-in db [:chats current-chat-id :metadata] dissoc :sending-image)}
(chat.message/send-messages
(map (fn [[_ {:keys [uri]}]]
{:chat-id chat-id
:content-type constants/content-type-image
:image-path (utils/safe-replace uri #"file://" "")
:text (i18n/label :t/update-to-see-image)})
images)))))
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :sending-image] nil)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil))}
(set-chat-input-text nil))))
(fx/defn send-messages [{:keys [db] :as cofx} input-text current-chat-id]
(let [image-messages (build-image-messages cofx current-chat-id)
text-message (build-text-message cofx input-text current-chat-id)
messages (keep identity (conj image-messages text-message))]
(when (seq messages)
(fx/merge cofx
(clean-input cofx)
(process-cooldown)
(chat.message/send-messages messages)))))
(fx/defn send-my-status-message
"when not empty, proceed by sending text message with public key topic"
@ -151,9 +160,7 @@
[{{:keys [current-chat-id] :as db} :db :as cofx}]
(let [{:keys [input-text]} (get-in db [:chat/inputs current-chat-id])
chat-id (chat/profile-chat-topic (get-in db [:multiaccount :public-key]))]
(fx/merge cofx
(send-image chat-id)
(send-plain-text-message input-text chat-id))))
(send-messages cofx input-text chat-id)))
(fx/defn send-audio-message
[cofx audio-path duration current-chat-id]
@ -179,7 +186,6 @@
(let [{:keys [input-text]} (get-in db [:chat/inputs current-chat-id])
input-text-with-mentions (mentions/check-mentions cofx input-text)]
(fx/merge cofx
(send-image current-chat-id)
(send-plain-text-message input-text-with-mentions current-chat-id)
(send-messages input-text-with-mentions current-chat-id)
(mentions/clear-mentions)
(mentions/clear-cursor))))

View File

@ -43,16 +43,17 @@
(let [last-element-clock-value (:clock-value (.-item last-element))
chat-id (:chat-id (.-item last-element))]
(when (and last-element-clock-value
(get-in db [:chats chat-id :messages-initialized?]))
(get-in db [:pagination-info chat-id :messages-initialized?]))
(let [new-messages (reduce-kv (fn [acc message-id {:keys [clock-value] :as v}]
(if (<= last-element-clock-value clock-value)
(assoc acc message-id v)
acc))
{}
(get-in db [:chats chat-id :messages]))]
(get-in db [:messages chat-id]))]
{:db (-> db
(assoc-in [:messages chat-id] new-messages)
(assoc-in [:pagination-info chat-id] {:all-loaded? false
:messages-initialized? true
:cursor (clock-value->cursor last-element-clock-value)})
(assoc-in [:message-lists chat-id] (message-list/add-many nil (vals new-messages))))}))))))

View File

@ -505,7 +505,7 @@
[:chats chat-id :mentions]
assoc
:at-idxs new-at-idxs)
(assoc-in [:chats/input-with-mentions chat-id] calculated-input))}))
(assoc-in [:chat/inputs-with-mentions chat-id] calculated-input))}))
(fx/defn calculate-suggestions
{:events [::calculate-suggestions]}
@ -521,7 +521,7 @@
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] nil)
(assoc-in [:chats chat-id :mentions :at-idxs] nil)
(assoc-in [:chats/input-with-mentions chat-id] [[:text text]]))}
(assoc-in [:chat/inputs-with-mentions chat-id] [[:text text]]))}
(let [new-at-idxs (check-idx-for-mentions
text
at-idxs
@ -551,7 +551,7 @@
:at-sign-idx at-sign-idx
:at-idxs new-at-idxs
:mention-end end)
(assoc-in [:chats/input-with-mentions chat-id] calculated-input)
(assoc-in [:chat/inputs-with-mentions chat-id] calculated-input)
(assoc-in [:chats/mention-suggestions chat-id] mentions))}))))
(defn new-input-text-with-mention
@ -586,7 +586,7 @@
cofx
{:db (-> db
(update-in [:chats chat-id] dissoc :mentions)
(update :chats/input-with-mentions dissoc chat-id))}
(update :chat/inputs-with-mentions dissoc chat-id))}
(clear-suggestions))))
(fx/defn clear-cursor

View File

@ -164,7 +164,7 @@
(fx/merge cofx
;;If its a profile updates we want to add this message to the timeline as well
#(when (get-in cofx [:db :chats chat-id :profile-public-key])
{:dispatch [::receive-one (assoc message :chat-id chat-model/timeline-chat-id)]})
{:dispatch-n [[::receive-one (assoc message :chat-id chat-model/timeline-chat-id)]]})
#(let [message-with-chat-id (assoc message :chat-id chat-id)]
(when-not (earlier-than-deleted-at? cofx message-with-chat-id)
(if (message-loaded? cofx message-with-chat-id)

View File

@ -45,6 +45,7 @@
"wakuext_enableInstallation" {}
"wakuext_disableInstallation" {}
"wakuext_sendChatMessage" {}
"wakuext_sendChatMessages" {}
"wakuext_confirmJoiningGroup" {}
"wakuext_addAdminsToGroupChat" {}
"wakuext_addMembersToGroupChat" {}

View File

@ -124,7 +124,7 @@
(reg-root-key-sub :group-chat/invitations :group-chat/invitations)
(reg-root-key-sub :chats/mention-suggestions :chats/mention-suggestions)
(reg-root-key-sub :chats/cursor :chats/cursor)
(reg-root-key-sub :chats/input-with-mentions :chats/input-with-mentions)
(reg-root-key-sub :chat/inputs-with-mentions :chat/inputs-with-mentions)
(reg-root-key-sub :inactive-chat-id :inactive-chat-id)
;;browser
(reg-root-key-sub :browsers :browser/browsers)
@ -651,11 +651,17 @@
(get chats current-chat-id)))
(re-frame/reg-sub
:chats/current-chat-input-text
:chats/current-chat-inputs
:<- [:chats/current-chat-id]
:<- [:chat/inputs]
(fn [[chat-id inputs]]
(get-in inputs [chat-id :input-text])))
(get inputs chat-id)))
(re-frame/reg-sub
:chats/current-chat-input-text
:<- [:chats/current-chat-inputs]
(fn [input]
(:input-text input)))
(re-frame/reg-sub
:chats/current-chat-membership
@ -835,15 +841,15 @@
(re-frame/reg-sub
:chats/reply-message
:<- [:chats/current-chat]
:<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}]
(:responding-to-message metadata)))
(re-frame/reg-sub
:chats/sending-image
:<- [:chats/current-raw-chat]
:<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}]
(get-in metadata [:sending-image])))
(:sending-image metadata)))
(re-frame/reg-sub
:public-chat.new/topic-error-message
@ -977,7 +983,7 @@
(re-frame/reg-sub
:chat/input-with-mentions
:<- [:chats/current-chat-id]
:<- [:chats/input-with-mentions]
:<- [:chat/inputs-with-mentions]
(fn [[chat-id cursor]]
(get cursor chat-id)))

View File

@ -14,22 +14,23 @@
audio-duration-ms
sticker
content-type]}]
{:method (json-rpc/call-ext-method "sendChatMessage")
:params [{:chatId chat-id
:text text
:responseTo response-to
:ensName ens-name
:imagePath image-path
:audioPath audio-path
:audioDurationMs audio-duration-ms
:sticker sticker
:contentType content-type}]
:on-success
#(re-frame/dispatch [:transport/message-sent % 1])
:on-failure #(log/error "failed to send a message" %)})
{:chatId chat-id
:text text
:responseTo response-to
:ensName ens-name
:imagePath image-path
:audioPath audio-path
:audioDurationMs audio-duration-ms
:sticker sticker
:contentType content-type})
(fx/defn send-chat-messages [cofx messages]
{::json-rpc/call (mapv build-message messages)})
{::json-rpc/call
[{:method (json-rpc/call-ext-method "sendChatMessages")
:params [(mapv build-message messages)]
:on-success
#(re-frame/dispatch [:transport/message-sent % 1])
:on-failure #(log/error "failed to send a message" %)}]})
(fx/defn send-reaction [cofx {:keys [message-id chat-id emoji-id]}]
{::json-rpc/call [{:method (json-rpc/call-ext-method

View File

@ -13,6 +13,7 @@
(def ^:private mergeable-keys
#{:filters/load-filters
:pairing/set-installation-metadata
:dispatch-n
:status-im.ens.core/verify-names
:shh/send-direct-message
:shh/remove-filter

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im",
"repo": "status-go",
"version": "v0.64.2",
"commit-sha1": "0304b3fa46a6a222b0e346d4a2d1472b965eb78c",
"src-sha256": "0jmwvapv1k3g45gv5xzwshsf2b96b897xs5wyp69sdz9p2nnl18z"
"version": "v0.64.3",
"commit-sha1": "14f4c40404d4d3b1a4e9f739b156f8c8b2eeded6",
"src-sha256": "0h1mbn4xb4r7fwniyjgi3hj5bwj8kyj8jfi47l33rg8i6mnvd3w9"
}