mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 21:32:34 +00:00
Hide message notification content when the app is locked (#6902)
* Hide message notification content by default when the app is locked * Make this the default without an option * Fix test * Update DefaultNotificationDrawerManager.kt * Fix
This commit is contained in:
+50
-1
@@ -11,6 +11,7 @@ package io.element.android.libraries.push.impl.notifications
|
|||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
import dev.zacsweers.metro.ContributesBinding
|
||||||
import dev.zacsweers.metro.SingleIn
|
import dev.zacsweers.metro.SingleIn
|
||||||
|
import io.element.android.features.lockscreen.api.LockScreenService
|
||||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
@@ -37,6 +38,7 @@ import io.element.android.services.appnavstate.api.currentRoomId
|
|||||||
import io.element.android.services.appnavstate.api.currentSessionId
|
import io.element.android.services.appnavstate.api.currentSessionId
|
||||||
import io.element.android.services.appnavstate.api.currentThreadId
|
import io.element.android.services.appnavstate.api.currentThreadId
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,6 +57,7 @@ class DefaultNotificationDrawerManager(
|
|||||||
private val matrixClientProvider: MatrixClientProvider,
|
private val matrixClientProvider: MatrixClientProvider,
|
||||||
private val imageLoaderHolder: ImageLoaderHolder,
|
private val imageLoaderHolder: ImageLoaderHolder,
|
||||||
private val activeNotificationsProvider: ActiveNotificationsProvider,
|
private val activeNotificationsProvider: ActiveNotificationsProvider,
|
||||||
|
private val lockScreenService: LockScreenService,
|
||||||
sessionObserver: SessionObserver,
|
sessionObserver: SessionObserver,
|
||||||
) : NotificationCleaner {
|
) : NotificationCleaner {
|
||||||
// TODO EAx add a setting per user for this
|
// TODO EAx add a setting per user for this
|
||||||
@@ -197,6 +200,8 @@ class DefaultNotificationDrawerManager(
|
|||||||
it.sessionId
|
it.sessionId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isAppLocked = lockScreenService.isPinSetup().first()
|
||||||
|
|
||||||
for ((sessionId, notifiableEvents) in eventsForSessions) {
|
for ((sessionId, notifiableEvents) in eventsForSessions) {
|
||||||
val client = matrixClientProvider.getOrRestore(sessionId).getOrThrow()
|
val client = matrixClientProvider.getOrRestore(sessionId).getOrThrow()
|
||||||
val imageLoader = imageLoaderHolder.get(client)
|
val imageLoader = imageLoaderHolder.get(client)
|
||||||
@@ -207,7 +212,25 @@ class DefaultNotificationDrawerManager(
|
|||||||
} else {
|
} else {
|
||||||
client.getUserProfile().getOrNull() ?: MatrixUser(sessionId)
|
client.getUserProfile().getOrNull() ?: MatrixUser(sessionId)
|
||||||
}
|
}
|
||||||
notificationRenderer.render(currentUser, useCompleteNotificationFormat, notifiableEvents, imageLoader)
|
if (isAppLocked) {
|
||||||
|
// When the app is locked, show a single fallback notification with event count
|
||||||
|
// instead of per-room notifications with message content/sender info.
|
||||||
|
clearAllMessagesEvents(sessionId)
|
||||||
|
val fallbackEvents = notifiableEvents.mapNotNull { it.toFallbackNotifiableEvent() }
|
||||||
|
notificationRenderer.render(
|
||||||
|
currentUser = currentUser,
|
||||||
|
useCompleteNotificationFormat = false,
|
||||||
|
eventsToProcess = fallbackEvents,
|
||||||
|
imageLoader = imageLoader,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
notificationRenderer.render(
|
||||||
|
currentUser = currentUser,
|
||||||
|
useCompleteNotificationFormat = useCompleteNotificationFormat,
|
||||||
|
eventsToProcess = notifiableEvents,
|
||||||
|
imageLoader = imageLoader,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,3 +261,29 @@ private fun AppNavigationState.shouldIgnoreEvent(event: NotifiableEvent): Boolea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a [NotifiableEvent] into a [FallbackNotifiableEvent], stripping all content and sender info.
|
||||||
|
* Used when notification content should be hidden (app locked with PIN).
|
||||||
|
*/
|
||||||
|
private fun NotifiableEvent.toFallbackNotifiableEvent(): FallbackNotifiableEvent? {
|
||||||
|
val timestamp = when (this) {
|
||||||
|
is NotifiableMessageEvent -> timestamp
|
||||||
|
is InviteNotifiableEvent -> timestamp
|
||||||
|
is SimpleNotifiableEvent -> timestamp
|
||||||
|
is FallbackNotifiableEvent -> timestamp
|
||||||
|
is NotifiableRingingCallEvent -> return null
|
||||||
|
}
|
||||||
|
return FallbackNotifiableEvent(
|
||||||
|
sessionId = sessionId,
|
||||||
|
roomId = roomId,
|
||||||
|
eventId = eventId,
|
||||||
|
editedEventId = null,
|
||||||
|
description = null,
|
||||||
|
canBeReplaced = false,
|
||||||
|
isRedacted = false,
|
||||||
|
isUpdated = false,
|
||||||
|
timestamp = timestamp,
|
||||||
|
cause = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ class DefaultRoomGroupMessageCreator(
|
|||||||
val roomIsDm = !roomIsGroup
|
val roomIsDm = !roomIsGroup
|
||||||
return notificationCreator.createMessagesListNotification(
|
return notificationCreator.createMessagesListNotification(
|
||||||
notificationAccountParams = notificationAccountParams,
|
notificationAccountParams = notificationAccountParams,
|
||||||
RoomEventGroupInfo(
|
roomInfo = RoomEventGroupInfo(
|
||||||
sessionId = notificationAccountParams.user.userId,
|
sessionId = notificationAccountParams.user.userId,
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
roomDisplayName = roomName,
|
roomDisplayName = roomName,
|
||||||
|
|||||||
+4
@@ -13,6 +13,8 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.features.enterprise.api.EnterpriseService
|
import io.element.android.features.enterprise.api.EnterpriseService
|
||||||
import io.element.android.features.enterprise.test.FakeEnterpriseService
|
import io.element.android.features.enterprise.test.FakeEnterpriseService
|
||||||
|
import io.element.android.features.lockscreen.api.LockScreenService
|
||||||
|
import io.element.android.features.lockscreen.test.FakeLockScreenService
|
||||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
||||||
@@ -510,6 +512,7 @@ fun TestScope.createDefaultNotificationDrawerManager(
|
|||||||
enterpriseService: EnterpriseService = FakeEnterpriseService(),
|
enterpriseService: EnterpriseService = FakeEnterpriseService(),
|
||||||
sessionObserver: SessionObserver = FakeSessionObserver(),
|
sessionObserver: SessionObserver = FakeSessionObserver(),
|
||||||
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
|
||||||
|
lockScreenService: LockScreenService = FakeLockScreenService(),
|
||||||
): DefaultNotificationDrawerManager {
|
): DefaultNotificationDrawerManager {
|
||||||
return DefaultNotificationDrawerManager(
|
return DefaultNotificationDrawerManager(
|
||||||
notificationDisplayer = notificationDisplayer,
|
notificationDisplayer = notificationDisplayer,
|
||||||
@@ -530,6 +533,7 @@ fun TestScope.createDefaultNotificationDrawerManager(
|
|||||||
matrixClientProvider = matrixClientProvider,
|
matrixClientProvider = matrixClientProvider,
|
||||||
imageLoaderHolder = FakeImageLoaderHolder(),
|
imageLoaderHolder = FakeImageLoaderHolder(),
|
||||||
activeNotificationsProvider = activeNotificationsProvider,
|
activeNotificationsProvider = activeNotificationsProvider,
|
||||||
|
lockScreenService = lockScreenService,
|
||||||
sessionObserver = sessionObserver,
|
sessionObserver = sessionObserver,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -57,7 +57,17 @@ class FakeNotificationCreator(
|
|||||||
events: List<NotifiableMessageEvent>,
|
events: List<NotifiableMessageEvent>,
|
||||||
): Notification {
|
): Notification {
|
||||||
return createMessagesListNotificationResult(
|
return createMessagesListNotificationResult(
|
||||||
listOf(notificationAccountParams, roomInfo, threadId, largeIcon, lastMessageTimestamp, tickerText, existingNotification, imageLoader, events)
|
listOf(
|
||||||
|
notificationAccountParams,
|
||||||
|
roomInfo,
|
||||||
|
threadId,
|
||||||
|
largeIcon,
|
||||||
|
lastMessageTimestamp,
|
||||||
|
tickerText,
|
||||||
|
existingNotification,
|
||||||
|
imageLoader,
|
||||||
|
events,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -56,7 +56,6 @@ class UserPushStoreDataStore(
|
|||||||
private val currentPushKey = stringPreferencesKey("currentPushKey")
|
private val currentPushKey = stringPreferencesKey("currentPushKey")
|
||||||
private val notificationEnabled = booleanPreferencesKey("notificationEnabled")
|
private val notificationEnabled = booleanPreferencesKey("notificationEnabled")
|
||||||
private val ignoreRegistrationError = booleanPreferencesKey("ignoreRegistrationError")
|
private val ignoreRegistrationError = booleanPreferencesKey("ignoreRegistrationError")
|
||||||
|
|
||||||
override suspend fun getPushProviderName(): String? {
|
override suspend fun getPushProviderName(): String? {
|
||||||
return store.data.first()[pushProviderName]
|
return store.data.first()[pushProviderName]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user