Only show green indicator for "All Messages"
- Only show green indicator for "All Messages" as mentions doesn't work and we should never see it for muted rooms. - Remove code that tried to reflect the notificationsEnabled setting I mis-undertood the requirements by reading the iOS code.
This commit is contained in:
parent
2a7a46841e
commit
43fab70d30
3 changed files with 18 additions and 36 deletions
|
|
@ -49,7 +49,6 @@ dependencies {
|
||||||
implementation(projects.libraries.dateformatter.api)
|
implementation(projects.libraries.dateformatter.api)
|
||||||
implementation(projects.libraries.eventformatter.api)
|
implementation(projects.libraries.eventformatter.api)
|
||||||
implementation(projects.libraries.deeplink)
|
implementation(projects.libraries.deeplink)
|
||||||
implementation(projects.libraries.pushstore.api)
|
|
||||||
implementation(projects.features.invitelist.api)
|
implementation(projects.features.invitelist.api)
|
||||||
implementation(projects.features.networkmonitor.api)
|
implementation(projects.features.networkmonitor.api)
|
||||||
implementation(projects.features.leaveroom.api)
|
implementation(projects.features.leaveroom.api)
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,10 @@ import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.IntrinsicSize
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
import androidx.compose.material.ripple.rememberRipple
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -154,7 +152,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) {
|
||||||
Text(
|
Text(
|
||||||
text = room.timestamp ?: "",
|
text = room.timestamp ?: "",
|
||||||
style = ElementTheme.typography.fontBodySmRegular,
|
style = ElementTheme.typography.fontBodySmRegular,
|
||||||
color = if (room.hasUnread) {
|
color = if (room.shouldDisplayNotificationAlertDecoration) {
|
||||||
ElementTheme.colors.unreadIndicator
|
ElementTheme.colors.unreadIndicator
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.roomListRoomMessageDate()
|
MaterialTheme.roomListRoomMessageDate()
|
||||||
|
|
@ -184,7 +182,7 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) {
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
NotificationIcon(room)
|
NotificationIcon(room)
|
||||||
if (room.hasUnread) {
|
if (room.shouldDisplayNotificationAlertDecoration) {
|
||||||
UnreadIndicatorAtom(
|
UnreadIndicatorAtom(
|
||||||
modifier = Modifier.padding(top = 3.dp),
|
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
|
@Composable
|
||||||
private fun NotificationIcon(room: RoomListRoomSummary) {
|
private fun NotificationIcon(room: RoomListRoomSummary) {
|
||||||
val tint = if(room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary
|
|
||||||
when(room.notificationMode) {
|
when(room.notificationMode) {
|
||||||
null, RoomNotificationMode.ALL_MESSAGES -> return
|
null, RoomNotificationMode.ALL_MESSAGES -> return
|
||||||
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ->
|
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ->
|
||||||
Icon(
|
Icon(
|
||||||
contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions),
|
contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions),
|
||||||
imageVector = ImageVector.vectorResource(VectorIcons.Mention),
|
imageVector = ImageVector.vectorResource(VectorIcons.Mention),
|
||||||
tint = tint,
|
tint = ElementTheme.colors.iconQuaternary,
|
||||||
)
|
)
|
||||||
RoomNotificationMode.MUTE ->
|
RoomNotificationMode.MUTE ->
|
||||||
Icon(
|
Icon(
|
||||||
contentDescription = stringResource(CommonStrings.common_mute),
|
contentDescription = stringResource(CommonStrings.common_mute),
|
||||||
imageVector = ImageVector.vectorResource(VectorIcons.Mute),
|
imageVector = ImageVector.vectorResource(VectorIcons.Mute),
|
||||||
tint = tint,
|
tint = ElementTheme.colors.iconQuaternary,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
|
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.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
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.room.RoomNotificationMode
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
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.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.FlowPreview
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
|
@ -59,8 +54,6 @@ class RoomListDataSource @Inject constructor(
|
||||||
private val coroutineDispatchers: CoroutineDispatchers,
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
notificationSettingsService: NotificationSettingsService,
|
notificationSettingsService: NotificationSettingsService,
|
||||||
appScope: CoroutineScope,
|
appScope: CoroutineScope,
|
||||||
userPushStoreFactory: UserPushStoreFactory,
|
|
||||||
matrixClient: MatrixClient,
|
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
notificationSettingsService.notificationSettingsChangeFlow
|
notificationSettingsService.notificationSettingsChangeFlow
|
||||||
|
|
@ -69,13 +62,6 @@ class RoomListDataSource @Inject constructor(
|
||||||
roomListService.rebuildRoomSummaries()
|
roomListService.rebuildRoomSummaries()
|
||||||
}
|
}
|
||||||
.launchIn(appScope)
|
.launchIn(appScope)
|
||||||
|
|
||||||
val userPushStore = userPushStoreFactory.create(matrixClient.sessionId)
|
|
||||||
userPushStore.getNotificationEnabledForDevice().distinctUntilChanged()
|
|
||||||
.onEach {
|
|
||||||
roomListService.rebuildRoomSummaries()
|
|
||||||
}
|
|
||||||
.launchIn(appScope)
|
|
||||||
}
|
}
|
||||||
private val _filter = MutableStateFlow("")
|
private val _filter = MutableStateFlow("")
|
||||||
private val _allRooms = MutableStateFlow<ImmutableList<RoomListRoomSummary>>(persistentListOf())
|
private val _allRooms = MutableStateFlow<ImmutableList<RoomListRoomSummary>>(persistentListOf())
|
||||||
|
|
@ -86,15 +72,13 @@ class RoomListDataSource @Inject constructor(
|
||||||
private val diffCacheUpdater = DiffCacheUpdater<RoomSummary, RoomListRoomSummary>(diffCache = diffCache, detectMoves = true) { old, new ->
|
private val diffCacheUpdater = DiffCacheUpdater<RoomSummary, RoomListRoomSummary>(diffCache = diffCache, detectMoves = true) { old, new ->
|
||||||
old?.identifier() == new?.identifier()
|
old?.identifier() == new?.identifier()
|
||||||
}
|
}
|
||||||
private val userPushStore = userPushStoreFactory.create(matrixClient.sessionId)
|
|
||||||
|
|
||||||
fun launchIn(coroutineScope: CoroutineScope) {
|
fun launchIn(coroutineScope: CoroutineScope) {
|
||||||
|
|
||||||
roomListService
|
roomListService
|
||||||
.allRooms()
|
.allRooms()
|
||||||
.summaries
|
.summaries
|
||||||
.onEach { roomSummaries ->
|
.onEach { roomSummaries ->
|
||||||
replaceWith(roomSummaries, userPushStore.getNotificationEnabledForDevice().first())
|
replaceWith(roomSummaries)
|
||||||
}
|
}
|
||||||
.launchIn(coroutineScope)
|
.launchIn(coroutineScope)
|
||||||
|
|
||||||
|
|
@ -121,14 +105,14 @@ class RoomListDataSource @Inject constructor(
|
||||||
val allRooms: StateFlow<ImmutableList<RoomListRoomSummary>> = _allRooms
|
val allRooms: StateFlow<ImmutableList<RoomListRoomSummary>> = _allRooms
|
||||||
val filteredRooms: StateFlow<ImmutableList<RoomListRoomSummary>> = _filteredRooms
|
val filteredRooms: StateFlow<ImmutableList<RoomListRoomSummary>> = _filteredRooms
|
||||||
|
|
||||||
private suspend fun replaceWith(roomSummaries: List<RoomSummary>, notificationsEnabled: Boolean) = withContext(coroutineDispatchers.computation) {
|
private suspend fun replaceWith(roomSummaries: List<RoomSummary>) = withContext(coroutineDispatchers.computation) {
|
||||||
lock.withLock {
|
lock.withLock {
|
||||||
diffCacheUpdater.updateWith(roomSummaries)
|
diffCacheUpdater.updateWith(roomSummaries)
|
||||||
buildAndEmitAllRooms(roomSummaries, notificationsEnabled)
|
buildAndEmitAllRooms(roomSummaries)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun buildAndEmitAllRooms(roomSummaries: List<RoomSummary>, notificationsEnabled: Boolean) {
|
private suspend fun buildAndEmitAllRooms(roomSummaries: List<RoomSummary>) {
|
||||||
if (diffCache.isEmpty()) {
|
if (diffCache.isEmpty()) {
|
||||||
_allRooms.emit(
|
_allRooms.emit(
|
||||||
RoomListRoomSummaryPlaceholders.createFakeList(16).toImmutableList()
|
RoomListRoomSummaryPlaceholders.createFakeList(16).toImmutableList()
|
||||||
|
|
@ -138,7 +122,7 @@ class RoomListDataSource @Inject constructor(
|
||||||
for (index in diffCache.indices()) {
|
for (index in diffCache.indices()) {
|
||||||
val cacheItem = diffCache.get(index)
|
val cacheItem = diffCache.get(index)
|
||||||
if (cacheItem == null) {
|
if (cacheItem == null) {
|
||||||
buildAndCacheItem(roomSummaries, index, notificationsEnabled)?.also { timelineItemState ->
|
buildAndCacheItem(roomSummaries, index)?.also { timelineItemState ->
|
||||||
roomListRoomSummaries.add(timelineItemState)
|
roomListRoomSummaries.add(timelineItemState)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -149,16 +133,12 @@ class RoomListDataSource @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildAndCacheItem(
|
private fun buildAndCacheItem(roomSummaries: List<RoomSummary>, index: Int, ): RoomListRoomSummary? {
|
||||||
roomSummaries: List<RoomSummary>,
|
|
||||||
index: Int,
|
|
||||||
notificationsEnabled: Boolean,
|
|
||||||
): RoomListRoomSummary? {
|
|
||||||
val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) {
|
val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) {
|
||||||
is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
|
is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
|
||||||
is RoomSummary.Filled -> {
|
is RoomSummary.Filled -> {
|
||||||
// Only show a decoration if notifications are enabled and the mode is not ALL_MESSAGES
|
// Only show a decoration if the mode is not ALL_MESSAGES
|
||||||
val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES || !notificationsEnabled) {
|
val notificationMode = if (roomSummary.details.notificationMode == RoomNotificationMode.ALL_MESSAGES) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
roomSummary.details.notificationMode
|
roomSummary.details.notificationMode
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue