Browse Source

Update dependency org.matrix.rustcomponents:sdk-android to v0.2.31 (#3145)

* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.31

* Use new Rust client side sorting API

* Make `RoomListEntriesUpdate.describe()` an extension function

* Remove `RoomListSummary.Filled` and `RoomListSummary.Empty`

* Fix icon sizes to pass the lint checks

* Update screenshots

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jorge Martín <jorgem@element.io>
Co-authored-by: ElementBot <benoitm+elementbot@element.io>
pull/3154/head
renovate[bot] 2 months ago committed by GitHub
parent
commit
68efc918ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. BIN
      appicon/enterprise/src/main/res/mipmap-hdpi/ic_launcher_background_enterprise.webp
  2. BIN
      appicon/enterprise/src/main/res/mipmap-mdpi/ic_launcher_background_enterprise.webp
  3. BIN
      appicon/enterprise/src/main/res/mipmap-xhdpi/ic_launcher_background_enterprise.webp
  4. BIN
      appicon/enterprise/src/main/res/mipmap-xxhdpi/ic_launcher_background_enterprise.webp
  5. BIN
      appicon/enterprise/src/main/res/mipmap-xxhdpi/ic_launcher_foreground_enterprise.webp
  6. BIN
      appicon/enterprise/src/main/res/mipmap-xxxhdpi/ic_launcher_background_enterprise.webp
  7. 6
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesPresenterTest.kt
  8. 14
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt
  9. 2
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingState.kt
  10. 17
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateProvider.kt
  11. 10
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt
  12. 9
      features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt
  13. 1
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt
  14. 13
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
  15. 24
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt
  16. 12
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListDataSource.kt
  17. 36
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/datasource/RoomListRoomSummaryFactory.kt
  18. 2
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchDataSource.kt
  19. 52
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt
  20. 8
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchPresenterTest.kt
  21. 2
      gradle/libs.versions.toml
  22. 6
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt
  23. 14
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt
  24. 2
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
  25. 57
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt
  26. 5
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt
  27. 14
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilter.kt
  28. 6
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt
  29. 43
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt
  30. 18
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt
  31. 45
      libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilterTest.kt
  32. 123
      libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt
  33. 31
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt
  34. 7
      libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt
  35. 8
      libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt
  36. 10
      libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt
  37. 4
      libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomSummaryExtension.kt
  38. 4
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvents.kt
  39. 4
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt
  40. 5
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectSearchDataSource.kt
  41. 6
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectState.kt
  42. 6
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt
  43. 14
      libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt
  44. 11
      libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt
  45. 4
      tests/uitests/src/test/snapshots/images/appicon.enterprise_Icon_en.png
  46. 4
      tests/uitests/src/test/snapshots/images/appicon.enterprise_RoundIcon_en.png

BIN
appicon/enterprise/src/main/res/mipmap-hdpi/ic_launcher_background_enterprise.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
appicon/enterprise/src/main/res/mipmap-mdpi/ic_launcher_background_enterprise.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
appicon/enterprise/src/main/res/mipmap-xhdpi/ic_launcher_background_enterprise.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
appicon/enterprise/src/main/res/mipmap-xxhdpi/ic_launcher_background_enterprise.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
appicon/enterprise/src/main/res/mipmap-xxhdpi/ic_launcher_foreground_enterprise.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
appicon/enterprise/src/main/res/mipmap-xxxhdpi/ic_launcher_background_enterprise.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 14 KiB

6
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesPresenterTest.kt

@ -25,7 +25,7 @@ import io.element.android.libraries.matrix.api.core.EventId @@ -25,7 +25,7 @@ import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider
import io.element.android.tests.testutils.WarmUpRule
@ -64,7 +64,7 @@ class ForwardMessagesPresenterTest { @@ -64,7 +64,7 @@ class ForwardMessagesPresenterTest {
presenter.present()
}.test {
skipItems(1)
val summary = aRoomSummaryDetails()
val summary = aRoomSummary()
presenter.onRoomSelected(listOf(summary.roomId))
val forwardingState = awaitItem()
assertThat(forwardingState.forwardAction.isLoading()).isTrue()
@ -88,7 +88,7 @@ class ForwardMessagesPresenterTest { @@ -88,7 +88,7 @@ class ForwardMessagesPresenterTest {
presenter.present()
}.test {
skipItems(1)
val summary = aRoomSummaryDetails()
val summary = aRoomSummary()
presenter.onRoomSelected(listOf(summary.roomId))
skipItems(1)
val failedForwardState = awaitItem()

14
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt

@ -66,7 +66,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor( @@ -66,7 +66,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
val changeNotificationSettingAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val roomsWithUserDefinedMode: MutableState<List<RoomSummary.Filled>> = remember {
val roomsWithUserDefinedMode: MutableState<List<RoomSummary>> = remember {
mutableStateOf(listOf())
}
@ -115,7 +115,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor( @@ -115,7 +115,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
.launchIn(this)
}
private fun CoroutineScope.observeRoomSummaries(roomsWithUserDefinedMode: MutableState<List<RoomSummary.Filled>>) {
private fun CoroutineScope.observeRoomSummaries(roomsWithUserDefinedMode: MutableState<List<RoomSummary>>) {
roomListService.allRooms
.summaries
.onEach {
@ -126,18 +126,18 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor( @@ -126,18 +126,18 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
private fun CoroutineScope.updateRoomsWithUserDefinedMode(
summaries: List<RoomSummary>,
roomsWithUserDefinedMode: MutableState<List<RoomSummary.Filled>>
roomsWithUserDefinedMode: MutableState<List<RoomSummary>>
) = launch {
val roomWithUserDefinedRules: Set<String> = notificationSettingsService.getRoomsWithUserDefinedRules().getOrThrow().toSet()
val sortedSummaries = summaries
.filterIsInstance<RoomSummary.Filled>()
.filterIsInstance<RoomSummary>()
.filter {
val room = matrixClient.getRoom(it.details.roomId) ?: return@filter false
roomWithUserDefinedRules.contains(it.identifier()) && isOneToOne == room.isOneToOne
val room = matrixClient.getRoom(it.roomId) ?: return@filter false
roomWithUserDefinedRules.contains(it.roomId.value) && isOneToOne == room.isOneToOne
}
// locale sensitive sorting
.sortedWith(compareBy(Collator.getInstance()) { it.details.name })
.sortedWith(compareBy(Collator.getInstance()) { it.name })
roomsWithUserDefinedMode.value = sortedSummaries
}

2
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingState.kt

@ -24,7 +24,7 @@ import kotlinx.collections.immutable.ImmutableList @@ -24,7 +24,7 @@ import kotlinx.collections.immutable.ImmutableList
data class EditDefaultNotificationSettingState(
val isOneToOne: Boolean,
val mode: RoomNotificationMode?,
val roomsWithUserDefinedMode: ImmutableList<RoomSummary.Filled>,
val roomsWithUserDefinedMode: ImmutableList<RoomSummary>,
val changeNotificationSettingAction: AsyncAction<Unit>,
val displayMentionsOnlyDisclaimer: Boolean,
val eventSink: (EditDefaultNotificationSettingStateEvents) -> Unit,

17
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingStateProvider.kt

@ -20,7 +20,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider @@ -20,7 +20,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.ui.components.aRoomSummaryDetails
import kotlinx.collections.immutable.persistentListOf
@ -53,13 +52,11 @@ private fun anEditDefaultNotificationSettingsState( @@ -53,13 +52,11 @@ private fun anEditDefaultNotificationSettingsState(
private fun aRoomSummary(
name: String?,
) = RoomSummary.Filled(
aRoomSummaryDetails(
roomId = RoomId("!roomId:domain"),
name = name,
avatarUrl = null,
isDirect = false,
lastMessage = null,
notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
)
) = aRoomSummaryDetails(
roomId = RoomId("!roomId:domain"),
name = name,
avatarUrl = null,
isDirect = false,
lastMessage = null,
notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
)

10
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt

@ -89,7 +89,7 @@ fun EditDefaultNotificationSettingView( @@ -89,7 +89,7 @@ fun EditDefaultNotificationSettingView(
if (state.roomsWithUserDefinedMode.isNotEmpty()) {
PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_edit_custom_settings_section_title)) {
state.roomsWithUserDefinedMode.forEach { summary ->
val subtitle = when (summary.details.userDefinedNotificationMode) {
val subtitle = when (summary.userDefinedNotificationMode) {
RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages)
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> {
stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords)
@ -99,7 +99,7 @@ fun EditDefaultNotificationSettingView( @@ -99,7 +99,7 @@ fun EditDefaultNotificationSettingView(
}
ListItem(
headlineContent = {
val roomName = summary.details.name
val roomName = summary.name
Text(
text = roomName ?: stringResource(id = CommonStrings.common_no_room_name),
fontStyle = FontStyle.Italic.takeIf { roomName == null }
@ -110,14 +110,14 @@ fun EditDefaultNotificationSettingView( @@ -110,14 +110,14 @@ fun EditDefaultNotificationSettingView(
},
leadingContent = ListItemContent.Custom {
CompositeAvatar(
avatarData = summary.details.getAvatarData(size = AvatarSize.CustomRoomNotificationSetting),
heroes = summary.details.heroes.map { user ->
avatarData = summary.getAvatarData(size = AvatarSize.CustomRoomNotificationSetting),
heroes = summary.heroes.map { user ->
user.getAvatarData(size = AvatarSize.CustomRoomNotificationSetting)
}.toPersistentList()
)
},
onClick = {
openRoomNotificationSettings(summary.details.roomId)
openRoomNotificationSettings(summary.roomId)
}
)
}

9
features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt

@ -23,13 +23,12 @@ import com.google.common.truth.Truth.assertThat @@ -23,13 +23,12 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingPresenter
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingStateEvents
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.tests.testutils.awaitLastSequentialItem
import io.element.android.tests.testutils.consumeItemsUntilPredicate
@ -72,11 +71,11 @@ class EditDefaultNotificationSettingsPresenterTest { @@ -72,11 +71,11 @@ class EditDefaultNotificationSettingsPresenterTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
roomListService.postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetails(notificationMode = RoomNotificationMode.ALL_MESSAGES))))
roomListService.postAllRooms(listOf(aRoomSummary(notificationMode = RoomNotificationMode.ALL_MESSAGES)))
val loadedState = consumeItemsUntilPredicate { state ->
state.roomsWithUserDefinedMode.any { it.details.userDefinedNotificationMode == RoomNotificationMode.ALL_MESSAGES }
state.roomsWithUserDefinedMode.any { it.userDefinedNotificationMode == RoomNotificationMode.ALL_MESSAGES }
}.last()
assertThat(loadedState.roomsWithUserDefinedMode.any { it.details.userDefinedNotificationMode == RoomNotificationMode.ALL_MESSAGES }).isTrue()
assertThat(loadedState.roomsWithUserDefinedMode.any { it.userDefinedNotificationMode == RoomNotificationMode.ALL_MESSAGES }).isTrue()
}
}

1
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt

@ -20,7 +20,6 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary @@ -20,7 +20,6 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.libraries.matrix.api.core.RoomId
sealed interface RoomListEvents {
data class UpdateVisibleRange(val range: IntRange) : RoomListEvents
data object DismissRequestVerificationPrompt : RoomListEvents
data object DismissRecoveryKeyPrompt : RoomListEvents
data object ToggleSearchResults : RoomListEvents

13
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt

@ -78,8 +78,6 @@ import kotlinx.coroutines.flow.takeWhile @@ -78,8 +78,6 @@ import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.launch
import javax.inject.Inject
private const val EXTENDED_RANGE_SIZE = 40
class RoomListPresenter @Inject constructor(
private val client: MatrixClient,
private val networkMonitor: NetworkMonitor,
@ -124,7 +122,6 @@ class RoomListPresenter @Inject constructor( @@ -124,7 +122,6 @@ class RoomListPresenter @Inject constructor(
fun handleEvents(event: RoomListEvents) {
when (event) {
is RoomListEvents.UpdateVisibleRange -> updateVisibleRange(event.range)
RoomListEvents.DismissRequestVerificationPrompt -> securityBannerDismissed = true
RoomListEvents.DismissRecoveryKeyPrompt -> securityBannerDismissed = true
RoomListEvents.ToggleSearchResults -> searchState.eventSink(RoomListSearchEvents.ToggleSearchVisibility)
@ -286,16 +283,6 @@ class RoomListPresenter @Inject constructor( @@ -286,16 +283,6 @@ class RoomListPresenter @Inject constructor(
}
}
}
private fun updateVisibleRange(range: IntRange) {
if (range.isEmpty()) return
val midExtendedRangeSize = EXTENDED_RANGE_SIZE / 2
val extendedRangeStart = (range.first - midExtendedRangeSize).coerceAtLeast(0)
// Safe to give bigger size than room list
val extendedRangeEnd = range.last + midExtendedRangeSize
val extendedRange = IntRange(extendedRangeStart, extendedRangeEnd)
client.roomListService.updateAllRoomsVisibleRange(extendedRange)
}
}
@VisibleForTesting

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

@ -30,17 +30,11 @@ import androidx.compose.foundation.lazy.LazyColumn @@ -30,17 +30,11 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
@ -171,25 +165,9 @@ private fun RoomsViewList( @@ -171,25 +165,9 @@ private fun RoomsViewList(
modifier: Modifier = Modifier,
) {
val lazyListState = rememberLazyListState()
val visibleRange by remember {
derivedStateOf {
val layoutInfo = lazyListState.layoutInfo
val firstItemIndex = layoutInfo.visibleItemsInfo.firstOrNull()?.index ?: 0
val size = layoutInfo.visibleItemsInfo.size
firstItemIndex until firstItemIndex + size
}
}
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
eventSink(RoomListEvents.UpdateVisibleRange(visibleRange))
return super.onPostFling(consumed, available)
}
}
}
LazyColumn(
state = lazyListState,
modifier = modifier.nestedScroll(nestedScrollConnection),
modifier = modifier,
// FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80
contentPadding = PaddingValues(bottom = 80.dp)
) {

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

@ -54,7 +54,7 @@ class RoomListDataSource @Inject constructor( @@ -54,7 +54,7 @@ class RoomListDataSource @Inject constructor(
private val lock = Mutex()
private val diffCache = MutableListDiffCache<RoomListRoomSummary>()
private val diffCacheUpdater = DiffCacheUpdater<RoomSummary, RoomListRoomSummary>(diffCache = diffCache, detectMoves = true) { old, new ->
old?.identifier() == new?.identifier()
old?.roomId == new?.roomId
}
fun launchIn(coroutineScope: CoroutineScope) {
@ -96,12 +96,8 @@ class RoomListDataSource @Inject constructor( @@ -96,12 +96,8 @@ class RoomListDataSource @Inject constructor(
}
private fun buildAndCacheItem(roomSummaries: List<RoomSummary>, index: Int): RoomListRoomSummary? {
val roomListRoomSummary = when (val roomSummary = roomSummaries.getOrNull(index)) {
is RoomSummary.Empty -> RoomListRoomSummaryFactory.createPlaceholder(roomSummary.identifier)
is RoomSummary.Filled -> roomListRoomSummaryFactory.create(roomSummary)
null -> null
}
diffCache[index] = roomListRoomSummary
return roomListRoomSummary
val roomListSummary = roomSummaries.getOrNull(index)?.let { roomListRoomSummaryFactory.create(it) }
diffCache[index] = roomListSummary
return roomListSummary
}
}

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

@ -20,16 +20,12 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary @@ -20,16 +20,12 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
import io.element.android.libraries.core.extensions.orEmpty
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
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.core.RoomId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.matrix.ui.model.toInviteSender
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject
@ -37,37 +33,7 @@ class RoomListRoomSummaryFactory @Inject constructor( @@ -37,37 +33,7 @@ class RoomListRoomSummaryFactory @Inject constructor(
private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
private val roomLastMessageFormatter: RoomLastMessageFormatter,
) {
companion object {
fun createPlaceholder(id: String): RoomListRoomSummary {
return RoomListRoomSummary(
id = id,
roomId = RoomId(id),
displayType = RoomSummaryDisplayType.PLACEHOLDER,
name = "Short name",
timestamp = "hh:mm",
lastMessage = "Last message for placeholder",
avatarData = AvatarData(id, "S", size = AvatarSize.RoomListItem),
numberOfUnreadMessages = 0,
numberOfUnreadMentions = 0,
numberOfUnreadNotifications = 0,
isMarkedUnread = false,
userDefinedNotificationMode = null,
hasRoomCall = false,
isDirect = false,
isFavorite = false,
inviteSender = null,
isDm = false,
canonicalAlias = null,
heroes = persistentListOf(),
)
}
}
fun create(roomSummary: RoomSummary.Filled): RoomListRoomSummary {
return create(roomSummary.details)
}
private fun create(details: RoomSummaryDetails): RoomListRoomSummary {
fun create(details: RoomSummary): RoomListRoomSummary {
val avatarData = details.getAvatarData(size = AvatarSize.RoomListItem)
return RoomListRoomSummary(
id = details.roomId.value,

2
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchDataSource.kt

@ -22,7 +22,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -22,7 +22,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
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.loadAllIncrementally
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
@ -48,7 +47,6 @@ class RoomListSearchDataSource @Inject constructor( @@ -48,7 +47,6 @@ class RoomListSearchDataSource @Inject constructor(
val roomSummaries: Flow<PersistentList<RoomListRoomSummary>> = roomList.filteredSummaries
.map { roomSummaries ->
roomSummaries
.filterIsInstance<RoomSummary.Filled>()
.map(roomSummaryFactory::create)
.toPersistentList()
}

52
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt

@ -68,7 +68,7 @@ import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService @@ -68,7 +68,7 @@ import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
@ -183,7 +183,7 @@ class RoomListPresenterTest { @@ -183,7 +183,7 @@ class RoomListPresenterTest {
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
roomListService.postAllRooms(
listOf(
aRoomSummaryFilled(
aRoomSummary(
numUnreadMentions = 1,
numUnreadMessages = 2,
)
@ -203,48 +203,6 @@ class RoomListPresenterTest { @@ -203,48 +203,6 @@ class RoomListPresenterTest {
}
}
@Test
fun `present - update visible range`() = runTest {
val roomListService = FakeRoomListService()
val matrixClient = FakeMatrixClient(
roomListService = roomListService
)
val scope = CoroutineScope(coroutineContext + SupervisorJob())
val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
roomListService.postAllRooms(listOf(aRoomSummaryFilled()))
val loadedState = awaitItem()
// check initial value
assertThat(roomListService.latestSlidingSyncRange).isNull()
// Test empty range
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(1, 0)))
assertThat(roomListService.latestSlidingSyncRange).isNull()
// Update visible range and check that range is transmitted to the SDK after computation
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(0, 0)))
assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(0, 20))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(0, 1)))
assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(0, 21))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(19, 29)))
assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(0, 49))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(49, 59)))
assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(29, 79))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(149, 159)))
assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(129, 179))
loadedState.eventSink.invoke(RoomListEvents.UpdateVisibleRange(IntRange(149, 259)))
assertThat(roomListService.latestSlidingSyncRange)
.isEqualTo(IntRange(129, 279))
cancelAndIgnoreRemainingEvents()
scope.cancel()
}
}
@Test
fun `present - handle DismissRequestVerificationPrompt`() = runTest {
val scope = CoroutineScope(context = coroutineContext + SupervisorJob())
@ -449,7 +407,7 @@ class RoomListPresenterTest { @@ -449,7 +407,7 @@ class RoomListPresenterTest {
val notificationSettingsService = FakeNotificationSettingsService()
val roomListService = FakeRoomListService()
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
roomListService.postAllRooms(listOf(aRoomSummaryFilled(notificationMode = userDefinedMode)))
roomListService.postAllRooms(listOf(aRoomSummary(notificationMode = userDefinedMode)))
val matrixClient = FakeMatrixClient(
roomListService = roomListService,
notificationSettingsService = notificationSettingsService
@ -594,7 +552,7 @@ class RoomListPresenterTest { @@ -594,7 +552,7 @@ class RoomListPresenterTest {
val matrixClient = FakeMatrixClient(
roomListService = roomListService,
)
val roomSummary = aRoomSummaryFilled(
val roomSummary = aRoomSummary(
currentUserMembership = CurrentUserMembership.INVITED
)
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
@ -610,7 +568,7 @@ class RoomListPresenterTest { @@ -610,7 +568,7 @@ class RoomListPresenterTest {
}.last()
val roomListRoomSummary = state.contentAsRooms().summaries.first {
it.id == roomSummary.identifier()
it.id == roomSummary.roomId.value
}
state.eventSink(RoomListEvents.AcceptInvite(roomListRoomSummary))
state.eventSink(RoomListEvents.DeclineInvite(roomListRoomSummary))

8
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchPresenterTest.kt

@ -28,8 +28,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags @@ -28,8 +28,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
@ -117,10 +116,7 @@ class RoomListSearchPresenterTest { @@ -117,10 +116,7 @@ class RoomListSearchPresenterTest {
assertThat(state.results).isEmpty()
}
roomListService.postAllRooms(
listOf(
RoomSummary.Empty("1"),
aRoomSummaryFilled()
)
listOf(aRoomSummary())
)
awaitItem().let { state ->
assertThat(state.results).hasSize(1)

2
gradle/libs.versions.toml

@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.17.2" @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.17.2"
appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" }
molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0"
timber = "com.jakewharton.timber:timber:5.0.1"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.30"
matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.31"
matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" }
matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" }
sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }

6
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListService.kt

@ -59,12 +59,6 @@ interface RoomListService { @@ -59,12 +59,6 @@ interface RoomListService {
*/
val allRooms: DynamicRoomList
/**
* Will set the visible range of all rooms.
* This is useful to load more data when the user scrolls down.
*/
fun updateAllRoomsVisibleRange(range: IntRange)
/**
* The sync indicator as a flow.
*/

14
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt

@ -24,19 +24,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode @@ -24,19 +24,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.message.RoomMessage
import io.element.android.libraries.matrix.api.user.MatrixUser
sealed interface RoomSummary {
data class Empty(val identifier: String) : RoomSummary
data class Filled(val details: RoomSummaryDetails) : RoomSummary
fun identifier(): String {
return when (this) {
is Empty -> identifier
is Filled -> details.roomId.value
}
}
}
data class RoomSummaryDetails(
data class RoomSummary(
val roomId: RoomId,
val name: String?,
val canonicalAlias: RoomAlias?,

2
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt

@ -311,7 +311,7 @@ class RustMatrixClient( @@ -311,7 +311,7 @@ class RustMatrixClient(
withTimeout(timeout) {
roomListService.allRooms.summaries
.filter { roomSummaries ->
roomSummaries.map { it.identifier() }.contains(roomId.value)
roomSummaries.map { it.roomId }.contains(roomId)
}
.first()
}

57
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
/*
* Copyright (c) 2024 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
*
* https://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 io.element.android.libraries.matrix.impl.roomlist
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
internal fun RoomListEntriesUpdate.describe(): String {
return when (this) {
is RoomListEntriesUpdate.Set -> {
"Set #$index to '${value.displayName()}'"
}
is RoomListEntriesUpdate.Append -> {
"Append ${values.map { "'" + it.displayName() + "'" }}"
}
is RoomListEntriesUpdate.PushBack -> {
"PushBack '${value.displayName()}'"
}
is RoomListEntriesUpdate.PushFront -> {
"PushFront '${value.displayName()}'"
}
is RoomListEntriesUpdate.Insert -> {
"Insert at #$index: '${value.displayName()}'"
}
is RoomListEntriesUpdate.Remove -> {
"Remove #$index"
}
is RoomListEntriesUpdate.Reset -> {
"Reset all to ${values.map { "'" + it.displayName() + "'" }}"
}
RoomListEntriesUpdate.PopBack -> {
"PopBack"
}
RoomListEntriesUpdate.PopFront -> {
"PopFront"
}
RoomListEntriesUpdate.Clear -> {
"Clear"
}
is RoomListEntriesUpdate.Truncate -> {
"Truncate to $length items"
}
}
}

5
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListExtensions.kt

@ -76,7 +76,7 @@ internal fun RoomListInterface.entriesFlow( @@ -76,7 +76,7 @@ internal fun RoomListInterface.entriesFlow(
}
}
val result = entriesWithDynamicAdapters(pageSize.toUInt(), listener)
val controller = result.controller
val controller = result.controller()
controller.setFilter(initialFilterKind)
roomListDynamicEvents.onEach { controllerEvents ->
when (controllerEvents) {
@ -92,7 +92,8 @@ internal fun RoomListInterface.entriesFlow( @@ -92,7 +92,8 @@ internal fun RoomListInterface.entriesFlow(
}
}.launchIn(this)
awaitClose {
result.entriesStream.cancelAndDestroy()
result.entriesStream().cancelAndDestroy()
controller.destroy()
result.destroy()
}
}.catch {

14
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilter.kt

@ -26,21 +26,19 @@ val RoomListFilter.predicate @@ -26,21 +26,19 @@ val RoomListFilter.predicate
is RoomListFilter.Any -> { _: RoomSummary -> true }
RoomListFilter.None -> { _: RoomSummary -> false }
RoomListFilter.Category.Group -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && !roomSummary.details.isDirect && !roomSummary.isInvited()
!roomSummary.isDirect && !roomSummary.isInvited()
}
RoomListFilter.Category.People -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && roomSummary.details.isDirect && !roomSummary.isInvited()
roomSummary.isDirect && !roomSummary.isInvited()
}
RoomListFilter.Favorite -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && roomSummary.details.isFavorite && !roomSummary.isInvited()
roomSummary.isFavorite && !roomSummary.isInvited()
}
RoomListFilter.Unread -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled &&
!roomSummary.isInvited() &&
(roomSummary.details.numUnreadNotifications > 0 || roomSummary.details.isMarkedUnread)
!roomSummary.isInvited() && (roomSummary.numUnreadNotifications > 0 || roomSummary.isMarkedUnread)
}
is RoomListFilter.NormalizedMatchRoomName -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && roomSummary.details.name.orEmpty().contains(pattern, ignoreCase = true)
roomSummary.name.orEmpty().contains(pattern, ignoreCase = true)
}
RoomListFilter.Invite -> { roomSummary: RoomSummary ->
roomSummary.isInvited()
@ -61,4 +59,4 @@ fun List<RoomSummary>.filter(filter: RoomListFilter): List<RoomSummary> { @@ -61,4 +59,4 @@ fun List<RoomSummary>.filter(filter: RoomListFilter): List<RoomSummary> {
}
}
private fun RoomSummary.isInvited() = this is RoomSummary.Filled && this.details.currentUserMembership == CurrentUserMembership.INVITED
private fun RoomSummary.isInvited() = currentUserMembership == CurrentUserMembership.INVITED

6
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt

@ -18,7 +18,7 @@ package io.element.android.libraries.matrix.impl.roomlist @@ -18,7 +18,7 @@ package io.element.android.libraries.matrix.impl.roomlist
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.impl.notificationsettings.RoomNotificationSettingsMapper
import io.element.android.libraries.matrix.impl.room.elementHeroes
import io.element.android.libraries.matrix.impl.room.map
@ -28,12 +28,12 @@ import org.matrix.rustcomponents.sdk.RoomListItem @@ -28,12 +28,12 @@ import org.matrix.rustcomponents.sdk.RoomListItem
import org.matrix.rustcomponents.sdk.use
class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory()) {
suspend fun create(roomListItem: RoomListItem): RoomSummaryDetails {
suspend fun create(roomListItem: RoomListItem): RoomSummary {
val roomInfo = roomListItem.roomInfo()
val latestRoomMessage = roomListItem.latestEvent()?.use {
roomMessageFactory.create(it)
}
return RoomSummaryDetails(
return RoomSummary(
roomId = RoomId(roomInfo.id),
name = roomInfo.displayName,
canonicalAlias = roomInfo.canonicalAlias?.let(::RoomAlias),

43
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessor.kt

@ -22,11 +22,10 @@ import kotlinx.coroutines.sync.Mutex @@ -22,11 +22,10 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
import org.matrix.rustcomponents.sdk.RoomListEntry
import org.matrix.rustcomponents.sdk.RoomListItem
import org.matrix.rustcomponents.sdk.RoomListServiceInterface
import org.matrix.rustcomponents.sdk.use
import timber.log.Timber
import java.util.UUID
import kotlin.coroutines.CoroutineContext
class RoomSummaryListProcessor(
@ -50,15 +49,17 @@ class RoomSummaryListProcessor( @@ -50,15 +49,17 @@ class RoomSummaryListProcessor(
suspend fun rebuildRoomSummaries() {
updateRoomSummaries {
forEachIndexed { i, summary ->
this[i] = when (summary) {
is RoomSummary.Empty -> summary
is RoomSummary.Filled -> buildAndCacheRoomSummaryForIdentifier(summary.identifier())
val result = buildAndCacheRoomSummaryForIdentifier(summary.roomId.value)
if (result != null) {
this[i] = result
}
}
}
}
private suspend fun MutableList<RoomSummary>.applyUpdate(update: RoomListEntriesUpdate) {
// Remove this comment to debug changes in the room list
// Timber.d("Apply room list update: ${update.describe()}")
when (update) {
is RoomListEntriesUpdate.Append -> {
val roomSummaries = update.values.map {
@ -104,27 +105,25 @@ class RoomSummaryListProcessor( @@ -104,27 +105,25 @@ class RoomSummaryListProcessor(
}
}
private suspend fun buildSummaryForRoomListEntry(entry: RoomListEntry): RoomSummary {
return when (entry) {
RoomListEntry.Empty -> buildEmptyRoomSummary()
is RoomListEntry.Filled -> buildAndCacheRoomSummaryForIdentifier(entry.roomId)
is RoomListEntry.Invalidated -> {
roomSummariesByIdentifier[entry.roomId] ?: buildAndCacheRoomSummaryForIdentifier(entry.roomId)
}
}
private suspend fun buildSummaryForRoomListEntry(entry: RoomListItem): RoomSummary {
return buildAndCacheRoomSummaryForRoomListItem(entry)
}
private fun buildEmptyRoomSummary(): RoomSummary {
return RoomSummary.Empty(UUID.randomUUID().toString())
private suspend fun buildAndCacheRoomSummaryForIdentifier(identifier: String): RoomSummary? {
val builtRoomSummary = roomListService.roomOrNull(identifier)?.use { roomListItem ->
buildAndCacheRoomSummaryForRoomListItem(roomListItem)
}
if (builtRoomSummary != null) {
roomSummariesByIdentifier[identifier] = builtRoomSummary
} else {
roomSummariesByIdentifier.remove(identifier)
}
return builtRoomSummary
}
private suspend fun buildAndCacheRoomSummaryForIdentifier(identifier: String): RoomSummary {
val builtRoomSummary = roomListService.roomOrNull(identifier)?.use { roomListItem ->
RoomSummary.Filled(
details = roomSummaryDetailsFactory.create(roomListItem)
)
} ?: buildEmptyRoomSummary()
roomSummariesByIdentifier[builtRoomSummary.identifier()] = builtRoomSummary
private suspend fun buildAndCacheRoomSummaryForRoomListItem(roomListItem: RoomListItem): RoomSummary {
val builtRoomSummary = roomSummaryDetailsFactory.create(roomListItem = roomListItem)
roomSummariesByIdentifier[builtRoomSummary.roomId.value] = builtRoomSummary
return builtRoomSummary
}

18
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt

@ -29,10 +29,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged @@ -29,10 +29,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.matrix.rustcomponents.sdk.RoomListException
import org.matrix.rustcomponents.sdk.RoomListInput
import org.matrix.rustcomponents.sdk.RoomListRange
import org.matrix.rustcomponents.sdk.RoomListServiceState
import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator
import timber.log.Timber
@ -73,20 +69,6 @@ internal class RustRoomListService( @@ -73,20 +69,6 @@ internal class RustRoomListService(
allRooms.loadAllIncrementally(sessionCoroutineScope)
}
override fun updateAllRoomsVisibleRange(range: IntRange) {
Timber.v("setVisibleRange=$range")
sessionCoroutineScope.launch {
try {
val ranges = listOf(RoomListRange(range.first.toUInt(), range.last.toUInt()))
innerRoomListService.applyInput(
RoomListInput.Viewport(ranges)
)
} catch (exception: RoomListException) {
Timber.e(exception, "Failed updating visible range")
}
}
}
override val syncIndicator: StateFlow<RoomListService.SyncIndicator> =
innerRoomListService.syncIndicator()
.map { it.toSyncIndicator() }

45
libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilterTest.kt

@ -19,46 +19,31 @@ package io.element.android.libraries.matrix.impl.roomlist @@ -19,46 +19,31 @@ package io.element.android.libraries.matrix.impl.roomlist
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import io.element.android.libraries.matrix.test.room.aRoomSummary
import kotlinx.coroutines.test.runTest
import org.junit.Test
class RoomListFilterTest {
private val regularRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
isDirect = false
)
private val regularRoom = aRoomSummary(
isDirect = false
)
private val directRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
isDirect = true
)
private val directRoom = aRoomSummary(
isDirect = true
)
private val favoriteRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
isFavorite = true
)
private val favoriteRoom = aRoomSummary(
isFavorite = true
)
private val markedAsUnreadRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
isMarkedUnread = true
)
private val markedAsUnreadRoom = aRoomSummary(
isMarkedUnread = true
)
private val unreadNotificationRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
numUnreadNotifications = 1
)
private val unreadNotificationRoom = aRoomSummary(
numUnreadNotifications = 1
)
private val roomToSearch = aRoomSummaryFilled(
aRoomSummaryDetails(
name = "Room to search"
)
private val roomToSearch = aRoomSummary(
name = "Room to search"
)
private val invitedRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
currentUserMembership = CurrentUserMembership.INVITED
)
private val invitedRoom = aRoomSummary(
currentUserMembership = CurrentUserMembership.INVITED
)
private val roomSummaries = listOf(

123
libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt

@ -18,23 +18,31 @@ package io.element.android.libraries.matrix.impl.roomlist @@ -18,23 +18,31 @@ package io.element.android.libraries.matrix.impl.roomlist
import com.google.common.truth.Truth.assertThat
import com.sun.jna.Pointer
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
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_NAME
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.matrix.rustcomponents.sdk.EventTimelineItem
import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.RoomHero
import org.matrix.rustcomponents.sdk.RoomInfo
import org.matrix.rustcomponents.sdk.RoomList
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
import org.matrix.rustcomponents.sdk.RoomListEntry
import org.matrix.rustcomponents.sdk.RoomListInput
import org.matrix.rustcomponents.sdk.RoomListItem
import org.matrix.rustcomponents.sdk.RoomListServiceInterface
import org.matrix.rustcomponents.sdk.RoomListServiceStateListener
import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener
import org.matrix.rustcomponents.sdk.RoomMember
import org.matrix.rustcomponents.sdk.RoomNotificationMode
import org.matrix.rustcomponents.sdk.TaskHandle
// NOTE: this class is using a fake implementation of a Rust SDK interface which returns actual Rust objects with pointers.
@ -44,33 +52,34 @@ class RoomSummaryListProcessorTest { @@ -44,33 +52,34 @@ class RoomSummaryListProcessorTest {
@Test
fun `Append adds new entries at the end of the list`() = runTest {
summaries.value = listOf(aRoomSummaryFilled())
summaries.value = listOf(aRoomSummary())
val processor = createProcessor()
processor.postUpdate(listOf(RoomListEntriesUpdate.Append(listOf(RoomListEntry.Empty, RoomListEntry.Empty, RoomListEntry.Empty))))
val newEntry = FakeRoomListItem(A_ROOM_ID_2)
processor.postUpdate(listOf(RoomListEntriesUpdate.Append(listOf(newEntry, newEntry, newEntry))))
assertThat(summaries.value.count()).isEqualTo(4)
assertThat(summaries.value.subList(1, 4).all { it is RoomSummary.Empty }).isTrue()
assertThat(summaries.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue()
}
@Test
fun `PushBack adds a new entry at the end of the list`() = runTest {
summaries.value = listOf(aRoomSummaryFilled())
val processor = createProcessor()
processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(RoomListEntry.Empty)))
processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(FakeRoomListItem(A_ROOM_ID_2))))
assertThat(summaries.value.count()).isEqualTo(2)
assertThat(summaries.value.last()).isInstanceOf(RoomSummary.Empty::class.java)
assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2)
}
@Test
fun `PushFront inserts a new entry at the start of the list`() = runTest {
summaries.value = listOf(aRoomSummaryFilled())
val processor = createProcessor()
processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(RoomListEntry.Empty)))
processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(FakeRoomListItem(A_ROOM_ID_2))))
assertThat(summaries.value.count()).isEqualTo(2)
assertThat(summaries.value.first()).isInstanceOf(RoomSummary.Empty::class.java)
assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2)
}
@Test
@ -79,10 +88,10 @@ class RoomSummaryListProcessorTest { @@ -79,10 +88,10 @@ class RoomSummaryListProcessorTest {
val processor = createProcessor()
val index = 0
processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), RoomListEntry.Empty)))
processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), FakeRoomListItem(A_ROOM_ID_2))))
assertThat(summaries.value.count()).isEqualTo(1)
assertThat(summaries.value[index]).isInstanceOf(RoomSummary.Empty::class.java)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Test
@ -91,10 +100,10 @@ class RoomSummaryListProcessorTest { @@ -91,10 +100,10 @@ class RoomSummaryListProcessorTest {
val processor = createProcessor()
val index = 0
processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), RoomListEntry.Empty)))
processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), FakeRoomListItem(A_ROOM_ID_2))))
assertThat(summaries.value.count()).isEqualTo(2)
assertThat(summaries.value[index]).isInstanceOf(RoomSummary.Empty::class.java)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Test
@ -106,7 +115,7 @@ class RoomSummaryListProcessorTest { @@ -106,7 +115,7 @@ class RoomSummaryListProcessorTest {
processor.postUpdate(listOf(RoomListEntriesUpdate.Remove(index.toUInt())))
assertThat(summaries.value.count()).isEqualTo(1)
assertThat((summaries.value[index] as RoomSummary.Filled).identifier()).isEqualTo(A_ROOM_ID_2.value)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Test
@ -118,7 +127,7 @@ class RoomSummaryListProcessorTest { @@ -118,7 +127,7 @@ class RoomSummaryListProcessorTest {
processor.postUpdate(listOf(RoomListEntriesUpdate.PopBack))
assertThat(summaries.value.count()).isEqualTo(1)
assertThat((summaries.value[index] as RoomSummary.Filled).identifier()).isEqualTo(A_ROOM_ID.value)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
}
@Test
@ -130,7 +139,7 @@ class RoomSummaryListProcessorTest { @@ -130,7 +139,7 @@ class RoomSummaryListProcessorTest {
processor.postUpdate(listOf(RoomListEntriesUpdate.PopFront))
assertThat(summaries.value.count()).isEqualTo(1)
assertThat((summaries.value[index] as RoomSummary.Filled).identifier()).isEqualTo(A_ROOM_ID_2.value)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Test
@ -152,7 +161,7 @@ class RoomSummaryListProcessorTest { @@ -152,7 +161,7 @@ class RoomSummaryListProcessorTest {
processor.postUpdate(listOf(RoomListEntriesUpdate.Truncate(1u)))
assertThat(summaries.value.count()).isEqualTo(1)
assertThat((summaries.value[index] as RoomSummary.Filled).identifier()).isEqualTo(A_ROOM_ID.value)
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
}
private fun TestScope.createProcessor() = RoomSummaryListProcessor(
@ -168,8 +177,6 @@ class RoomSummaryListProcessorTest { @@ -168,8 +177,6 @@ class RoomSummaryListProcessorTest {
return RoomList(Pointer.NULL)
}
override suspend fun applyInput(input: RoomListInput) = Unit
override fun room(roomId: String): RoomListItem {
return RoomListItem(Pointer.NULL)
}
@ -183,3 +190,81 @@ class RoomSummaryListProcessorTest { @@ -183,3 +190,81 @@ class RoomSummaryListProcessorTest {
}
}
}
private fun aRustRoomInfo(
id: String = A_ROOM_ID.value,
displayName: String = A_ROOM_NAME,
rawName: String = A_ROOM_NAME,
topic: String? = null,
avatarUrl: String? = null,
isDirect: Boolean = false,
isPublic: Boolean = false,
isSpace: Boolean = false,
isTombstoned: Boolean = false,
isFavourite: Boolean = false,
canonicalAlias: String? = null,
alternativeAliases: List<String> = listOf(),
membership: Membership = Membership.JOINED,
inviter: RoomMember? = null,
heroes: List<RoomHero> = listOf(),
activeMembersCount: ULong = 0uL,
invitedMembersCount: ULong = 0uL,
joinedMembersCount: ULong = 0uL,
userPowerLevels: Map<String, Long> = mapOf(),
highlightCount: ULong = 0uL,
notificationCount: ULong = 0uL,
userDefinedNotificationMode: RoomNotificationMode? = null,
hasRoomCall: Boolean = false,
activeRoomCallParticipants: List<String> = listOf(),
isMarkedUnread: Boolean = false,
numUnreadMessages: ULong = 0uL,
numUnreadNotifications: ULong = 0uL,
numUnreadMentions: ULong = 0uL,
) = RoomInfo(
id = id,
displayName = displayName,
rawName = rawName,
topic = topic,
avatarUrl = avatarUrl,
isDirect = isDirect,
isPublic = isPublic,
isSpace = isSpace,
isTombstoned = isTombstoned,
isFavourite = isFavourite,
canonicalAlias = canonicalAlias,
alternativeAliases = alternativeAliases,
membership = membership,
inviter = inviter,
heroes = heroes,
activeMembersCount = activeMembersCount,
invitedMembersCount = invitedMembersCount,
joinedMembersCount = joinedMembersCount,
userPowerLevels = userPowerLevels,
highlightCount = highlightCount,
notificationCount = notificationCount,
userDefinedNotificationMode = userDefinedNotificationMode,
hasRoomCall = hasRoomCall,
activeRoomCallParticipants = activeRoomCallParticipants,
isMarkedUnread = isMarkedUnread,
numUnreadMessages = numUnreadMessages,
numUnreadNotifications = numUnreadNotifications,
numUnreadMentions = numUnreadMentions
)
class FakeRoomListItem(
private val roomId: RoomId,
private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value),
private val latestEvent: EventTimelineItem? = null,
) : RoomListItem(NoPointer) {
override fun id(): String {
return roomId.value
}
override suspend fun roomInfo(): RoomInfo {
return roomInfo
}
override suspend fun latestEvent(): EventTimelineItem? {
return latestEvent
}
}

31
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt

@ -25,7 +25,6 @@ import io.element.android.libraries.matrix.api.room.RoomMember @@ -25,7 +25,6 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.message.RoomMessage
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.AN_EVENT_ID
@ -44,25 +43,19 @@ fun aRoomSummaryFilled( @@ -44,25 +43,19 @@ fun aRoomSummaryFilled(
numUnreadMessages: Int = 0,
notificationMode: RoomNotificationMode? = null,
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
) = RoomSummary.Filled(
aRoomSummaryDetails(
roomId = roomId,
name = name,
isDirect = isDirect,
avatarUrl = avatarUrl,
lastMessage = lastMessage,
numUnreadMentions = numUnreadMentions,
numUnreadMessages = numUnreadMessages,
notificationMode = notificationMode,
currentUserMembership = currentUserMembership,
)
) = aRoomSummary(
roomId = roomId,
name = name,
isDirect = isDirect,
avatarUrl = avatarUrl,
lastMessage = lastMessage,
numUnreadMentions = numUnreadMentions,
numUnreadMessages = numUnreadMessages,
notificationMode = notificationMode,
currentUserMembership = currentUserMembership,
)
fun aRoomSummaryFilled(
details: RoomSummaryDetails = aRoomSummaryDetails(),
) = RoomSummary.Filled(details)
fun aRoomSummaryDetails(
fun aRoomSummary(
roomId: RoomId = A_ROOM_ID,
name: String? = A_ROOM_NAME,
isDirect: Boolean = false,
@ -80,7 +73,7 @@ fun aRoomSummaryDetails( @@ -80,7 +73,7 @@ fun aRoomSummaryDetails(
isFavorite: Boolean = false,
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
heroes: List<MatrixUser> = emptyList(),
) = RoomSummaryDetails(
) = RoomSummary(
roomId = roomId,
name = name,
isDirect = isDirect,

7
libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomlist/FakeRoomListService.kt

@ -46,9 +46,6 @@ class FakeRoomListService : RoomListService { @@ -46,9 +46,6 @@ class FakeRoomListService : RoomListService {
syncIndicatorStateFlow.emit(value)
}
var latestSlidingSyncRange: IntRange? = null
private set
override fun createRoomList(
pageSize: Int,
initialFilter: RoomListFilter,
@ -65,10 +62,6 @@ class FakeRoomListService : RoomListService { @@ -65,10 +62,6 @@ class FakeRoomListService : RoomListService {
MutableStateFlow(RoomListFilter.all())
)
override fun updateAllRoomsVisibleRange(range: IntRange) {
latestSlidingSyncRange = range
}
override val state: StateFlow<RoomListService.State> = roomListStateFlow
override val syncIndicator: StateFlow<RoomListService.SyncIndicator> = syncIndicatorStateFlow

8
libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/RoomSummaryDetailsProvider.kt

@ -23,11 +23,11 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership @@ -23,11 +23,11 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.message.RoomMessage
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.user.MatrixUser
open class RoomSummaryDetailsProvider : PreviewParameterProvider<RoomSummaryDetails> {
override val values: Sequence<RoomSummaryDetails>
open class RoomSummaryDetailsProvider : PreviewParameterProvider<RoomSummary> {
override val values: Sequence<RoomSummary>
get() = sequenceOf(
aRoomSummaryDetails(),
aRoomSummaryDetails(name = null),
@ -52,7 +52,7 @@ fun aRoomSummaryDetails( @@ -52,7 +52,7 @@ fun aRoomSummaryDetails(
isFavorite: Boolean = false,
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
heroes: List<MatrixUser> = emptyList(),
) = RoomSummaryDetails(
) = RoomSummary(
roomId = roomId,
name = name,
canonicalAlias = canonicalAlias,

10
libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/SelectedRoom.kt

@ -43,15 +43,15 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -43,15 +43,15 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.toImmutableList
@Composable
fun SelectedRoom(
roomSummary: RoomSummaryDetails,
onRemoveRoom: (RoomSummaryDetails) -> Unit,
roomSummary: RoomSummary,
onRemoveRoom: (RoomSummary) -> Unit,
modifier: Modifier = Modifier,
) {
Box(
@ -100,10 +100,10 @@ fun SelectedRoom( @@ -100,10 +100,10 @@ fun SelectedRoom(
@PreviewsDayNight
@Composable
internal fun SelectedRoomPreview(
@PreviewParameter(RoomSummaryDetailsProvider::class) roomSummaryDetails: RoomSummaryDetails
@PreviewParameter(RoomSummaryDetailsProvider::class) roomSummary: RoomSummary
) = ElementPreview {
SelectedRoom(
roomSummary = roomSummaryDetails,
roomSummary = roomSummary,
onRemoveRoom = {},
)
}

4
libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/model/RoomSummaryExtension.kt

@ -18,9 +18,9 @@ package io.element.android.libraries.matrix.ui.model @@ -18,9 +18,9 @@ package io.element.android.libraries.matrix.ui.model
import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
fun RoomSummaryDetails.getAvatarData(size: AvatarSize) = AvatarData(
fun RoomSummary.getAvatarData(size: AvatarSize) = AvatarData(
id = roomId.value,
name = name,
url = avatarUrl,

4
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvents.kt

@ -16,10 +16,10 @@ @@ -16,10 +16,10 @@
package io.element.android.libraries.roomselect.impl
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
sealed interface RoomSelectEvents {
data class SetSelectedRoom(val room: RoomSummaryDetails) : RoomSelectEvents
data class SetSelectedRoom(val room: RoomSummary) : RoomSelectEvents
// TODO remove to restore multi-selection
data object RemoveSelectedRoom : RoomSelectEvents

4
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt

@ -29,7 +29,7 @@ import dagger.assisted.AssistedFactory @@ -29,7 +29,7 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.roomselect.api.RoomSelectMode
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@ -45,7 +45,7 @@ class RoomSelectPresenter @AssistedInject constructor( @@ -45,7 +45,7 @@ class RoomSelectPresenter @AssistedInject constructor(
@Composable
override fun present(): RoomSelectState {
var selectedRooms by remember { mutableStateOf(persistentListOf<RoomSummaryDetails>()) }
var selectedRooms by remember { mutableStateOf(persistentListOf<RoomSummary>()) }
var searchQuery by remember { mutableStateOf("") }
var isSearchActive by remember { mutableStateOf(false) }

5
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectSearchDataSource.kt

@ -22,7 +22,6 @@ import io.element.android.libraries.matrix.api.roomlist.RoomList @@ -22,7 +22,6 @@ import io.element.android.libraries.matrix.api.roomlist.RoomList
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
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.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
@ -48,11 +47,9 @@ class RoomSelectSearchDataSource @Inject constructor( @@ -48,11 +47,9 @@ class RoomSelectSearchDataSource @Inject constructor(
source = RoomList.Source.All,
)
val roomSummaries: Flow<PersistentList<RoomSummaryDetails>> = roomList.filteredSummaries
val roomSummaries: Flow<PersistentList<RoomSummary>> = roomList.filteredSummaries
.map { roomSummaries ->
roomSummaries
.filterIsInstance<RoomSummary.Filled>()
.map { it.details }
.filter { it.currentUserMembership == CurrentUserMembership.JOINED }
.distinctBy { it.roomId } // This should be removed once we're sure no duplicate Rooms can be received
.toPersistentList()

6
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectState.kt

@ -17,15 +17,15 @@ @@ -17,15 +17,15 @@
package io.element.android.libraries.roomselect.impl
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.roomselect.api.RoomSelectMode
import kotlinx.collections.immutable.ImmutableList
data class RoomSelectState(
val mode: RoomSelectMode,
val resultState: SearchBarResultState<ImmutableList<RoomSummaryDetails>>,
val resultState: SearchBarResultState<ImmutableList<RoomSummary>>,
val query: String,
val isSearchActive: Boolean,
val selectedRooms: ImmutableList<RoomSummaryDetails>,
val selectedRooms: ImmutableList<RoomSummary>,
val eventSink: (RoomSelectEvents) -> Unit
)

6
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt

@ -20,7 +20,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider @@ -20,7 +20,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.ui.components.aRoomSummaryDetails
import io.element.android.libraries.roomselect.api.RoomSelectMode
import kotlinx.collections.immutable.ImmutableList
@ -52,10 +52,10 @@ open class RoomSelectStateProvider : PreviewParameterProvider<RoomSelectState> { @@ -52,10 +52,10 @@ open class RoomSelectStateProvider : PreviewParameterProvider<RoomSelectState> {
private fun aRoomSelectState(
mode: RoomSelectMode = RoomSelectMode.Forward,
resultState: SearchBarResultState<ImmutableList<RoomSummaryDetails>> = SearchBarResultState.Initial(),
resultState: SearchBarResultState<ImmutableList<RoomSummary>> = SearchBarResultState.Initial(),
query: String = "",
isSearchActive: Boolean = false,
selectedRooms: ImmutableList<RoomSummaryDetails> = persistentListOf(),
selectedRooms: ImmutableList<RoomSummary> = persistentListOf(),
) = RoomSelectState(
mode = mode,
resultState = resultState,

14
libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt

@ -56,7 +56,7 @@ import io.element.android.libraries.designsystem.theme.components.Text @@ -56,7 +56,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.ui.components.SelectedRoom
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.roomselect.api.RoomSelectMode
@ -73,13 +73,13 @@ fun RoomSelectView( @@ -73,13 +73,13 @@ fun RoomSelectView(
modifier: Modifier = Modifier,
) {
@Suppress("UNUSED_PARAMETER")
fun onRoomRemoved(roomSummaryDetails: RoomSummaryDetails) {
fun onRoomRemoved(roomSummary: RoomSummary) {
// TODO toggle selection when multi-selection is enabled
state.eventSink(RoomSelectEvents.RemoveSelectedRoom)
}
@Composable
fun SelectedRoomsHelper(isForwarding: Boolean, selectedRooms: ImmutableList<RoomSummaryDetails>) {
fun SelectedRoomsHelper(isForwarding: Boolean, selectedRooms: ImmutableList<RoomSummary>) {
if (isForwarding) return
SelectedRooms(
selectedRooms = selectedRooms,
@ -193,8 +193,8 @@ fun RoomSelectView( @@ -193,8 +193,8 @@ fun RoomSelectView(
@Composable
private fun SelectedRooms(
selectedRooms: ImmutableList<RoomSummaryDetails>,
onRemoveRoom: (RoomSummaryDetails) -> Unit,
selectedRooms: ImmutableList<RoomSummary>,
onRemoveRoom: (RoomSummary) -> Unit,
modifier: Modifier = Modifier,
) {
LazyRow(
@ -210,9 +210,9 @@ private fun SelectedRooms( @@ -210,9 +210,9 @@ private fun SelectedRooms(
@Composable
private fun RoomSummaryView(
summary: RoomSummaryDetails,
summary: RoomSummary,
isSelected: Boolean,
onSelection: (RoomSummaryDetails) -> Unit,
onSelection: (RoomSummary) -> Unit,
) {
Row(
modifier = Modifier

11
libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt

@ -23,8 +23,7 @@ import com.google.common.truth.Truth.assertThat @@ -23,8 +23,7 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.libraries.roomselect.api.RoomSelectMode
import io.element.android.tests.testutils.WarmUpRule
@ -69,7 +68,7 @@ class RoomSelectPresenterTest { @@ -69,7 +68,7 @@ class RoomSelectPresenterTest {
@Test
fun `present - update query`() = runTest {
val roomListService = FakeRoomListService().apply {
postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetails())))
postAllRooms(listOf(aRoomSummary()))
}
val presenter = createRoomSelectPresenter(
roomListService = roomListService
@ -78,7 +77,7 @@ class RoomSelectPresenterTest { @@ -78,7 +77,7 @@ class RoomSelectPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(awaitItem().resultState as? SearchBarResultState.Results).isEqualTo(SearchBarResultState.Results(listOf(aRoomSummaryDetails())))
assertThat(awaitItem().resultState as? SearchBarResultState.Results).isEqualTo(SearchBarResultState.Results(listOf(aRoomSummary())))
initialState.eventSink(RoomSelectEvents.ToggleSearchActive)
skipItems(1)
initialState.eventSink(RoomSelectEvents.UpdateQuery("string not contained"))
@ -98,7 +97,7 @@ class RoomSelectPresenterTest { @@ -98,7 +97,7 @@ class RoomSelectPresenterTest {
@Test
fun `present - select and remove a room`() = runTest {
val roomListService = FakeRoomListService().apply {
postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetails())))
postAllRooms(listOf(aRoomSummary()))
}
val presenter = createRoomSelectPresenter(
roomListService = roomListService,
@ -107,7 +106,7 @@ class RoomSelectPresenterTest { @@ -107,7 +106,7 @@ class RoomSelectPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
val summary = aRoomSummaryDetails()
val summary = aRoomSummary()
initialState.eventSink(RoomSelectEvents.SetSelectedRoom(summary))
assertThat(awaitItem().selectedRooms).isEqualTo(persistentListOf(summary))
initialState.eventSink(RoomSelectEvents.RemoveSelectedRoom)

4
tests/uitests/src/test/snapshots/images/appicon.enterprise_Icon_en.png

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fda6dfc8c57df5456535a8ec33f78830beaab61cc27ba4119e9576c5d641023b
size 47856
oid sha256:fe7dd8d4416b397b63fa2b3295e94e53af62f731eaeecca43b5df298a3e834d3
size 17253

4
tests/uitests/src/test/snapshots/images/appicon.enterprise_RoundIcon_en.png

@ -1,3 +1,3 @@ @@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:60b169ac392d4b51e8260c595a97dd14f267facd8f428ad69814bd27e502e189
size 44355
oid sha256:dd6e7de23ed7048d02a2e7f412158e2372a19c0f6106d0f2876345aadfff906e
size 16247

Loading…
Cancel
Save