mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
chaining the event process, notification creation and display logic into a NotificationRender
- extract the displaying into its own class to avoid leaking the entire notificationutils - cancel/display notification actions are completely driven by the event or abscense of event from the eventList - attempts to avoid redundant render passes by checking if the eventList has changed since the last render
This commit is contained in:
parent
0f4ec65b7a
commit
3023cb4d39
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 android.app.Notification
|
||||
import android.content.Context
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class NotificationDisplayer @Inject constructor(context: Context) {
|
||||
|
||||
private val notificationManager = NotificationManagerCompat.from(context)
|
||||
|
||||
fun showNotificationMessage(tag: String?, id: Int, notification: Notification) {
|
||||
notificationManager.notify(tag, id, notification)
|
||||
}
|
||||
|
||||
fun cancelNotificationMessage(tag: String?, id: Int) {
|
||||
notificationManager.cancel(tag, id)
|
||||
}
|
||||
|
||||
fun cancelAllNotifications() {
|
||||
// Keep this try catch (reported by GA)
|
||||
try {
|
||||
notificationManager.cancelAll()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## cancelAllNotifications() failed")
|
||||
}
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ class NotificationFactory @Inject constructor(
|
||||
fun Map<String, List<NotifiableMessageEvent>>.toNotifications(myUserDisplayName: String, myUserAvatarUrl: String?): List<RoomNotification> {
|
||||
return this.map { (roomId, events) ->
|
||||
when {
|
||||
events.hasNoEventsToDisplay() -> RoomNotification.EmptyRoom(roomId)
|
||||
events.hasNoEventsToDisplay() -> RoomNotification.Removed(roomId)
|
||||
else -> roomGroupMessageCreator.createRoomMessage(events, roomId, myUserDisplayName, myUserAvatarUrl)
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ private fun List<RoomNotification>.mapToMeta() = filterIsInstance<RoomNotificati
|
||||
private fun List<OneShotNotification>.mapToMeta() = filterIsInstance<OneShotNotification.Append>().map { it.meta }
|
||||
|
||||
sealed interface RoomNotification {
|
||||
data class EmptyRoom(val roomId: String) : RoomNotification
|
||||
data class Removed(val roomId: String) : RoomNotification
|
||||
data class Message(val notification: Notification, val meta: Meta) : RoomNotification {
|
||||
data class Meta(
|
||||
val summaryLine: CharSequence,
|
||||
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2019 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 androidx.annotation.WorkerThread
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class NotificationRenderer @Inject constructor(private val notifiableEventProcessor: NotifiableEventProcessor,
|
||||
private val notificationDisplayer: NotificationDisplayer,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val notificationFactory: NotificationFactory) {
|
||||
|
||||
private var lastKnownEventList = -1
|
||||
private var useCompleteNotificationFormat = vectorPreferences.useCompleteNotificationFormat()
|
||||
|
||||
@WorkerThread
|
||||
fun render(currentRoomId: String?, myUserId: String, myUserDisplayName: String, myUserAvatarUrl: String?, eventList: MutableList<NotifiableEvent>) {
|
||||
Timber.v("refreshNotificationDrawerBg()")
|
||||
val newSettings = vectorPreferences.useCompleteNotificationFormat()
|
||||
if (newSettings != useCompleteNotificationFormat) {
|
||||
// Settings has changed, remove all current notifications
|
||||
notificationDisplayer.cancelAllNotifications()
|
||||
useCompleteNotificationFormat = newSettings
|
||||
}
|
||||
|
||||
val notificationEvents = notifiableEventProcessor.modifyAndProcess(eventList, currentRoomId)
|
||||
if (lastKnownEventList == notificationEvents.hashCode()) {
|
||||
Timber.d("Skipping notification update due to event list not changing")
|
||||
} else {
|
||||
processEvents(notificationEvents, myUserId, myUserDisplayName, myUserAvatarUrl)
|
||||
lastKnownEventList = notificationEvents.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
private fun processEvents(notificationEvents: ProcessedNotificationEvents, myUserId: String, myUserDisplayName: String, myUserAvatarUrl: String?) {
|
||||
val (roomEvents, simpleEvents, invitationEvents) = notificationEvents
|
||||
with(notificationFactory) {
|
||||
val roomNotifications = roomEvents.toNotifications(myUserDisplayName, myUserAvatarUrl)
|
||||
val invitationNotifications = invitationEvents.toNotifications(myUserId)
|
||||
val simpleNotifications = simpleEvents.toNotifications(myUserId)
|
||||
|
||||
if (roomNotifications.isEmpty() && invitationNotifications.isEmpty() && simpleNotifications.isEmpty()) {
|
||||
notificationDisplayer.cancelNotificationMessage(null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID)
|
||||
} else {
|
||||
val summaryNotification = createSummaryNotification(
|
||||
roomNotifications = roomNotifications,
|
||||
invitationNotifications = invitationNotifications,
|
||||
simpleNotifications = simpleNotifications,
|
||||
useCompleteNotificationFormat = useCompleteNotificationFormat
|
||||
)
|
||||
roomNotifications.forEach { wrapper ->
|
||||
when (wrapper) {
|
||||
is RoomNotification.Removed -> notificationDisplayer.cancelNotificationMessage(wrapper.roomId, NotificationDrawerManager.ROOM_MESSAGES_NOTIFICATION_ID)
|
||||
is RoomNotification.Message -> if (useCompleteNotificationFormat) {
|
||||
Timber.d("Updating room messages notification ${wrapper.meta.roomId}")
|
||||
notificationDisplayer.showNotificationMessage(wrapper.meta.roomId, NotificationDrawerManager.ROOM_MESSAGES_NOTIFICATION_ID, wrapper.notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invitationNotifications.forEach { wrapper ->
|
||||
when (wrapper) {
|
||||
is OneShotNotification.Removed -> notificationDisplayer.cancelNotificationMessage(wrapper.key, NotificationDrawerManager.ROOM_INVITATION_NOTIFICATION_ID)
|
||||
is OneShotNotification.Append -> if (useCompleteNotificationFormat) {
|
||||
Timber.d("Updating invitation notification ${wrapper.meta.key}")
|
||||
notificationDisplayer.showNotificationMessage(wrapper.meta.key, NotificationDrawerManager.ROOM_INVITATION_NOTIFICATION_ID, wrapper.notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simpleNotifications.forEach { wrapper ->
|
||||
when (wrapper) {
|
||||
is OneShotNotification.Removed -> notificationDisplayer.cancelNotificationMessage(wrapper.key, NotificationDrawerManager.ROOM_EVENT_NOTIFICATION_ID)
|
||||
is OneShotNotification.Append -> if (useCompleteNotificationFormat) {
|
||||
Timber.d("Updating simple notification ${wrapper.meta.key}")
|
||||
notificationDisplayer.showNotificationMessage(wrapper.meta.key, NotificationDrawerManager.ROOM_EVENT_NOTIFICATION_ID, wrapper.notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
notificationDisplayer.showNotificationMessage(null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, summaryNotification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,25 +22,25 @@ import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* ======== Build summary notification =========
|
||||
* On Android 7.0 (API level 24) and higher, the system automatically builds a summary for
|
||||
* your group using snippets of text from each notification. The user can expand this
|
||||
* notification to see each separate notification.
|
||||
* To support older versions, which cannot show a nested group of notifications,
|
||||
* you must create an extra notification that acts as the summary.
|
||||
* This appears as the only notification and the system hides all the others.
|
||||
* So this summary should include a snippet from all the other notifications,
|
||||
* which the user can tap to open your app.
|
||||
* The behavior of the group summary may vary on some device types such as wearables.
|
||||
* To ensure the best experience on all devices and versions, always include a group summary when you create a group
|
||||
* https://developer.android.com/training/notify-user/group
|
||||
*/
|
||||
class SummaryGroupMessageCreator @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val notificationUtils: NotificationUtils
|
||||
) {
|
||||
|
||||
/**
|
||||
* ======== Build summary notification =========
|
||||
* On Android 7.0 (API level 24) and higher, the system automatically builds a summary for
|
||||
* your group using snippets of text from each notification. The user can expand this
|
||||
* notification to see each separate notification.
|
||||
* To support older versions, which cannot show a nested group of notifications,
|
||||
* you must create an extra notification that acts as the summary.
|
||||
* This appears as the only notification and the system hides all the others.
|
||||
* So this summary should include a snippet from all the other notifications,
|
||||
* which the user can tap to open your app.
|
||||
* The behavior of the group summary may vary on some device types such as wearables.
|
||||
* To ensure the best experience on all devices and versions, always include a group summary when you create a group
|
||||
* https://developer.android.com/training/notify-user/group
|
||||
*/
|
||||
fun createSummaryNotification(roomNotifications: List<RoomNotification.Message.Meta>,
|
||||
invitationNotifications: List<OneShotNotification.Append.Meta>,
|
||||
simpleNotifications: List<OneShotNotification.Append.Meta>,
|
||||
|
@ -116,7 +116,7 @@ class NotificationFactoryTest {
|
||||
|
||||
val result = emptyRoom.toNotifications(MY_USER_ID, MY_AVATAR_URL)
|
||||
|
||||
result shouldBeEqualTo listOf(RoomNotification.EmptyRoom(
|
||||
result shouldBeEqualTo listOf(RoomNotification.Removed(
|
||||
roomId = A_ROOM_ID
|
||||
))
|
||||
}
|
||||
@ -127,7 +127,7 @@ class NotificationFactoryTest {
|
||||
|
||||
val result = redactedRoom.toNotifications(MY_USER_ID, MY_AVATAR_URL)
|
||||
|
||||
result shouldBeEqualTo listOf(RoomNotification.EmptyRoom(
|
||||
result shouldBeEqualTo listOf(RoomNotification.Removed(
|
||||
roomId = A_ROOM_ID
|
||||
))
|
||||
}
|
||||
|
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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 android.app.Notification
|
||||
import im.vector.app.test.fakes.FakeNotifiableEventProcessor
|
||||
import im.vector.app.test.fakes.FakeNotificationDisplayer
|
||||
import im.vector.app.test.fakes.FakeNotificationFactory
|
||||
import im.vector.app.test.fakes.FakeVectorPreferences
|
||||
import io.mockk.mockk
|
||||
import org.junit.Test
|
||||
|
||||
private const val A_CURRENT_ROOM_ID = "current-room-id"
|
||||
private const val MY_USER_ID = "my-user-id"
|
||||
private const val MY_USER_DISPLAY_NAME = "display-name"
|
||||
private const val MY_USER_AVATAR_URL = "avatar-url"
|
||||
private const val AN_EVENT_ID = "event-id"
|
||||
private const val A_ROOM_ID = "room-id"
|
||||
private const val USE_COMPLETE_NOTIFICATION_FORMAT = true
|
||||
|
||||
private val AN_EVENT_LIST = mutableListOf<NotifiableEvent>()
|
||||
private val A_PROCESSED_EVENTS = ProcessedNotificationEvents(emptyMap(), emptyMap(), emptyMap())
|
||||
private val A_SUMMARY_NOTIFICATION = mockk<Notification>()
|
||||
private val A_NOTIFICATION = mockk<Notification>()
|
||||
private val MESSAGE_META = RoomNotification.Message.Meta(
|
||||
summaryLine = "ignored", messageCount = 1, latestTimestamp = -1, roomId = A_ROOM_ID, shouldBing = false
|
||||
)
|
||||
private val ONE_SHOT_META = OneShotNotification.Append.Meta(key = "ignored", summaryLine = "ignored", isNoisy = false)
|
||||
|
||||
class NotificationRendererTest {
|
||||
|
||||
private val notifiableEventProcessor = FakeNotifiableEventProcessor()
|
||||
private val notificationDisplayer = FakeNotificationDisplayer()
|
||||
private val preferences = FakeVectorPreferences().also {
|
||||
it.givenUseCompleteNotificationFormat(USE_COMPLETE_NOTIFICATION_FORMAT)
|
||||
}
|
||||
private val notificationFactory = FakeNotificationFactory()
|
||||
|
||||
private val notificationRenderer = NotificationRenderer(
|
||||
notifiableEventProcessor = notifiableEventProcessor.instance,
|
||||
notificationDisplayer = notificationDisplayer.instance,
|
||||
vectorPreferences = preferences.instance,
|
||||
notificationFactory = notificationFactory.instance
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `given no notifications when rendering then cancels summary notification`() {
|
||||
givenNoNotifications()
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifySummaryCancelled()
|
||||
notificationDisplayer.verifyNoOtherInteractions()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a room message group notification is removed when rendering then remove the message notification and update summary`() {
|
||||
givenNotifications(roomNotifications = listOf(RoomNotification.Removed(A_ROOM_ID)))
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifyInOrder {
|
||||
cancelNotificationMessage(tag = A_ROOM_ID, NotificationDrawerManager.ROOM_MESSAGES_NOTIFICATION_ID)
|
||||
showNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a room message group notification is added when rendering then show the message notification and update summary`() {
|
||||
givenNotifications(roomNotifications = listOf(RoomNotification.Message(
|
||||
A_NOTIFICATION,
|
||||
MESSAGE_META
|
||||
)))
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifyInOrder {
|
||||
showNotificationMessage(tag = A_ROOM_ID, NotificationDrawerManager.ROOM_MESSAGES_NOTIFICATION_ID, A_NOTIFICATION)
|
||||
showNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a simple notification is removed when rendering then remove the simple notification and update summary`() {
|
||||
givenNotifications(simpleNotifications = listOf(OneShotNotification.Removed(AN_EVENT_ID)))
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifyInOrder {
|
||||
cancelNotificationMessage(tag = AN_EVENT_ID, NotificationDrawerManager.ROOM_EVENT_NOTIFICATION_ID)
|
||||
showNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a simple notification is added when rendering then show the simple notification and update summary`() {
|
||||
givenNotifications(simpleNotifications = listOf(OneShotNotification.Append(
|
||||
A_NOTIFICATION,
|
||||
ONE_SHOT_META.copy(key = AN_EVENT_ID)
|
||||
)))
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifyInOrder {
|
||||
showNotificationMessage(tag = AN_EVENT_ID, NotificationDrawerManager.ROOM_EVENT_NOTIFICATION_ID, A_NOTIFICATION)
|
||||
showNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given an invitation notification is removed when rendering then remove the invitation notification and update summary`() {
|
||||
givenNotifications(invitationNotifications = listOf(OneShotNotification.Removed(A_ROOM_ID)))
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifyInOrder {
|
||||
cancelNotificationMessage(tag = A_ROOM_ID, NotificationDrawerManager.ROOM_INVITATION_NOTIFICATION_ID)
|
||||
showNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given an invitation notification is added when rendering then show the invitation notification and update summary`() {
|
||||
givenNotifications(simpleNotifications = listOf(OneShotNotification.Append(
|
||||
A_NOTIFICATION,
|
||||
ONE_SHOT_META.copy(key = A_ROOM_ID)
|
||||
)))
|
||||
|
||||
renderEventsAsNotifications()
|
||||
|
||||
notificationDisplayer.verifyInOrder {
|
||||
showNotificationMessage(tag = A_ROOM_ID, NotificationDrawerManager.ROOM_EVENT_NOTIFICATION_ID, A_NOTIFICATION)
|
||||
showNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderEventsAsNotifications() {
|
||||
notificationRenderer.render(
|
||||
currentRoomId = A_CURRENT_ROOM_ID,
|
||||
myUserId = MY_USER_ID,
|
||||
myUserDisplayName = MY_USER_DISPLAY_NAME,
|
||||
myUserAvatarUrl = MY_USER_AVATAR_URL,
|
||||
eventList = AN_EVENT_LIST
|
||||
)
|
||||
}
|
||||
|
||||
private fun givenNoNotifications() {
|
||||
givenNotifications(emptyList(), emptyList(), emptyList(), USE_COMPLETE_NOTIFICATION_FORMAT, A_SUMMARY_NOTIFICATION)
|
||||
}
|
||||
|
||||
private fun givenNotifications(roomNotifications: List<RoomNotification> = emptyList(),
|
||||
invitationNotifications: List<OneShotNotification> = emptyList(),
|
||||
simpleNotifications: List<OneShotNotification> = emptyList(),
|
||||
useCompleteNotificationFormat: Boolean = USE_COMPLETE_NOTIFICATION_FORMAT,
|
||||
summaryNotification: Notification = A_SUMMARY_NOTIFICATION) {
|
||||
notifiableEventProcessor.givenProcessedEventsFor(AN_EVENT_LIST, A_CURRENT_ROOM_ID, A_PROCESSED_EVENTS)
|
||||
notificationFactory.givenNotificationsFor(
|
||||
processedEvents = A_PROCESSED_EVENTS,
|
||||
myUserId = MY_USER_ID,
|
||||
myUserDisplayName = MY_USER_DISPLAY_NAME,
|
||||
myUserAvatarUrl = MY_USER_AVATAR_URL,
|
||||
useCompleteNotificationFormat = useCompleteNotificationFormat,
|
||||
roomNotifications = roomNotifications,
|
||||
invitationNotifications = invitationNotifications,
|
||||
simpleNotifications = simpleNotifications,
|
||||
summaryNotification = summaryNotification
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.NotifiableEventProcessor
|
||||
import im.vector.app.features.notifications.ProcessedNotificationEvents
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
||||
class FakeNotifiableEventProcessor {
|
||||
|
||||
val instance = mockk<NotifiableEventProcessor>()
|
||||
|
||||
fun givenProcessedEventsFor(events: MutableList<NotifiableEvent>, currentRoomId: String?, processedEvents: ProcessedNotificationEvents) {
|
||||
every { instance.modifyAndProcess(events, currentRoomId) } returns processedEvents
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.NotificationDisplayer
|
||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||
import io.mockk.confirmVerified
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import io.mockk.verifyOrder
|
||||
|
||||
class FakeNotificationDisplayer {
|
||||
|
||||
val instance = mockk<NotificationDisplayer>(relaxed = true)
|
||||
|
||||
fun verifySummaryCancelled() {
|
||||
verify { instance.cancelNotificationMessage(tag = null, NotificationDrawerManager.SUMMARY_NOTIFICATION_ID) }
|
||||
}
|
||||
|
||||
fun verifyNoOtherInteractions() {
|
||||
confirmVerified(instance)
|
||||
}
|
||||
|
||||
fun verifyInOrder(verifyBlock: NotificationDisplayer.() -> Unit) {
|
||||
verifyOrder { verifyBlock(instance) }
|
||||
verifyNoOtherInteractions()
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 android.app.Notification
|
||||
import im.vector.app.features.notifications.NotificationFactory
|
||||
import im.vector.app.features.notifications.OneShotNotification
|
||||
import im.vector.app.features.notifications.ProcessedNotificationEvents
|
||||
import im.vector.app.features.notifications.RoomNotification
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
||||
class FakeNotificationFactory {
|
||||
|
||||
val instance = mockk<NotificationFactory>()
|
||||
|
||||
fun givenNotificationsFor(processedEvents: ProcessedNotificationEvents,
|
||||
myUserId: String,
|
||||
myUserDisplayName: String,
|
||||
myUserAvatarUrl: String?,
|
||||
useCompleteNotificationFormat: Boolean,
|
||||
roomNotifications: List<RoomNotification>,
|
||||
invitationNotifications: List<OneShotNotification>,
|
||||
simpleNotifications: List<OneShotNotification>,
|
||||
summaryNotification: Notification) {
|
||||
with(instance) {
|
||||
every { processedEvents.roomEvents.toNotifications(myUserDisplayName, myUserAvatarUrl) } returns roomNotifications
|
||||
every { processedEvents.invitationEvents.toNotifications(myUserId) } returns invitationNotifications
|
||||
every { processedEvents.simpleEvents.toNotifications(myUserId) } returns simpleNotifications
|
||||
|
||||
every {
|
||||
createSummaryNotification(
|
||||
roomNotifications,
|
||||
invitationNotifications,
|
||||
simpleNotifications,
|
||||
useCompleteNotificationFormat
|
||||
)
|
||||
} returns summaryNotification
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.settings.VectorPreferences
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
||||
class FakeVectorPreferences {
|
||||
|
||||
val instance = mockk<VectorPreferences>()
|
||||
|
||||
fun givenUseCompleteNotificationFormat(value: Boolean) {
|
||||
every { instance.useCompleteNotificationFormat() } returns value
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user