diff --git a/features/roomlist/impl/build.gradle.kts b/features/roomlist/impl/build.gradle.kts index 3a3639de98..f5a08ba860 100644 --- a/features/roomlist/impl/build.gradle.kts +++ b/features/roomlist/impl/build.gradle.kts @@ -49,7 +49,6 @@ dependencies { implementation(projects.libraries.dateformatter.api) implementation(projects.libraries.eventformatter.api) implementation(projects.libraries.deeplink) - implementation(projects.libraries.pushstore.api) implementation(projects.features.invitelist.api) implementation(projects.features.networkmonitor.api) implementation(projects.features.leaveroom.api) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index 61826dc2b2..33a8564efb 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -24,12 +24,10 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable @@ -154,7 +152,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) { Text( text = room.timestamp ?: "", style = ElementTheme.typography.fontBodySmRegular, - color = if (room.hasUnread) { + color = if (room.shouldDisplayNotificationAlertDecoration) { ElementTheme.colors.unreadIndicator } else { MaterialTheme.roomListRoomMessageDate() @@ -184,7 +182,7 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { horizontalArrangement = Arrangement.spacedBy(8.dp) ) { NotificationIcon(room) - if (room.hasUnread) { + if (room.shouldDisplayNotificationAlertDecoration) { UnreadIndicatorAtom( modifier = Modifier.padding(top = 3.dp), ) @@ -192,23 +190,28 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) { } } +// We should never show a green dot/icon for mute. Also mentions is not yet supported by the mobile app. +// In some cases a green @ was incorrectly shown when we switch from ALL_MESSAGES to MENTIONS_AND_KEYWORDS_ONLY +// and we don't know whether the room has mentions, just that it has unread. +private val RoomListRoomSummary.shouldDisplayNotificationAlertDecoration get() = hasUnread + && notificationMode != RoomNotificationMode.MUTE + && notificationMode != RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY @Composable private fun NotificationIcon(room: RoomListRoomSummary) { - val tint = if(room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary when(room.notificationMode) { null, RoomNotificationMode.ALL_MESSAGES -> return RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> Icon( contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions), imageVector = ImageVector.vectorResource(VectorIcons.Mention), - tint = tint, + tint = ElementTheme.colors.iconQuaternary, ) RoomNotificationMode.MUTE -> Icon( contentDescription = stringResource(CommonStrings.common_mute), imageVector = ImageVector.vectorResource(VectorIcons.Mute), - tint = tint, + tint = ElementTheme.colors.iconQuaternary, ) } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt index e0b20aada9..2cf28a6913 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt @@ -26,24 +26,19 @@ import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormat import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter -import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomSummary -import io.element.android.libraries.pushstore.api.UserPushStoreFactory import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex @@ -59,8 +54,6 @@ class RoomListDataSource @Inject constructor( private val coroutineDispatchers: CoroutineDispatchers, notificationSettingsService: NotificationSettingsService, appScope: CoroutineScope, - userPushStoreFactory: UserPushStoreFactory, - matrixClient: MatrixClient, ) { init { notificationSettingsService.notificationSettingsChangeFlow @@ -69,13 +62,6 @@ class RoomListDataSource @Inject constructor( roomListService.rebuildRoomSummaries() } .launchIn(appScope) - - val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) - userPushStore.getNotificationEnabledForDevice().distinctUntilChanged() - .onEach { - roomListService.rebuildRoomSummaries() - } - .launchIn(appScope) } private val _filter = MutableStateFlow("") private val _allRooms = MutableStateFlow>(persistentListOf()) @@ -86,15 +72,13 @@ class RoomListDataSource @Inject constructor( private val diffCacheUpdater = DiffCacheUpdater(diffCache = diffCache, detectMoves = true) { old, new -> old?.identifier() == new?.identifier() } - private val userPushStore = userPushStoreFactory.create(matrixClient.sessionId) fun launchIn(coroutineScope: CoroutineScope) { - roomListService .allRooms() .summaries .onEach { roomSummaries -> - replaceWith(roomSummaries, userPushStore.getNotificationEnabledForDevice().first()) + replaceWith(roomSummaries) } .launchIn(coroutineScope) @@ -121,14 +105,14 @@ class RoomListDataSource @Inject constructor( val allRooms: StateFlow> = _allRooms val filteredRooms: StateFlow> = _filteredRooms - private suspend fun replaceWith(roomSummaries: List, notificationsEnabled: Boolean) = withContext(coroutineDispatchers.computation) { + private suspend fun replaceWith(roomSummaries: List) = withContext(coroutineDispatchers.computation) { lock.withLock { diffCacheUpdater.updateWith(roomSummaries) - buildAndEmitAllRooms(roomSummaries, notificationsEnabled) + buildAndEmitAllRooms(roomSummaries) } } - private suspend fun buildAndEmitAllRooms(roomSummaries: List, notificationsEnabled: Boolean) { + private suspend fun buildAndEmitAllRooms(roomSummaries: List) { if (diffCache.isEmpty()) { _allRooms.emit( RoomListRoomSummaryPlaceholders.createFakeList(16).toImmutableList() @@ -138,7 +122,7 @@ class RoomListDataSource @Inject constructor( for (index in diffCache.indices()) { val cacheItem = diffCache.get(index) if (cacheItem == null) { - buildAndCacheItem(roomSummaries, index, notificationsEnabled)?.also { timelineItemState -> + buildAndCacheItem(roomSummaries, index)?.also { timelineItemState -> roomListRoomSummaries.add(timelineItemState) } } else { @@ -149,16 +133,12 @@ class RoomListDataSource @Inject constructor( } } - private fun buildAndCacheItem( - roomSummaries: List, - index: Int, - notificationsEnabled: Boolean, - ): RoomListRoomSummary? { + private fun buildAndCacheItem(roomSummaries: List, index: Int, ): RoomListRoomSummary? { val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) { is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier) is RoomSummary.Filled -> { - // Only show a decoration if notifications are enabled and the mode is not ALL_MESSAGES - val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES || !notificationsEnabled) { + // Only show a decoration if the mode is not ALL_MESSAGES + val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES) { null } else { roomSummary.details.notificationMode