Skip to content

Commit

Permalink
Merge pull request #11876 from nextcloud/fix/11484/system-message-gro…
Browse files Browse the repository at this point in the history
…uping

fix(MessagesSystemGroup): collapse `actor removed` messages, collapse previously open groups with unread marker
  • Loading branch information
Antreesy authored Mar 25, 2024
2 parents 20defcf + 1f82203 commit 09fadad
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 12 deletions.
22 changes: 21 additions & 1 deletion src/components/MessagesList/MessagesGroup/Message/Message.vue
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,17 @@ export default {
type: Boolean,
default: undefined,
},
/**
* Specifies if the message is inside a collapsed group.
*/
isCollapsedSystemMessage: {
type: Boolean,
default: false,
},
lastCollapsedMessageId: {
type: [String, Number],
default: 0,
},
/**
* The type of the message.
*/
Expand Down Expand Up @@ -329,8 +340,17 @@ export default {
return !this.nextMessageId || this.id === this.conversation?.lastMessage?.id
},

visualLastLastReadMessageId() {
return this.$store.getters.getVisualLastReadMessageId(this.token)
},

isLastReadMessage() {
return !this.isLastMessage && this.id === this.$store.getters.getVisualLastReadMessageId(this.token)
if (this.isLastMessage) {
return false
}
return (!this.isCollapsedSystemMessage && this.id === this.visualLastLastReadMessageId)
|| (this.isCollapsedSystemMessage && this.id === this.visualLastLastReadMessageId && this.id !== this.lastCollapsedMessageId)
|| (this.isCombinedSystemMessage && this.lastCollapsedMessageId === this.visualLastLastReadMessageId)
},

isSystemMessage() {
Expand Down
29 changes: 20 additions & 9 deletions src/components/MessagesList/MessagesGroup/MessagesSystemGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
:is-combined-system-message-collapsed="messagesCollapsed.collapsed"
:next-message-id="getNextMessageId(messagesCollapsed.messages.at(-1))"
:previous-message-id="getPrevMessageId(messagesCollapsed.messages.at(0))"
:last-collapsed-message-id="messagesCollapsed.lastId"
@toggle-combined-system-message="toggleCollapsed(messagesCollapsed)" />
</ul>
<ul v-show="messagesCollapsed.messages?.length === 1 || !messagesCollapsed.collapsed"
Expand All @@ -41,6 +42,8 @@
:key="message.id"
v-bind="message"
:token="token"
is-collapsed-system-message
:last-collapsed-message-id="messagesCollapsed.lastId"
:next-message-id="getNextMessageId(message)"
:previous-message-id="getPrevMessageId(message)" />
</ul>
Expand Down Expand Up @@ -153,6 +156,14 @@ export default {
return 'user_added'
}

// Group users removed by one actor
if (message1.systemMessage === 'user_removed'
&& message1.systemMessage === message2.systemMessage
&& message1.actorId === message2.actorId
&& message1.actorType === message2.actorType) {
return 'user_removed'
}

// Group users reconnected in a minute
if (message1.systemMessage === 'call_joined'
&& message2.systemMessage === 'call_left'
Expand Down Expand Up @@ -194,30 +205,30 @@ export default {
let lastMessage = null
let forceNextGroup = false
for (const message of messages) {
const isLastRead = message.id === this.lastReadMessageId
const groupingType = this.messagesShouldBeGrouped(message, lastMessage)
if (!groupingType || forceNextGroup) {
groups.push({ id: message.id, messages: [message], type: '', collapsed: this.groupIsCollapsed[message.id] ?? !isLastRead })
groups.push({ id: message.id, lastId: message.id, messages: [message], type: '', collapsed: this.groupIsCollapsed[message.id] ?? true })
forceNextGroup = false
} else {
if (groupingType === 'call_reconnected') {
groups.push({ id: message.id, messages: [groups.at(-1).messages.pop()], type: '', collapsed: this.groupIsCollapsed[message.id] ?? !isLastRead })
groups.push({ id: message.id, lastId: message.id, messages: [groups.at(-1).messages.pop()], type: '', collapsed: this.groupIsCollapsed[message.id] ?? true })
groups.at(-1).lastId = groups.at(-1).messages.at(-1).id
forceNextGroup = true
}
groups.at(-1).messages.push(message)
groups.at(-1).lastId = message.id
groups.at(-1).type = groupingType
if (isLastRead) {

// Check if last read message is hidden inside the collapsed group, and open it, if so.
// Otherwise, combined system message will show a marker
const isLastReadInsideGroup = this.lastReadMessageId >= groups.at(-1).id && this.lastReadMessageId < groups.at(-1).lastId
if (isLastReadInsideGroup) {
groups.at(-1).collapsed = false
}
}
lastMessage = message
}

groups.forEach(group => {
if (this.groupIsCollapsed[group.id] === undefined) {
this.groupIsCollapsed[group.id] = group.collapsed
}
})
return groups
},

Expand Down
4 changes: 2 additions & 2 deletions src/components/MessagesList/MessagesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,10 @@ export default {
},

softUpdateAuthorGroups(oldGroups, newGroups, dateTimestamp) {
const oldKeys = Object.keys(oldGroups)
Object.entries(newGroups).forEach(([id, newGroup]) => {
if (!oldGroups[id]) {
const oldId = oldKeys.find(key => id < key && oldGroups[key].nextMessageId <= newGroup.nextMessageId)
const oldId = Object.keys(oldGroups)
.find(key => id < key && oldGroups[key].nextMessageId <= newGroup.nextMessageId)
if (oldId) {
// newGroup includes oldGroup and more old messages, remove oldGroup
delete this.messagesGroupedByDateByAuthor[dateTimestamp][oldId]
Expand Down
51 changes: 51 additions & 0 deletions src/composables/useCombinedSystemMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,57 @@ export function useCombinedSystemMessage() {
}
}

// Handle cases when actor removed users from conversation (when remove team/group, for example)
if (type === 'user_removed') {
messages.forEach(message => {
if (checkIfSelfIsOneOfUsers(message)) {
selfIsUser = true
} else {
combinedMessage.messageParameters[`user${referenceIndex}`] = message.messageParameters.user
referenceIndex++
}
usersCounter++
})

if (checkIfSelfIsActor(combinedMessage)) {
if (usersCounter === 2) {
combinedMessage.message = t('spreed', 'You removed {user0} and {user1}')
} else {
combinedMessage.message = n('spreed',
'You removed {user0}, {user1} and %n more participant',
'You removed {user0}, {user1} and %n more participants', usersCounter - 2)
}
} else if (selfIsUser) {
if (usersCounter === 2) {
combinedMessage.message = actorIsAdministrator
? t('spreed', 'An administrator removed you and {user0}')
: t('spreed', '{actor} removed you and {user0}')
} else {
combinedMessage.message = actorIsAdministrator
? n('spreed',
'An administrator removed you, {user0} and %n more participant',
'An administrator removed you, {user0} and %n more participants', usersCounter - 2)
: n('spreed',
'{actor} removed you, {user0} and %n more participant',
'{actor} removed you, {user0} and %n more participants', usersCounter - 2)
}
} else {
if (usersCounter === 2) {
combinedMessage.message = actorIsAdministrator
? t('spreed', 'An administrator removed {user0} and {user1}')
: t('spreed', '{actor} removed {user0} and {user1}')
} else {
combinedMessage.message = actorIsAdministrator
? n('spreed',
'An administrator removed {user0}, {user1} and %n more participant',
'An administrator removed {user0}, {user1} and %n more participants', usersCounter - 2)
: n('spreed',
'{actor} removed {user0}, {user1} and %n more participant',
'{actor} removed {user0}, {user1} and %n more participants', usersCounter - 2)
}
}
}

// Handle cases when users joined or left the call
if (type === 'call_joined' || type === 'call_left') {
const storedUniqueUsers = []
Expand Down

0 comments on commit 09fadad

Please sign in to comment.