Skip to content

Commit 50fbc5e

Browse files
authored
Merge pull request #1330 from vector-im/dla/feature/room_list_decoration
Show a room list decoration for notification setting applied
2 parents 635a4eb + 0d172df commit 50fbc5e

File tree

28 files changed

+228
-43
lines changed

28 files changed

+228
-43
lines changed

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package io.element.android.features.roomlist.impl.components
1919
import androidx.compose.foundation.ExperimentalFoundationApi
2020
import androidx.compose.foundation.combinedClickable
2121
import androidx.compose.foundation.interaction.MutableInteractionSource
22+
import androidx.compose.foundation.layout.Arrangement
2223
import androidx.compose.foundation.layout.Column
2324
import androidx.compose.foundation.layout.IntrinsicSize
2425
import androidx.compose.foundation.layout.Row
@@ -33,6 +34,9 @@ import androidx.compose.runtime.Composable
3334
import androidx.compose.runtime.remember
3435
import androidx.compose.ui.Alignment
3536
import androidx.compose.ui.Modifier
37+
import androidx.compose.ui.graphics.vector.ImageVector
38+
import androidx.compose.ui.res.stringResource
39+
import androidx.compose.ui.res.vectorResource
3640
import androidx.compose.ui.text.AnnotatedString
3741
import androidx.compose.ui.text.style.TextOverflow
3842
import androidx.compose.ui.tooling.preview.Preview
@@ -41,16 +45,20 @@ import androidx.compose.ui.unit.dp
4145
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
4246
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
4347
import io.element.android.libraries.core.extensions.orEmpty
48+
import io.element.android.libraries.designsystem.VectorIcons
4449
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
4550
import io.element.android.libraries.designsystem.components.avatar.Avatar
4651
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
4752
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
53+
import io.element.android.libraries.designsystem.theme.components.Icon
4854
import io.element.android.libraries.designsystem.theme.components.Text
4955
import io.element.android.libraries.designsystem.theme.roomListRoomMessage
5056
import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate
5157
import io.element.android.libraries.designsystem.theme.roomListRoomName
5258
import io.element.android.libraries.designsystem.theme.unreadIndicator
59+
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
5360
import io.element.android.libraries.theme.ElementTheme
61+
import io.element.android.libraries.ui.strings.CommonStrings
5462

5563
internal val minHeight = 84.dp
5664

@@ -161,11 +169,39 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) {
161169
maxLines = 2,
162170
overflow = TextOverflow.Ellipsis
163171
)
172+
164173
// Unread
165-
UnreadIndicatorAtom(
166-
modifier = Modifier.padding(top = 3.dp),
167-
isVisible = room.hasUnread,
168-
)
174+
Row(
175+
horizontalArrangement = Arrangement.spacedBy(8.dp)
176+
) {
177+
NotificationIcon(room)
178+
if (room.hasUnread) {
179+
UnreadIndicatorAtom(
180+
modifier = Modifier.padding(top = 3.dp),
181+
)
182+
}
183+
}
184+
185+
}
186+
187+
@Composable
188+
private fun NotificationIcon(room: RoomListRoomSummary) {
189+
val tint = if(room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary
190+
when(room.notificationMode) {
191+
null, RoomNotificationMode.ALL_MESSAGES -> return
192+
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ->
193+
Icon(
194+
contentDescription = stringResource(CommonStrings.screen_notification_settings_mode_mentions),
195+
imageVector = ImageVector.vectorResource(VectorIcons.Mention),
196+
tint = tint,
197+
)
198+
RoomNotificationMode.MUTE ->
199+
Icon(
200+
contentDescription = stringResource(CommonStrings.common_mute),
201+
imageVector = ImageVector.vectorResource(VectorIcons.Mute),
202+
tint = tint,
203+
)
204+
}
169205
}
170206

171207
@Preview

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,37 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
2727
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
2828
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
2929
import io.element.android.libraries.matrix.api.core.RoomId
30+
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
3031
import io.element.android.libraries.matrix.api.roomlist.RoomListService
3132
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
3233
import kotlinx.collections.immutable.ImmutableList
3334
import kotlinx.collections.immutable.persistentListOf
3435
import kotlinx.collections.immutable.toImmutableList
3536
import kotlinx.coroutines.CoroutineScope
37+
import kotlinx.coroutines.FlowPreview
3638
import kotlinx.coroutines.flow.MutableStateFlow
3739
import kotlinx.coroutines.flow.StateFlow
3840
import kotlinx.coroutines.flow.combine
41+
import kotlinx.coroutines.flow.debounce
3942
import kotlinx.coroutines.flow.launchIn
4043
import kotlinx.coroutines.flow.onEach
4144
import kotlinx.coroutines.sync.Mutex
4245
import kotlinx.coroutines.sync.withLock
4346
import kotlinx.coroutines.withContext
4447
import javax.inject.Inject
48+
import kotlin.time.Duration.Companion.seconds
4549

4650
class RoomListDataSource @Inject constructor(
4751
private val roomListService: RoomListService,
4852
private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
4953
private val roomLastMessageFormatter: RoomLastMessageFormatter,
5054
private val coroutineDispatchers: CoroutineDispatchers,
55+
private val notificationSettingsService: NotificationSettingsService,
56+
private val appScope: CoroutineScope,
5157
) {
58+
init {
59+
observeNotificationSettings()
60+
}
5261

5362
private val _filter = MutableStateFlow("")
5463
private val _allRooms = MutableStateFlow<ImmutableList<RoomListRoomSummary>>(persistentListOf())
@@ -92,6 +101,16 @@ class RoomListDataSource @Inject constructor(
92101
val allRooms: StateFlow<ImmutableList<RoomListRoomSummary>> = _allRooms
93102
val filteredRooms: StateFlow<ImmutableList<RoomListRoomSummary>> = _filteredRooms
94103

104+
@OptIn(FlowPreview::class)
105+
private fun observeNotificationSettings() {
106+
notificationSettingsService.notificationSettingsChangeFlow
107+
.debounce(0.5.seconds)
108+
.onEach {
109+
roomListService.rebuildRoomSummaries()
110+
}
111+
.launchIn(appScope)
112+
}
113+
95114
private suspend fun replaceWith(roomSummaries: List<RoomSummary>) = withContext(coroutineDispatchers.computation) {
96115
lock.withLock {
97116
diffCacheUpdater.updateWith(roomSummaries)
@@ -120,10 +139,7 @@ class RoomListDataSource @Inject constructor(
120139
}
121140
}
122141

123-
private fun buildAndCacheItem(
124-
roomSummaries: List<RoomSummary>,
125-
index: Int
126-
): RoomListRoomSummary? {
142+
private fun buildAndCacheItem(roomSummaries: List<RoomSummary>, index: Int): RoomListRoomSummary? {
127143
val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) {
128144
is RoomSummary.Empty -> RoomListRoomSummaryPlaceholders.create(roomSummary.identifier)
129145
is RoomSummary.Filled -> {
@@ -144,10 +160,12 @@ class RoomListDataSource @Inject constructor(
144160
roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect)
145161
}.orEmpty(),
146162
avatarData = avatarData,
163+
notificationMode = roomSummary.details.notificationMode,
147164
)
148165
}
149166
null -> null
150167
}
168+
151169
diffCache[index] = roomListRoomSummary
152170
return roomListRoomSummary
153171
}

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummary.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.compose.runtime.Immutable
2020
import io.element.android.libraries.designsystem.components.avatar.AvatarData
2121
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
2222
import io.element.android.libraries.matrix.api.core.RoomId
23+
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
2324

2425
@Immutable
2526
data class RoomListRoomSummary constructor(
@@ -31,4 +32,5 @@ data class RoomListRoomSummary constructor(
3132
val lastMessage: CharSequence? = null,
3233
val avatarData: AvatarData = AvatarData(id, name, size = AvatarSize.RoomListItem),
3334
val isPlaceholder: Boolean = false,
35+
val notificationMode: RoomNotificationMode? = null,
3436
)

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/model/RoomListRoomSummaryProvider.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
2020
import io.element.android.libraries.designsystem.components.avatar.AvatarData
2121
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
2222
import io.element.android.libraries.matrix.api.core.RoomId
23+
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
2324

2425
open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSummary> {
2526
override val values: Sequence<RoomListRoomSummary>
2627
get() = sequenceOf(
2728
aRoomListRoomSummary(),
2829
aRoomListRoomSummary().copy(lastMessage = null),
29-
aRoomListRoomSummary().copy(hasUnread = true),
30-
aRoomListRoomSummary().copy(timestamp = "88:88"),
30+
aRoomListRoomSummary().copy(hasUnread = true, notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY),
31+
aRoomListRoomSummary().copy(timestamp = "88:88", notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY),
32+
aRoomListRoomSummary().copy(timestamp = "88:88", notificationMode = RoomNotificationMode.MUTE),
3133
aRoomListRoomSummary().copy(timestamp = "88:88", hasUnread = true),
3234
aRoomListRoomSummary().copy(isPlaceholder = true, timestamp = "88:88"),
3335
aRoomListRoomSummary().copy(

0 commit comments

Comments
 (0)