creating dedicated class for the processing the serialized events
- updates the logic to track when events are removed as a way for the notifications to remove themselves, null events mean they've been removed
This commit is contained in:
parent
4459aab558
commit
7b0c483134
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.notifications
|
||||
|
||||
import im.vector.app.features.invite.AutoAcceptInvites
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class NotifiableEventProcessor @Inject constructor(
|
||||
private val outdatedDetector: OutdatedEventDetector,
|
||||
private val autoAcceptInvites: AutoAcceptInvites
|
||||
) {
|
||||
|
||||
fun modifyAndProcess(eventList: MutableList<NotifiableEvent>, currentRoomId: String?): ProcessedNotificationEvents {
|
||||
val roomIdToEventMap: MutableMap<String, MutableList<NotifiableMessageEvent>> = LinkedHashMap()
|
||||
val simpleEvents: MutableMap<String, SimpleNotifiableEvent?> = LinkedHashMap()
|
||||
val invitationEvents: MutableMap<String, InviteNotifiableEvent?> = LinkedHashMap()
|
||||
|
||||
val eventIterator = eventList.listIterator()
|
||||
while (eventIterator.hasNext()) {
|
||||
when (val event = eventIterator.next()) {
|
||||
is NotifiableMessageEvent -> {
|
||||
val roomId = event.roomId
|
||||
val roomEvents = roomIdToEventMap.getOrPut(roomId) { ArrayList() }
|
||||
|
||||
// should we limit to last 7 messages per room?
|
||||
if (shouldIgnoreMessageEventInRoom(currentRoomId, roomId) || outdatedDetector.isMessageOutdated(event)) {
|
||||
// forget this event
|
||||
eventIterator.remove()
|
||||
} else {
|
||||
roomEvents.add(event)
|
||||
}
|
||||
}
|
||||
is InviteNotifiableEvent -> {
|
||||
if (autoAcceptInvites.hideInvites) {
|
||||
// Forget this event
|
||||
eventIterator.remove()
|
||||
invitationEvents[event.roomId] = null
|
||||
} else {
|
||||
invitationEvents[event.roomId] = event
|
||||
}
|
||||
}
|
||||
is SimpleNotifiableEvent -> simpleEvents[event.eventId] = event
|
||||
else -> Timber.w("Type not handled")
|
||||
}
|
||||
}
|
||||
return ProcessedNotificationEvents(roomIdToEventMap, simpleEvents, invitationEvents)
|
||||
}
|
||||
|
||||
private fun shouldIgnoreMessageEventInRoom(currentRoomId: String?, roomId: String?): Boolean {
|
||||
return currentRoomId != null && roomId == currentRoomId
|
||||
}
|
||||
}
|
||||
|
||||
data class ProcessedNotificationEvents(
|
||||
val roomEvents: Map<String, List<NotifiableMessageEvent>>,
|
||||
val simpleEvents: Map<String, SimpleNotifiableEvent?>,
|
||||
val invitationEvents: Map<String, InviteNotifiableEvent?>
|
||||
)
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.notifications
|
||||
|
||||
import im.vector.app.test.fakes.FakeAutoAcceptInvites
|
||||
import im.vector.app.test.fakes.FakeOutdatedEventDetector
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
import org.junit.Test
|
||||
|
||||
private val NOT_VIEWING_A_ROOM: String? = null
|
||||
|
||||
class NotifiableEventProcessorTest {
|
||||
|
||||
private val outdatedDetector = FakeOutdatedEventDetector()
|
||||
private val autoAcceptInvites = FakeAutoAcceptInvites()
|
||||
|
||||
private val eventProcessor = NotifiableEventProcessor(outdatedDetector.instance, autoAcceptInvites)
|
||||
|
||||
@Test
|
||||
fun `given simple events when processing then return without mutating`() {
|
||||
val (events, originalEvents) = createEventsList(
|
||||
aSimpleNotifiableEvent(eventId = "event-1"),
|
||||
aSimpleNotifiableEvent(eventId = "event-2")
|
||||
)
|
||||
|
||||
val result = eventProcessor.modifyAndProcess(events, currentRoomId = NOT_VIEWING_A_ROOM)
|
||||
|
||||
result shouldBeEqualTo aProcessedNotificationEvents(
|
||||
simpleEvents = mapOf(
|
||||
"event-1" to events[0] as SimpleNotifiableEvent,
|
||||
"event-2" to events[1] as SimpleNotifiableEvent
|
||||
)
|
||||
)
|
||||
events shouldBeEqualTo originalEvents
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given invites are auto accepted when processing then remove invitations`() {
|
||||
autoAcceptInvites._isEnabled = true
|
||||
val events = mutableListOf<NotifiableEvent>(
|
||||
anInviteNotifiableEvent(roomId = "room-1"),
|
||||
anInviteNotifiableEvent(roomId = "room-2")
|
||||
)
|
||||
|
||||
val result = eventProcessor.modifyAndProcess(events, currentRoomId = NOT_VIEWING_A_ROOM)
|
||||
|
||||
result shouldBeEqualTo aProcessedNotificationEvents(
|
||||
invitationEvents = mapOf(
|
||||
"room-1" to null,
|
||||
"room-2" to null
|
||||
)
|
||||
)
|
||||
events shouldBeEqualTo emptyList()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given invites are not auto accepted when processing then return without mutating`() {
|
||||
autoAcceptInvites._isEnabled = false
|
||||
val (events, originalEvents) = createEventsList(
|
||||
anInviteNotifiableEvent(roomId = "room-1"),
|
||||
anInviteNotifiableEvent(roomId = "room-2")
|
||||
)
|
||||
|
||||
val result = eventProcessor.modifyAndProcess(events, currentRoomId = NOT_VIEWING_A_ROOM)
|
||||
|
||||
result shouldBeEqualTo aProcessedNotificationEvents(
|
||||
invitationEvents = mapOf(
|
||||
"room-1" to originalEvents[0] as InviteNotifiableEvent,
|
||||
"room-2" to originalEvents[1] as InviteNotifiableEvent
|
||||
)
|
||||
)
|
||||
events shouldBeEqualTo originalEvents
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given out of date message event when processing then removes message`() {
|
||||
val (events) = createEventsList(aNotifiableMessageEvent(eventId = "event-1", roomId = "room-1"))
|
||||
outdatedDetector.givenEventIsOutOfDate(events[0])
|
||||
|
||||
val result = eventProcessor.modifyAndProcess(events, currentRoomId = NOT_VIEWING_A_ROOM)
|
||||
|
||||
result shouldBeEqualTo aProcessedNotificationEvents(
|
||||
roomEvents = mapOf(
|
||||
"room-1" to emptyList()
|
||||
)
|
||||
)
|
||||
events shouldBeEqualTo emptyList()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given in date message event when processing then without mutating`() {
|
||||
val (events, originalEvents) = createEventsList(aNotifiableMessageEvent(eventId = "event-1", roomId = "room-1"))
|
||||
outdatedDetector.givenEventIsInDate(events[0])
|
||||
|
||||
val result = eventProcessor.modifyAndProcess(events, currentRoomId = NOT_VIEWING_A_ROOM)
|
||||
|
||||
result shouldBeEqualTo aProcessedNotificationEvents(
|
||||
roomEvents = mapOf(
|
||||
"room-1" to listOf(events[0] as NotifiableMessageEvent)
|
||||
)
|
||||
)
|
||||
events shouldBeEqualTo originalEvents
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given viewing the same room as message event when processing then removes message`() {
|
||||
val (events) = createEventsList(aNotifiableMessageEvent(eventId = "event-1", roomId = "room-1"))
|
||||
|
||||
val result = eventProcessor.modifyAndProcess(events, currentRoomId = "room-1")
|
||||
|
||||
result shouldBeEqualTo aProcessedNotificationEvents(
|
||||
roomEvents = mapOf(
|
||||
"room-1" to emptyList()
|
||||
)
|
||||
)
|
||||
events shouldBeEqualTo emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun createEventsList(vararg event: NotifiableEvent): Pair<MutableList<NotifiableEvent>, List<NotifiableEvent>> {
|
||||
val mutableEvents = mutableListOf(*event)
|
||||
val immutableEvents = mutableEvents.toList()
|
||||
return mutableEvents to immutableEvents
|
||||
}
|
||||
|
||||
fun aProcessedNotificationEvents(simpleEvents: Map<String, SimpleNotifiableEvent?> = emptyMap(),
|
||||
invitationEvents: Map<String, InviteNotifiableEvent?> = emptyMap(),
|
||||
roomEvents: Map<String, List<NotifiableMessageEvent>> = emptyMap()
|
||||
) = ProcessedNotificationEvents(
|
||||
roomEvents = roomEvents,
|
||||
simpleEvents = simpleEvents,
|
||||
invitationEvents = invitationEvents,
|
||||
)
|
||||
|
||||
fun aSimpleNotifiableEvent(eventId: String) = SimpleNotifiableEvent(
|
||||
matrixID = null,
|
||||
eventId = eventId,
|
||||
editedEventId = null,
|
||||
noisy = false,
|
||||
title = "title",
|
||||
description = "description",
|
||||
type = null,
|
||||
timestamp = 0,
|
||||
soundName = null,
|
||||
isPushGatewayEvent = false
|
||||
)
|
||||
|
||||
fun anInviteNotifiableEvent(roomId: String) = InviteNotifiableEvent(
|
||||
matrixID = null,
|
||||
eventId = "event-id",
|
||||
roomId = roomId,
|
||||
editedEventId = null,
|
||||
noisy = false,
|
||||
title = "title",
|
||||
description = "description",
|
||||
type = null,
|
||||
timestamp = 0,
|
||||
soundName = null,
|
||||
isPushGatewayEvent = false
|
||||
)
|
||||
|
||||
fun aNotifiableMessageEvent(eventId: String, roomId: String) = NotifiableMessageEvent(
|
||||
eventId = eventId,
|
||||
editedEventId = null,
|
||||
noisy = false,
|
||||
timestamp = 0,
|
||||
senderName = "sender-name",
|
||||
senderId = "sending-id",
|
||||
body = "message-body",
|
||||
roomId = roomId,
|
||||
roomName = "room-name",
|
||||
roomIsDirect = false
|
||||
)
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.features.invite.AutoAcceptInvites
|
||||
|
||||
class FakeAutoAcceptInvites : AutoAcceptInvites {
|
||||
|
||||
var _isEnabled: Boolean = false
|
||||
|
||||
override val isEnabled: Boolean
|
||||
get() = _isEnabled
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.features.notifications.NotifiableEvent
|
||||
import im.vector.app.features.notifications.OutdatedEventDetector
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
||||
class FakeOutdatedEventDetector {
|
||||
val instance = mockk<OutdatedEventDetector>()
|
||||
|
||||
fun givenEventIsOutOfDate(notifiableEvent: NotifiableEvent) {
|
||||
every { instance.isMessageOutdated(notifiableEvent) } returns true
|
||||
}
|
||||
|
||||
fun givenEventIsInDate(notifiableEvent: NotifiableEvent) {
|
||||
every { instance.isMessageOutdated(notifiableEvent) } returns false
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user