Add joining of group chats
Members will now have to explicitly join a group chat to start receiving messages from it. Messages are still sent to users who have not joined for backward compatibility. Group updates are unaffected.
This commit is contained in:
parent
a52f3d4d08
commit
881691fbc3
|
@ -19,15 +19,27 @@
|
||||||
[status-im.utils.priority-map :refer [empty-message-map]]
|
[status-im.utils.priority-map :refer [empty-message-map]]
|
||||||
[status-im.utils.utils :as utils]))
|
[status-im.utils.utils :as utils]))
|
||||||
|
|
||||||
(defn multi-user-chat? [cofx chat-id]
|
(defn- get-chat [cofx chat-id]
|
||||||
(get-in cofx [:db :chats chat-id :group-chat]))
|
(get-in cofx [:db :chats chat-id]))
|
||||||
|
|
||||||
(defn group-chat? [cofx chat-id]
|
(defn multi-user-chat?
|
||||||
(and (multi-user-chat? cofx chat-id)
|
([chat]
|
||||||
(not (get-in cofx [:db :chats chat-id :public?]))))
|
(:group-chat chat))
|
||||||
|
([cofx chat-id]
|
||||||
|
(multi-user-chat? (get-chat cofx chat-id))))
|
||||||
|
|
||||||
(defn public-chat? [cofx chat-id]
|
(defn public-chat?
|
||||||
(get-in cofx [:db :chats chat-id :public?]))
|
([chat]
|
||||||
|
(:public? chat))
|
||||||
|
([cofx chat-id]
|
||||||
|
(public-chat? (get-chat cofx chat-id))))
|
||||||
|
|
||||||
|
(defn group-chat?
|
||||||
|
([chat]
|
||||||
|
(and (multi-user-chat? chat)
|
||||||
|
(not (public-chat? chat))))
|
||||||
|
([cofx chat-id]
|
||||||
|
(group-chat? (get-chat cofx chat-id))))
|
||||||
|
|
||||||
(defn set-chat-ui-props
|
(defn set-chat-ui-props
|
||||||
"Updates ui-props in active chat by merging provided kvs into them"
|
"Updates ui-props in active chat by merging provided kvs into them"
|
||||||
|
|
|
@ -252,7 +252,7 @@
|
||||||
(cond
|
(cond
|
||||||
(and (= :group-user-message message-type)
|
(and (= :group-user-message message-type)
|
||||||
(and (get-in cofx [:db :chats chat-id :contacts from])
|
(and (get-in cofx [:db :chats chat-id :contacts from])
|
||||||
(get-in cofx [:db :chats chat-id :contacts (accounts.db/current-public-key cofx)]))) chat-id
|
(get-in cofx [:db :chats chat-id :members-joined (accounts.db/current-public-key cofx)]))) chat-id
|
||||||
(and (= :public-group-user-message message-type)
|
(and (= :public-group-user-message message-type)
|
||||||
(get-in cofx [:db :chats chat-id :public?])) chat-id
|
(get-in cofx [:db :chats chat-id :public?])) chat-id
|
||||||
(and (= :user-message message-type)
|
(and (= :user-message message-type)
|
||||||
|
|
|
@ -1254,6 +1254,11 @@
|
||||||
(fn [cofx [_ chat-id]]
|
(fn [cofx [_ chat-id]]
|
||||||
(group-chats/remove cofx chat-id)))
|
(group-chats/remove cofx chat-id)))
|
||||||
|
|
||||||
|
(handlers/register-handler-fx
|
||||||
|
:group-chats.ui/join-pressed
|
||||||
|
(fn [cofx [_ chat-id]]
|
||||||
|
(group-chats/join-chat cofx chat-id)))
|
||||||
|
|
||||||
(handlers/register-handler-fx
|
(handlers/register-handler-fx
|
||||||
:group-chats.callback/sign-success
|
:group-chats.callback/sign-success
|
||||||
[(re-frame/inject-cofx :random-guid-generator)]
|
[(re-frame/inject-cofx :random-guid-generator)]
|
||||||
|
|
|
@ -84,6 +84,8 @@
|
||||||
"name-changed" (and (admins from)
|
"name-changed" (and (admins from)
|
||||||
(not (string/blank? (:name new-event))))
|
(not (string/blank? (:name new-event))))
|
||||||
"members-added" (admins from)
|
"members-added" (admins from)
|
||||||
|
"member-joined" (and (contacts member)
|
||||||
|
(= from member))
|
||||||
"admins-added" (and (admins from)
|
"admins-added" (and (admins from)
|
||||||
(clojure.set/subset? members contacts))
|
(clojure.set/subset? members contacts))
|
||||||
"member-removed" (or
|
"member-removed" (or
|
||||||
|
@ -168,6 +170,11 @@
|
||||||
:clock-value (utils.clocks/send last-clock-value)
|
:clock-value (utils.clocks/send last-clock-value)
|
||||||
:members members})
|
:members members})
|
||||||
|
|
||||||
|
(defn- member-joined-event [last-clock-value member]
|
||||||
|
{:type "member-joined"
|
||||||
|
:clock-value (utils.clocks/send last-clock-value)
|
||||||
|
:member member})
|
||||||
|
|
||||||
(fx/defn create
|
(fx/defn create
|
||||||
"Format group update message and sign membership"
|
"Format group update message and sign membership"
|
||||||
[{:keys [db random-guid-generator] :as cofx} group-name]
|
[{:keys [db random-guid-generator] :as cofx} group-name]
|
||||||
|
@ -202,6 +209,20 @@
|
||||||
:from my-public-key
|
:from my-public-key
|
||||||
:events [remove-event]}})))
|
:events [remove-event]}})))
|
||||||
|
|
||||||
|
(fx/defn join-chat
|
||||||
|
"Format group update message and sign membership"
|
||||||
|
[{:keys [db] :as cofx} chat-id]
|
||||||
|
(let [my-public-key (accounts.db/current-public-key cofx)
|
||||||
|
last-clock-value (get-last-clock-value cofx chat-id)
|
||||||
|
chat (get-in cofx [:db :chats chat-id])
|
||||||
|
event (member-joined-event last-clock-value my-public-key)]
|
||||||
|
(when (valid-event? chat (assoc event
|
||||||
|
:from
|
||||||
|
my-public-key))
|
||||||
|
{:group-chats/sign-membership {:chat-id chat-id
|
||||||
|
:from my-public-key
|
||||||
|
:events [event]}})))
|
||||||
|
|
||||||
(fx/defn make-admin
|
(fx/defn make-admin
|
||||||
"Format group update with make admin message and sign membership"
|
"Format group update with make admin message and sign membership"
|
||||||
[{:keys [db] :as cofx} chat-id member]
|
[{:keys [db] :as cofx} chat-id member]
|
||||||
|
@ -284,6 +305,7 @@
|
||||||
"chat-created" {:name name
|
"chat-created" {:name name
|
||||||
:created-at clock-value
|
:created-at clock-value
|
||||||
:admins #{from}
|
:admins #{from}
|
||||||
|
:members-joined #{from}
|
||||||
:contacts #{from}}
|
:contacts #{from}}
|
||||||
"name-changed" (assoc group
|
"name-changed" (assoc group
|
||||||
:name name
|
:name name
|
||||||
|
@ -292,12 +314,16 @@
|
||||||
"members-added" (as-> group $
|
"members-added" (as-> group $
|
||||||
(update $ :contacts clojure.set/union (set members))
|
(update $ :contacts clojure.set/union (set members))
|
||||||
(reduce (fn [acc member] (assoc-in acc [member :added] clock-value)) $ members))
|
(reduce (fn [acc member] (assoc-in acc [member :added] clock-value)) $ members))
|
||||||
|
"member-joined" (-> group
|
||||||
|
(update :members-joined conj member)
|
||||||
|
(assoc-in [member :joined] clock-value))
|
||||||
"admins-added" (as-> group $
|
"admins-added" (as-> group $
|
||||||
(update $ :admins clojure.set/union (set members))
|
(update $ :admins clojure.set/union (set members))
|
||||||
(reduce (fn [acc member] (assoc-in acc [member :admin-added] clock-value)) $ members))
|
(reduce (fn [acc member] (assoc-in acc [member :admin-added] clock-value)) $ members))
|
||||||
"member-removed" (-> group
|
"member-removed" (-> group
|
||||||
(update :contacts disj member)
|
(update :contacts disj member)
|
||||||
(update :admins disj member)
|
(update :admins disj member)
|
||||||
|
(update :members-joined disj member)
|
||||||
(assoc-in [member :removed] clock-value))
|
(assoc-in [member :removed] clock-value))
|
||||||
"admin-removed" (-> group
|
"admin-removed" (-> group
|
||||||
(update :admins disj member)
|
(update :admins disj member)
|
||||||
|
@ -312,6 +338,7 @@
|
||||||
(reduce
|
(reduce
|
||||||
process-event
|
process-event
|
||||||
{:admins #{}
|
{:admins #{}
|
||||||
|
:members-joined #{}
|
||||||
:contacts #{}})))
|
:contacts #{}})))
|
||||||
|
|
||||||
(defn membership-changes->system-messages [cofx
|
(defn membership-changes->system-messages [cofx
|
||||||
|
@ -320,6 +347,7 @@
|
||||||
chat-name
|
chat-name
|
||||||
creator
|
creator
|
||||||
members-added
|
members-added
|
||||||
|
members-joined
|
||||||
admins-added
|
admins-added
|
||||||
name-changed?
|
name-changed?
|
||||||
members-removed]}]
|
members-removed]}]
|
||||||
|
@ -337,6 +365,9 @@
|
||||||
contacts-added (map
|
contacts-added (map
|
||||||
get-contact
|
get-contact
|
||||||
(disj members-added creator))
|
(disj members-added creator))
|
||||||
|
contacts-joined (map
|
||||||
|
get-contact
|
||||||
|
(disj members-joined creator))
|
||||||
contacts-removed (map
|
contacts-removed (map
|
||||||
get-contact
|
get-contact
|
||||||
members-removed)]
|
members-removed)]
|
||||||
|
@ -356,6 +387,11 @@
|
||||||
(i18n/label :t/group-chat-member-added {:member (:name %)})
|
(i18n/label :t/group-chat-member-added {:member (:name %)})
|
||||||
(get-in clock-values [(:public-key %) :added]))
|
(get-in clock-values [(:public-key %) :added]))
|
||||||
contacts-added))
|
contacts-added))
|
||||||
|
(seq members-joined) (concat (map #(format-message
|
||||||
|
%
|
||||||
|
(i18n/label :t/group-chat-member-joined {:member (:name %)})
|
||||||
|
(get-in clock-values [(:public-key %) :joined]))
|
||||||
|
contacts-joined))
|
||||||
(seq admins-added) (concat (map #(format-message
|
(seq admins-added) (concat (map #(format-message
|
||||||
%
|
%
|
||||||
(i18n/label :t/group-chat-admin-added {:member (:name %)})
|
(i18n/label :t/group-chat-admin-added {:member (:name %)})
|
||||||
|
@ -373,6 +409,7 @@
|
||||||
name-changed? (and (seq previous-chat)
|
name-changed? (and (seq previous-chat)
|
||||||
(not= (:name previous-chat) (:name current-chat)))
|
(not= (:name previous-chat) (:name current-chat)))
|
||||||
members-added (clojure.set/difference (:contacts current-chat) (:contacts previous-chat))
|
members-added (clojure.set/difference (:contacts current-chat) (:contacts previous-chat))
|
||||||
|
members-joined (clojure.set/difference (:members-joined current-chat) (:members-joined previous-chat))
|
||||||
members-removed (clojure.set/difference (:contacts previous-chat) (:contacts current-chat))
|
members-removed (clojure.set/difference (:contacts previous-chat) (:contacts current-chat))
|
||||||
admins-added (clojure.set/difference (:admins current-chat) (:admins previous-chat))
|
admins-added (clojure.set/difference (:admins current-chat) (:admins previous-chat))
|
||||||
membership-changes (cond-> {:chat-id chat-id
|
membership-changes (cond-> {:chat-id chat-id
|
||||||
|
@ -380,12 +417,14 @@
|
||||||
:chat-name (:name current-chat)
|
:chat-name (:name current-chat)
|
||||||
:admins-added admins-added
|
:admins-added admins-added
|
||||||
:members-added members-added
|
:members-added members-added
|
||||||
|
:members-joined members-joined
|
||||||
:members-removed members-removed}
|
:members-removed members-removed}
|
||||||
(nil? previous-chat)
|
(nil? previous-chat)
|
||||||
(assoc :creator (extract-creator current-chat)))]
|
(assoc :creator (extract-creator current-chat)))]
|
||||||
(when (or name-changed?
|
(when (or name-changed?
|
||||||
(seq admins-added)
|
(seq admins-added)
|
||||||
(seq members-added)
|
(seq members-added)
|
||||||
|
(seq members-joined)
|
||||||
(seq members-removed))
|
(seq members-removed))
|
||||||
(->> membership-changes
|
(->> membership-changes
|
||||||
(membership-changes->system-messages cofx clock-values)
|
(membership-changes->system-messages cofx clock-values)
|
||||||
|
@ -399,6 +438,21 @@
|
||||||
(map #(assoc % :from from) events))
|
(map #(assoc % :from from) events))
|
||||||
all-updates))
|
all-updates))
|
||||||
|
|
||||||
|
(defn joined? [my-public-key {:keys [members-joined]}]
|
||||||
|
(contains? members-joined my-public-key))
|
||||||
|
|
||||||
|
(defn invited? [my-public-key {:keys [contacts]}]
|
||||||
|
(contains? contacts my-public-key))
|
||||||
|
|
||||||
|
(defn get-inviter-pk [my-public-key {:keys [membership-updates] :as chat}]
|
||||||
|
(->> membership-updates
|
||||||
|
unwrap-events
|
||||||
|
(keep (fn [{:keys [from type members]}]
|
||||||
|
(when (and (= type "members-added")
|
||||||
|
(contains? members my-public-key))
|
||||||
|
from)))
|
||||||
|
last))
|
||||||
|
|
||||||
(fx/defn handle-membership-update
|
(fx/defn handle-membership-update
|
||||||
"Upsert chat and receive message if valid"
|
"Upsert chat and receive message if valid"
|
||||||
;; Care needs to be taken here as chat-id is not coming from a whisper filter
|
;; Care needs to be taken here as chat-id is not coming from a whisper filter
|
||||||
|
@ -423,6 +477,7 @@
|
||||||
:group-chat true
|
:group-chat true
|
||||||
:membership-updates (into [] all-updates)
|
:membership-updates (into [] all-updates)
|
||||||
:admins (:admins new-group)
|
:admins (:admins new-group)
|
||||||
|
:members-joined (:members-joined new-group)
|
||||||
:contacts (:contacts new-group)})
|
:contacts (:contacts new-group)})
|
||||||
(add-system-messages chat-id previous-chat new-group)
|
(add-system-messages chat-id previous-chat new-group)
|
||||||
#(when (and message
|
#(when (and message
|
||||||
|
|
|
@ -234,3 +234,6 @@
|
||||||
|
|
||||||
(def empty-chat-text-name
|
(def empty-chat-text-name
|
||||||
{:color colors/black})
|
{:color colors/black})
|
||||||
|
|
||||||
|
(def join-button
|
||||||
|
{:margin-bottom 5})
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.contact.core :as models.contact]
|
[status-im.contact.core :as models.contact]
|
||||||
|
[status-im.chat.models :as models.chat]
|
||||||
|
[status-im.group-chats.core :as models.group-chats]
|
||||||
[status-im.ui.screens.chat.styles.main :as style]
|
[status-im.ui.screens.chat.styles.main :as style]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.ui.screens.chat.input.input :as input]
|
[status-im.ui.screens.chat.input.input :as input]
|
||||||
|
@ -14,6 +16,7 @@
|
||||||
[status-im.ui.screens.chat.message.datemark :as message-datemark]
|
[status-im.ui.screens.chat.message.datemark :as message-datemark]
|
||||||
[status-im.ui.screens.chat.toolbar-content :as toolbar-content]
|
[status-im.ui.screens.chat.toolbar-content :as toolbar-content]
|
||||||
[status-im.ui.components.animation :as animation]
|
[status-im.ui.components.animation :as animation]
|
||||||
|
[status-im.ui.components.button.view :as buttons]
|
||||||
[status-im.ui.components.list.views :as list]
|
[status-im.ui.components.list.views :as list]
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
|
@ -114,7 +117,21 @@
|
||||||
[react/text {:style style/empty-chat-text-name} (:name contact)]]
|
[react/text {:style style/empty-chat-text-name} (:name contact)]]
|
||||||
(i18n/label :t/empty-chat-description))]])))
|
(i18n/label :t/empty-chat-description))]])))
|
||||||
|
|
||||||
(defview messages-view [chat group-chat modal?]
|
(defn join-chat-button [chat-id]
|
||||||
|
[buttons/primary-button {:style style/join-button
|
||||||
|
:on-press #(re-frame/dispatch [:group-chats.ui/join-pressed chat-id])}
|
||||||
|
(i18n/label :t/join-group-chat)])
|
||||||
|
|
||||||
|
(defview group-chat-join-section [my-public-key {:keys [name chat-id] :as chat}]
|
||||||
|
(letsubs [contact [:contacts/contact-by-identity (models.group-chats/get-inviter-pk my-public-key chat)]]
|
||||||
|
[react/view style/empty-chat-container
|
||||||
|
[join-chat-button chat-id]
|
||||||
|
[react/text {:style style/empty-chat-text}
|
||||||
|
[react/text style/empty-chat-container-one-to-one
|
||||||
|
(i18n/label :t/join-group-chat-description {:username (:name contact)
|
||||||
|
:group-name name})]]]))
|
||||||
|
|
||||||
|
(defview messages-view [{:keys [group-chat] :as chat} modal?]
|
||||||
(letsubs [messages [:chats/current-chat-messages-stream]
|
(letsubs [messages [:chats/current-chat-messages-stream]
|
||||||
current-public-key [:account/public-key]]
|
current-public-key [:account/public-key]]
|
||||||
{:component-did-mount
|
{:component-did-mount
|
||||||
|
@ -124,9 +141,18 @@
|
||||||
(re-frame/dispatch [:chat.ui/set-chat-ui-props
|
(re-frame/dispatch [:chat.ui/set-chat-ui-props
|
||||||
{:messages-focused? true
|
{:messages-focused? true
|
||||||
:input-focused? false}]))}
|
:input-focused? false}]))}
|
||||||
(if (and (empty? messages)
|
(cond
|
||||||
|
|
||||||
|
(and (models.chat/group-chat? chat)
|
||||||
|
(models.group-chats/invited? current-public-key chat)
|
||||||
|
(not (models.group-chats/joined? current-public-key chat)))
|
||||||
|
[group-chat-join-section current-public-key chat]
|
||||||
|
|
||||||
|
(and (empty? messages)
|
||||||
(:messages-initialized? chat))
|
(:messages-initialized? chat))
|
||||||
[empty-chat-container chat]
|
[empty-chat-container chat]
|
||||||
|
|
||||||
|
:else
|
||||||
[list/flat-list {:data messages
|
[list/flat-list {:data messages
|
||||||
:key-fn #(or (:message-id %) (:value %))
|
:key-fn #(or (:message-id %) (:value %))
|
||||||
:render-fn (fn [message]
|
:render-fn (fn [message]
|
||||||
|
@ -139,12 +165,17 @@
|
||||||
:enableEmptySections true
|
:enableEmptySections true
|
||||||
:keyboardShouldPersistTaps :handled}])))
|
:keyboardShouldPersistTaps :handled}])))
|
||||||
|
|
||||||
(defview messages-view-wrapper [group-chat modal?]
|
(defview messages-view-wrapper [modal?]
|
||||||
(letsubs [chat [:chats/current-chat]]
|
(letsubs [chat [:chats/current-chat]]
|
||||||
[messages-view chat group-chat modal?]))
|
[messages-view chat modal?]))
|
||||||
|
|
||||||
|
(defn show-input-container? [my-public-key current-chat]
|
||||||
|
(or (not (models.chat/group-chat? current-chat))
|
||||||
|
(models.group-chats/joined? my-public-key current-chat)))
|
||||||
|
|
||||||
(defview chat-root [modal?]
|
(defview chat-root [modal?]
|
||||||
(letsubs [{:keys [group-chat public?]} [:chats/current-chat]
|
(letsubs [{:keys [public?] :as current-chat} [:chats/current-chat]
|
||||||
|
my-public-key [:account/public-key]
|
||||||
show-bottom-info? [:chats/current-chat-ui-prop :show-bottom-info?]
|
show-bottom-info? [:chats/current-chat-ui-prop :show-bottom-info?]
|
||||||
show-message-options? [:chats/current-chat-ui-prop :show-message-options?]
|
show-message-options? [:chats/current-chat-ui-prop :show-message-options?]
|
||||||
current-view [:get :view-id]]
|
current-view [:get :view-id]]
|
||||||
|
@ -160,9 +191,10 @@
|
||||||
[chat-toolbar public? modal?]
|
[chat-toolbar public? modal?]
|
||||||
(if (or (= :chat current-view) modal?)
|
(if (or (= :chat current-view) modal?)
|
||||||
[messages-view-animation
|
[messages-view-animation
|
||||||
[messages-view-wrapper group-chat modal?]]
|
[messages-view-wrapper modal?]]
|
||||||
[react/view style/message-view-preview])
|
[react/view style/message-view-preview])
|
||||||
[input/container]
|
(when (show-input-container? my-public-key current-chat)
|
||||||
|
[input/container])
|
||||||
(when show-bottom-info?
|
(when show-bottom-info?
|
||||||
[bottom-info/bottom-info-view])
|
[bottom-info/bottom-info-view])
|
||||||
(when show-message-options?
|
(when show-message-options?
|
||||||
|
|
|
@ -66,11 +66,12 @@
|
||||||
(is (= :sent status)))))))
|
(is (= :sent status)))))))
|
||||||
|
|
||||||
(deftest receive-group-chats
|
(deftest receive-group-chats
|
||||||
(let [cofx {:db {:chats {"chat-id" {:contacts #{"present" "a"}}}
|
(let [cofx {:db {:chats {"chat-id" {:contacts #{"present"}
|
||||||
|
:members-joined #{"a"}}}
|
||||||
:account/account {:public-key "a"}
|
:account/account {:public-key "a"}
|
||||||
:current-chat-id "chat-id"
|
:current-chat-id "chat-id"
|
||||||
:view-id :chat}}
|
:view-id :chat}}
|
||||||
cofx-without-member (update-in cofx [:db :chats "chat-id" :contacts] disj "a")
|
cofx-without-member (update-in cofx [:db :chats "chat-id" :members-joined] disj "a")
|
||||||
valid-message {:chat-id "chat-id"
|
valid-message {:chat-id "chat-id"
|
||||||
:from "present"
|
:from "present"
|
||||||
:message-type :group-user-message
|
:message-type :group-user-message
|
||||||
|
|
|
@ -146,13 +146,19 @@
|
||||||
{:type "members-added"
|
{:type "members-added"
|
||||||
:clock-value 3
|
:clock-value 3
|
||||||
:from "2"
|
:from "2"
|
||||||
:members ["3"]}]
|
:members ["3"]}
|
||||||
|
{:type "member-joined"
|
||||||
|
:clock-value 4
|
||||||
|
:from "3"
|
||||||
|
:member "3"}]
|
||||||
expected {:name "chat-name"
|
expected {:name "chat-name"
|
||||||
:created-at 0
|
:created-at 0
|
||||||
"2" {:added 1
|
"2" {:added 1
|
||||||
:admin-added 2}
|
:admin-added 2}
|
||||||
"3" {:added 3}
|
"3" {:added 3
|
||||||
|
:joined 4}
|
||||||
:admins #{"1" "2"}
|
:admins #{"1" "2"}
|
||||||
|
:members-joined #{"1" "3"}
|
||||||
:contacts #{"1" "2" "3"}}]
|
:contacts #{"1" "2" "3"}}]
|
||||||
(is (= expected (group-chats/build-group events)))))
|
(is (= expected (group-chats/build-group events)))))
|
||||||
(testing "adds and removes"
|
(testing "adds and removes"
|
||||||
|
@ -164,25 +170,31 @@
|
||||||
:clock-value 1
|
:clock-value 1
|
||||||
:from "1"
|
:from "1"
|
||||||
:members ["2"]}
|
:members ["2"]}
|
||||||
{:type "admins-added"
|
{:type "member-joined"
|
||||||
:clock-value 2
|
|
||||||
:from "1"
|
|
||||||
:members ["2"]}
|
|
||||||
{:type "admin-removed"
|
|
||||||
:clock-value 3
|
:clock-value 3
|
||||||
:from "2"
|
:from "2"
|
||||||
:member "2"}
|
:member "2"}
|
||||||
{:type "member-removed"
|
{:type "admins-added"
|
||||||
:clock-value 4
|
:clock-value 4
|
||||||
|
:from "1"
|
||||||
|
:members ["2"]}
|
||||||
|
{:type "admin-removed"
|
||||||
|
:clock-value 5
|
||||||
|
:from "2"
|
||||||
|
:member "2"}
|
||||||
|
{:type "member-removed"
|
||||||
|
:clock-value 6
|
||||||
:from "2"
|
:from "2"
|
||||||
:member "2"}]
|
:member "2"}]
|
||||||
expected {:name "chat-name"
|
expected {:name "chat-name"
|
||||||
:created-at 0
|
:created-at 0
|
||||||
"2" {:added 1
|
"2" {:added 1
|
||||||
:admin-added 2
|
:joined 3
|
||||||
:admin-removed 3
|
:admin-added 4
|
||||||
:removed 4}
|
:admin-removed 5
|
||||||
|
:removed 6}
|
||||||
:admins #{"1"}
|
:admins #{"1"}
|
||||||
|
:members-joined #{"1"}
|
||||||
:contacts #{"1"}}]
|
:contacts #{"1"}}]
|
||||||
(is (= expected (group-chats/build-group events)))))
|
(is (= expected (group-chats/build-group events)))))
|
||||||
(testing "an admin removing themselves"
|
(testing "an admin removing themselves"
|
||||||
|
@ -204,6 +216,7 @@
|
||||||
:member "2"}]
|
:member "2"}]
|
||||||
expected {:name "chat-name"
|
expected {:name "chat-name"
|
||||||
:created-at 0
|
:created-at 0
|
||||||
|
:members-joined #{"1"}
|
||||||
"2" {:added 1
|
"2" {:added 1
|
||||||
:admin-added 2
|
:admin-added 2
|
||||||
:removed 3}
|
:removed 3}
|
||||||
|
@ -229,6 +242,7 @@
|
||||||
:name "new-name"}]
|
:name "new-name"}]
|
||||||
expected {:name "new-name"
|
expected {:name "new-name"
|
||||||
:created-at 0
|
:created-at 0
|
||||||
|
:members-joined #{"1"}
|
||||||
:name-changed-by "2"
|
:name-changed-by "2"
|
||||||
:name-changed-at 3
|
:name-changed-at 3
|
||||||
"2" {:added 1
|
"2" {:added 1
|
||||||
|
@ -249,6 +263,10 @@
|
||||||
:clock-value 2
|
:clock-value 2
|
||||||
:from "1"
|
:from "1"
|
||||||
:members ["2"]}
|
:members ["2"]}
|
||||||
|
{:type "member-joined" ; non-invited user joining
|
||||||
|
:clock-value 2
|
||||||
|
:from "non-invited"
|
||||||
|
:member "non-invited"}
|
||||||
{:type "admins-added"
|
{:type "admins-added"
|
||||||
:clock-value 3
|
:clock-value 3
|
||||||
:from "1"
|
:from "1"
|
||||||
|
@ -261,15 +279,40 @@
|
||||||
:clock-value 5
|
:clock-value 5
|
||||||
:from "1"
|
:from "1"
|
||||||
:member "2"}
|
:member "2"}
|
||||||
|
{:type "member-joined"
|
||||||
|
:clock-value 5
|
||||||
|
:from "2"
|
||||||
|
:member "2"}
|
||||||
{:type "member-removed" ; can't remove an admin from the group
|
{:type "member-removed" ; can't remove an admin from the group
|
||||||
:clock-value 6
|
:clock-value 6
|
||||||
:from "1"
|
:from "1"
|
||||||
:member "2"}]
|
:member "2"}
|
||||||
|
{:type "members-added"
|
||||||
|
:clock-value 7
|
||||||
|
:from "2"
|
||||||
|
:members ["4"]}
|
||||||
|
{:type "member-joined"
|
||||||
|
:clock-value 8
|
||||||
|
:from "4"
|
||||||
|
:member "4"}
|
||||||
|
{:type "member-removed"
|
||||||
|
:clock-value 9
|
||||||
|
:from "1"
|
||||||
|
:member "4"}
|
||||||
|
{:type "member-joined" ; join after being removed
|
||||||
|
:clock-value 10
|
||||||
|
:from "4"
|
||||||
|
:member "4"}]
|
||||||
expected {:name "chat-name"
|
expected {:name "chat-name"
|
||||||
|
:members-joined #{"1" "2"}
|
||||||
:created-at 0
|
:created-at 0
|
||||||
"2" {:added 2
|
"2" {:added 2
|
||||||
:admin-added 3}
|
:admin-added 3
|
||||||
|
:joined 5}
|
||||||
"3" {:added 4}
|
"3" {:added 4}
|
||||||
|
"4" {:added 7
|
||||||
|
:joined 8
|
||||||
|
:removed 9}
|
||||||
:admins #{"1" "2"}
|
:admins #{"1" "2"}
|
||||||
:contacts #{"1" "2" "3"}}]
|
:contacts #{"1" "2" "3"}}]
|
||||||
(is (= expected (group-chats/build-group events)))))
|
(is (= expected (group-chats/build-group events)))))
|
||||||
|
@ -292,6 +335,7 @@
|
||||||
:members ["3"]}]
|
:members ["3"]}]
|
||||||
expected {:name "chat-name"
|
expected {:name "chat-name"
|
||||||
:created-at 0
|
:created-at 0
|
||||||
|
:members-joined #{"1"}
|
||||||
"2" {:added 1
|
"2" {:added 1
|
||||||
:admin-added 2}
|
:admin-added 2}
|
||||||
"3" {:added 3}
|
"3" {:added 3}
|
||||||
|
|
|
@ -38,10 +38,13 @@
|
||||||
"other": "You can select {{count}} more participants"
|
"other": "You can select {{count}} more participants"
|
||||||
},
|
},
|
||||||
"no-more-participants-available": "You can't add anymore participants",
|
"no-more-participants-available": "You can't add anymore participants",
|
||||||
|
"join-group-chat-description": "{{username}} invited you to join the group {{group-name}}",
|
||||||
|
"join-group-chat": "Join chat",
|
||||||
"group-chat-created": "*{{member}}* created the group *{{name}}*",
|
"group-chat-created": "*{{member}}* created the group *{{name}}*",
|
||||||
"group-chat-admin": "Admin",
|
"group-chat-admin": "Admin",
|
||||||
"group-chat-name-changed": "*{{member}}* changed the group's name to *{{name}}*",
|
"group-chat-name-changed": "*{{member}}* changed the group's name to *{{name}}*",
|
||||||
"group-chat-member-added": "*{{member}}* joined the group",
|
"group-chat-member-added": "*{{member}}* has been invited",
|
||||||
|
"group-chat-member-joined": "*{{member}}* has joined the group",
|
||||||
"group-chat-member-removed": "*{{member}}* left the group",
|
"group-chat-member-removed": "*{{member}}* left the group",
|
||||||
"group-chat-admin-added": "*{{member}}* has been made admin",
|
"group-chat-admin-added": "*{{member}}* has been made admin",
|
||||||
"group-chat-no-contacts": "You don't have any contacts yet.\nInvite your friends to start chatting",
|
"group-chat-no-contacts": "You don't have any contacts yet.\nInvite your friends to start chatting",
|
||||||
|
|
Loading…
Reference in New Issue