Extend message hash confirmation for group chats
Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
e8069f523d
commit
3e761c3b85
|
@ -17,6 +17,7 @@
|
|||
|
||||
(def min-password-length 6)
|
||||
(def max-chat-name-length 20)
|
||||
(def max-group-chat-participants 10)
|
||||
(def response-suggesstion-resize-duration 100)
|
||||
(def default-number-of-messages 20)
|
||||
(def blocks-per-hour 120)
|
||||
|
|
|
@ -1292,8 +1292,8 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:transport/message-sent
|
||||
(fn [cofx [_ chat-id message-id message-type envelope-hash-js]]
|
||||
(transport.message/set-message-envelope-hash cofx chat-id message-id message-type envelope-hash-js)))
|
||||
(fn [cofx [_ chat-id message-id message-type envelope-hash-js messages-count]]
|
||||
(transport.message/set-message-envelope-hash cofx chat-id message-id message-type envelope-hash-js messages-count)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:transport/contact-message-sent
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.group-chat :as message.group-chat]
|
||||
[status-im.transport.message.public-chat :as transport.public-chat]
|
||||
|
||||
[status-im.transport.chat.core :as transport.chat]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.chat.models :as models.chat]
|
||||
|
@ -465,7 +464,7 @@
|
|||
(map #(assoc % :from from) events))
|
||||
all-updates))
|
||||
|
||||
(defn get-inviter-pk [my-public-key {:keys [membership-updates] :as chat}]
|
||||
(defn get-inviter-pk [my-public-key {:keys [membership-updates]}]
|
||||
(->> membership-updates
|
||||
unwrap-events
|
||||
(keep (fn [{:keys [from type members]}]
|
||||
|
@ -501,12 +500,15 @@
|
|||
(let [previous-chat (get-in cofx [:db :chats chat-id])
|
||||
all-updates (clojure.set/union (set (:membership-updates previous-chat))
|
||||
(set (:membership-updates membership-update)))
|
||||
my-public-key (accounts.db/current-public-key cofx)
|
||||
unwrapped-events (unwrap-events all-updates)
|
||||
new-group (build-group unwrapped-events)]
|
||||
new-group (build-group unwrapped-events)
|
||||
member? (contains? (:contacts new-group) my-public-key)]
|
||||
(fx/merge cofx
|
||||
(models.chat/upsert-chat {:chat-id chat-id
|
||||
:name (:name new-group)
|
||||
:is-active (get previous-chat :is-active true)
|
||||
:is-active (or member?
|
||||
(get previous-chat :is-active true))
|
||||
:group-chat true
|
||||
:membership-updates (into [] all-updates)
|
||||
:admins (:admins new-group)
|
||||
|
|
|
@ -57,6 +57,20 @@
|
|||
{:db (assoc-in db [:transport/chats chat-id :resend?] nil)
|
||||
:data-store/tx [(transport-store/save-transport-tx {:chat-id chat-id
|
||||
:chat updated-chat})]}))
|
||||
(fx/defn check-confirmations [{:keys [db] :as cofx} status chat-id message-id]
|
||||
(when-let [{:keys [pending-confirmations not-sent]}
|
||||
(get-in db [:transport/message-ids->confirmations message-id])]
|
||||
(if (zero? (dec pending-confirmations))
|
||||
(fx/merge cofx
|
||||
{:db (update db :transport/message-ids->confirmations dissoc message-id)}
|
||||
(models.message/update-message-status chat-id message-id (if not-sent
|
||||
:not-sent
|
||||
status)))
|
||||
(let [confirmations {:pending-confirmations (dec pending-confirmations)
|
||||
:not-sent (or not-sent
|
||||
(= :not-sent status))}]
|
||||
{:db (assoc-in db [:transport/message-ids->confirmations message-id] confirmations)}))))
|
||||
|
||||
(fx/defn update-envelope-status
|
||||
[{:keys [db] :as cofx} envelope-hash status]
|
||||
(let [{:keys [chat-id message-type message-id]}
|
||||
|
@ -72,7 +86,7 @@
|
|||
(let [{:keys [fcm-token]} (get-in db [:contacts/contacts chat-id])]
|
||||
(fx/merge cofx
|
||||
(remove-hash envelope-hash)
|
||||
(models.message/update-message-status chat-id message-id status)
|
||||
(check-confirmations status chat-id message-id)
|
||||
(models.message/send-push-notification fcm-token status)))))))
|
||||
|
||||
(fx/defn set-contact-message-envelope-hash
|
||||
|
@ -82,18 +96,19 @@
|
|||
:message-type :contact-message})})
|
||||
|
||||
(fx/defn set-message-envelope-hash
|
||||
"message-type is used for tracking
|
||||
TODO (cammellos): For group messages it returns multiple hashes, for now
|
||||
we naively assume that if one is sent the batch is ok"
|
||||
[{:keys [db] :as cofx} chat-id message-id message-type envelope-hash-js]
|
||||
"message-type is used for tracking"
|
||||
[{:keys [db] :as cofx} chat-id message-id message-type envelope-hash-js messages-count]
|
||||
(let [envelope-hash (js->clj envelope-hash-js)
|
||||
hash (if (vector? envelope-hash)
|
||||
(last envelope-hash)
|
||||
envelope-hash)]
|
||||
{:db (assoc-in db [:transport/message-envelopes hash]
|
||||
{:chat-id chat-id
|
||||
:message-id message-id
|
||||
:message-type message-type})}))
|
||||
{:db (-> db
|
||||
(assoc-in [:transport/message-envelopes hash]
|
||||
{:chat-id chat-id
|
||||
:message-id message-id
|
||||
:message-type message-type})
|
||||
(update-in [:transport/message-ids->confirmations message-id]
|
||||
#(or % {:pending-confirmations messages-count})))}))
|
||||
|
||||
(defn- own-info [db]
|
||||
(let [{:keys [name photo-path address]} (:account/account db)
|
||||
|
|
|
@ -59,11 +59,11 @@
|
|||
(on-success resp)
|
||||
(on-error err))))))
|
||||
|
||||
(defn handle-response [success-event error-event]
|
||||
(defn handle-response [success-event error-event messages-count]
|
||||
(fn [err resp]
|
||||
(if-not err
|
||||
(if success-event
|
||||
(re-frame/dispatch (conj success-event resp))
|
||||
(re-frame/dispatch (conj success-event resp messages-count))
|
||||
(log/debug :shh/post-success))
|
||||
(re-frame/dispatch [error-event err resp]))))
|
||||
|
||||
|
@ -82,12 +82,12 @@
|
|||
-shh
|
||||
(sendDirectMessage
|
||||
direct-message
|
||||
(handle-response success-event error-event)))))))
|
||||
(handle-response success-event error-event 1)))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/send-pairing-message
|
||||
(fn [params]
|
||||
(let [{:keys [web3 payload src dsts success-event error-event]
|
||||
(let [{:keys [web3 payload src success-event error-event]
|
||||
:or {error-event :protocol/send-status-message-error}} params
|
||||
message (clj->js {:sig src
|
||||
:chat constants/contact-discovery
|
||||
|
@ -98,7 +98,7 @@
|
|||
-shh
|
||||
(sendPairingMessage
|
||||
message
|
||||
(handle-response success-event error-event))))))
|
||||
(handle-response success-event error-event 1))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/send-group-message
|
||||
|
@ -118,7 +118,7 @@
|
|||
-shh
|
||||
(sendDirectMessage
|
||||
message
|
||||
(handle-response success-event error-event))))))))
|
||||
(handle-response success-event error-event (count dsts)))))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/send-public-message
|
||||
|
@ -134,7 +134,7 @@
|
|||
-shh
|
||||
(sendPublicMessage
|
||||
message
|
||||
(handle-response success-event error-event)))))))
|
||||
(handle-response success-event error-event 1)))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shh/post
|
||||
|
@ -145,7 +145,7 @@
|
|||
:whisper-message (update message :payload (comp transport.utils/from-utf8
|
||||
transit/serialize))
|
||||
:on-success (if success-event
|
||||
#(re-frame/dispatch (conj success-event %))
|
||||
#(re-frame/dispatch (conj success-event % 1))
|
||||
#(log/debug :shh/post-success))
|
||||
:on-error #(re-frame/dispatch [error-event %])}))))
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[taoensso.timbre :as log]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.chat.models :as models.chat]
|
||||
[status-im.group-chats.core :as models.group-chats]
|
||||
[status-im.ui.screens.chat.utils :as chat-utils]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.constants :as constants]
|
||||
|
@ -22,6 +24,7 @@
|
|||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.screens.desktop.main.chat.styles :as styles]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.ui.screens.chat.views :as views.chat]
|
||||
[status-im.ui.components.popup-menu.views :refer [show-desktop-menu
|
||||
get-chat-menu-items]]
|
||||
[status-im.i18n :as i18n]
|
||||
|
@ -323,12 +326,21 @@
|
|||
(re-frame/dispatch [:chat.ui/set-chat-input-text text])))}]
|
||||
[send-button inp-ref disconnected?]])))
|
||||
|
||||
(defn not-joined-group-chat? [chat current-public-key]
|
||||
(and (models.chat/group-chat? chat)
|
||||
(models.group-chats/invited? current-public-key chat)
|
||||
(not (models.group-chats/joined? current-public-key chat))))
|
||||
|
||||
(views/defview chat-view []
|
||||
(views/letsubs [{:keys [input-text chat-id] :as current-chat} [:chats/current-chat]]
|
||||
(views/letsubs [{:keys [input-text chat-id] :as current-chat} [:chats/current-chat]
|
||||
current-public-key [:account/public-key]]
|
||||
|
||||
[react/view {:style styles/chat-view}
|
||||
[toolbar-chat-view current-chat]
|
||||
[react/view {:style styles/separator}]
|
||||
[messages-view current-chat]
|
||||
(if (not-joined-group-chat? current-chat current-public-key)
|
||||
[views.chat/group-chat-join-section current-public-key current-chat]
|
||||
[messages-view current-chat])
|
||||
[react/view {:style styles/separator}]
|
||||
[reply-message-view]
|
||||
[chat-text-input chat-id input-text]]))
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.platform :as utils.platform]
|
||||
[status-im.ui.components.button.view :as buttons]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.contact.contact :refer [toggle-contact-view]]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
|
@ -86,8 +87,6 @@
|
|||
(i18n/label :t/group-chat-no-contacts)]
|
||||
[buttons/secondary-button {:on-press handle-invite-friends-pressed} (i18n/label :t/invite-friends)]])
|
||||
|
||||
(def max-participants 10)
|
||||
|
||||
(defn number-of-participants-disclaimer [number-of-participants-available]
|
||||
[react/view {:style styles/number-of-participants-disclaimer}
|
||||
[react/text (if (> number-of-participants-available
|
||||
|
@ -105,9 +104,10 @@
|
|||
:label (i18n/label :t/next)
|
||||
:count (pos? selected-contacts-count)}
|
||||
(i18n/label :t/group-chat)]
|
||||
[number-of-participants-disclaimer (- (dec max-participants) selected-contacts-count)]
|
||||
(when (seq contacts)
|
||||
[number-of-participants-disclaimer (- (dec constants/max-group-chat-participants) selected-contacts-count)])
|
||||
(if (seq contacts)
|
||||
[toggle-list contacts (partial group-toggle-contact (< selected-contacts-count (dec max-participants)))]
|
||||
[toggle-list contacts (partial group-toggle-contact (< selected-contacts-count (dec constants/max-group-chat-participants)))]
|
||||
[no-contacts])]))
|
||||
|
||||
;; Add participants to existing group chat
|
||||
|
@ -125,7 +125,7 @@
|
|||
:label (i18n/label :t/add)}
|
||||
name]
|
||||
|
||||
[number-of-participants-disclaimer (- max-participants current-participants-count)]
|
||||
[number-of-participants-disclaimer (- constants/max-group-chat-participants current-participants-count)]
|
||||
(when (seq contacts)
|
||||
[toggle-list contacts (partial group-toggle-participant (< (+ current-participants-count
|
||||
selected-contacts-count) max-participants))])])))
|
||||
selected-contacts-count) constants/max-group-chat-participants))])])))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.ui.screens.profile.group-chat.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.utils.platform :as platform]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.screens.profile.group-chat.styles :as styles]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.profile.components.styles :as profile.components.styles]
|
||||
|
@ -37,9 +38,9 @@
|
|||
:icon-opts {:color colors/blue
|
||||
:accessibility-label :done-button}}]])
|
||||
|
||||
(defn actions [admin? chat-id]
|
||||
(defn actions [allow-adding-members? chat-id]
|
||||
(concat
|
||||
(when admin?
|
||||
(when allow-adding-members?
|
||||
[{:label (i18n/label :add-members)
|
||||
:icon :icons/add
|
||||
:action #(re-frame/dispatch [:navigate-to :add-participants-toggle-list])}])
|
||||
|
@ -96,11 +97,14 @@
|
|||
(defview group-chat-profile []
|
||||
(letsubs [{:keys [admins chat-id] :as current-chat} [:chats/current-chat]
|
||||
editing? [:get :group-chat-profile/editing?]
|
||||
members [:contacts/current-chat-contacts]
|
||||
changed-chat [:get :group-chat-profile/profile]
|
||||
current-pk [:account/public-key]]
|
||||
(when current-chat
|
||||
(let [shown-chat (merge current-chat changed-chat)
|
||||
admin? (admins current-pk)]
|
||||
(let [shown-chat (merge current-chat changed-chat)
|
||||
admin? (admins current-pk)
|
||||
allow-adding-members? (and admin?
|
||||
(< (count members) constants/max-group-chat-participants))]
|
||||
[react/view profile.components.styles/profile
|
||||
[status-bar/status-bar]
|
||||
(if editing?
|
||||
|
@ -113,7 +117,7 @@
|
|||
:editing? editing?
|
||||
:allow-icon-change? false
|
||||
:on-change-text-event :group-chats.ui/name-changed}]
|
||||
[list/action-list (actions admin? chat-id)
|
||||
[list/action-list (actions allow-adding-members? chat-id)
|
||||
{:container-style styles/action-container
|
||||
:action-style styles/action
|
||||
:action-label-style styles/action-label
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
(is (not actual)))))
|
||||
(testing "an already existing chat"
|
||||
(let [cofx (assoc
|
||||
(group-chats/handle-membership-update {:now 0 :db {}} initial-message "payload" admin)
|
||||
(group-chats/handle-membership-update {:now 0 :db {:account/account {:public-key member-3}}} initial-message "payload" admin)
|
||||
:now 0)]
|
||||
(testing "the message has already been received"
|
||||
(let [actual (group-chats/handle-membership-update cofx initial-message "payload" admin)]
|
||||
|
@ -83,6 +83,47 @@
|
|||
(is (=
|
||||
(get-in cofx [:db :chats chat-id])
|
||||
(get-in actual [:db :chats chat-id]))))))
|
||||
(testing "a chat we have deleted"
|
||||
(let [after-leaving-cofx (-> (group-chats/handle-membership-update cofx
|
||||
{:chat-id chat-id
|
||||
:membership-updates [{:from member-1
|
||||
:events [{:type "chat-created"
|
||||
:clock-value 1
|
||||
:name "group-name"}
|
||||
{:type "admins-added"
|
||||
:clock-value 10
|
||||
:members [member-2]}
|
||||
{:type "admin-removed"
|
||||
:clock-value 11
|
||||
:member member-1}]}
|
||||
{:from member-3
|
||||
:events [{:type "member-removed"
|
||||
:clock-value 12
|
||||
:member member-3}]}]}
|
||||
"payload"
|
||||
member-3)
|
||||
(assoc-in [:db :chats chat-id :is-active] false))
|
||||
after-been-invited-again-cofx (group-chats/handle-membership-update (assoc after-leaving-cofx :now 0)
|
||||
{:chat-id chat-id
|
||||
:membership-updates [{:from member-1
|
||||
:events [{:type "chat-created"
|
||||
:clock-value 1
|
||||
:name "group-name"}
|
||||
{:type "admins-added"
|
||||
:clock-value 10
|
||||
:members [member-2]}
|
||||
{:type "admin-removed"
|
||||
:clock-value 11
|
||||
:member member-1}]}
|
||||
{:from member-2
|
||||
:events [{:type "members-added"
|
||||
:clock-value 13
|
||||
:members [member-3]}]}]}
|
||||
"payload"
|
||||
member-2)]
|
||||
|
||||
(testing "it sets the chat active after been invited again"
|
||||
(is (get-in after-been-invited-again-cofx [:db :chats chat-id :is-active])))))
|
||||
(testing "a new message comes in"
|
||||
(let [actual (group-chats/handle-membership-update cofx
|
||||
{:chat-id chat-id
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.test.transport.core
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.transport.core :as transport]
|
||||
[status-im.transport.message.core :as message]))
|
||||
|
@ -82,3 +83,71 @@
|
|||
(let [actual (message/receive-whisper-messages {:db {}} nil messages sig)]
|
||||
(testing "it add an fx for the message"
|
||||
(is (:chat-received-message/add-fx actual))))))
|
||||
|
||||
(deftest message-envelopes
|
||||
(let [chat-id "chat-id"
|
||||
from "from"
|
||||
message-id "message-id"
|
||||
initial-cofx {:db {:chats {chat-id {:messages {message-id {:from from}}}}}}]
|
||||
|
||||
(testing "a single envelope message"
|
||||
(let [cofx (message/set-message-envelope-hash initial-cofx chat-id message-id :message-type "hash-1" 1)]
|
||||
(testing "it sets the message-infos"
|
||||
(is (= {:chat-id chat-id
|
||||
:message-id message-id
|
||||
:message-type :message-type}
|
||||
(get-in cofx [:db :transport/message-envelopes "hash-1"]))))
|
||||
(testing "the message is sent"
|
||||
(is (= :sent
|
||||
|
||||
(get-in
|
||||
(message/update-envelope-status cofx "hash-1" :sent)
|
||||
[:db :chats chat-id :message-statuses message-id from :status]))))
|
||||
|
||||
(testing "the message is not sent"
|
||||
(is (= :not-sent
|
||||
(get-in
|
||||
(message/update-envelope-status cofx "hash-1" :not-sent)
|
||||
[:db :chats chat-id :message-statuses message-id from :status]))))))
|
||||
(testing "multi envelope message"
|
||||
(testing "only inserts"
|
||||
(let [cofx (fx/merge
|
||||
initial-cofx
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-1" 3)
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-2" 3)
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-3" 3))]
|
||||
(testing "it sets the message count"
|
||||
(is (= {:pending-confirmations 3}
|
||||
(get-in cofx [:db :transport/message-ids->confirmations message-id]))))))
|
||||
(testing "message sent correctly"
|
||||
(let [cofx (fx/merge
|
||||
initial-cofx
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-1" 3)
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-2" 3)
|
||||
(message/update-envelope-status "hash-1" :sent)
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-3" 3)
|
||||
(message/update-envelope-status "hash-2" :sent)
|
||||
(message/update-envelope-status "hash-3" :sent))]
|
||||
(testing "it removes the confirmations"
|
||||
(is (not (get-in cofx [:db :transport/message-ids->confirmations message-id]))))
|
||||
(testing "the message is sent"
|
||||
(is (= :sent
|
||||
(get-in
|
||||
cofx
|
||||
[:db :chats chat-id :message-statuses message-id from :status]))))))
|
||||
(testing "message not sent"
|
||||
(let [cofx (fx/merge
|
||||
initial-cofx
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-1" 3)
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-2" 3)
|
||||
(message/update-envelope-status "hash-1" :sent)
|
||||
(message/set-message-envelope-hash chat-id message-id :message-type "hash-3" 3)
|
||||
(message/update-envelope-status "hash-2" :not-sent)
|
||||
(message/update-envelope-status "hash-3" :sent))]
|
||||
(testing "it removes the confirmations"
|
||||
(is (not (get-in cofx [:db :transport/message-ids->confirmations message-id]))))
|
||||
(testing "the message is sent"
|
||||
(is (= :not-sent
|
||||
(get-in
|
||||
cofx
|
||||
[:db :chats chat-id :message-statuses message-id from :status])))))))))
|
||||
|
|
Loading…
Reference in New Issue