Add Konsist test to check that toPersistentList() is not used.

Same for `toPersistentSet()` and `toPersistentMap()`.
Fix existing issues.
This commit is contained in:
Benoit Marty
2025-10-08 14:25:15 +02:00
parent 2fa1b9d448
commit 67c9daa0bf
85 changed files with 305 additions and 254 deletions
@@ -37,10 +37,8 @@ import io.element.android.libraries.matrix.ui.model.roleOf
import io.element.android.libraries.matrix.ui.room.PowerLevelRoomMemberComparator import io.element.android.libraries.matrix.ui.room.PowerLevelRoomMemberComparator
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@@ -73,11 +71,11 @@ class ChangeRolesPresenter(
} }
val exitState: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) } val exitState: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val saveState: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) } val saveState: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val usersWithRole = produceState(initialValue = persistentListOf()) { val usersWithRole = produceState<ImmutableList<MatrixUser>>(initialValue = persistentListOf()) {
room.usersWithRole(role).map { members -> members.map { it.toMatrixUser() } } room.usersWithRole(role).map { members -> members.map { it.toMatrixUser() } }
.onEach { users -> .onEach { users ->
val previous: PersistentList<MatrixUser> = value val previous = value
value = users.toPersistentList() value = users.toImmutableList()
// Users who were selected but didn't have the role, so their role change was pending // Users who were selected but didn't have the role, so their role change was pending
val toAdd = selectedUsers.value.filter { user -> users.none { it.userId == user.userId } && previous.none { it.userId == user.userId } } val toAdd = selectedUsers.value.filter { user -> users.none { it.userId == user.userId } && previous.none { it.userId == user.userId } }
// Users who no longer have the role // Users who no longer have the role
@@ -32,8 +32,8 @@ import io.element.android.libraries.previewutils.room.aRoomMemberList
import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
@@ -103,7 +103,7 @@ class ChangeRolesPresenterTest {
// Owner - creator // Owner - creator
aRoomMember(userId = creatorUserId, role = RoomMember.Role.Owner(isCreator = true)) aRoomMember(userId = creatorUserId, role = RoomMember.Role.Owner(isCreator = true))
) )
givenRoomMembersState(RoomMembersState.Ready(roomMemberList.toPersistentList())) givenRoomMembersState(RoomMembersState.Ready(roomMemberList.toImmutableList()))
} }
val presenter = createChangeRolesPresenter(room = room) val presenter = createChangeRolesPresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
@@ -124,7 +124,7 @@ class ChangeRolesPresenterTest {
val creatorUserId = UserId("@creator:matrix.org") val creatorUserId = UserId("@creator:matrix.org")
val memberList = aRoomMemberList() val memberList = aRoomMemberList()
.plus(aRoomMember(displayName = "CREATOR", role = RoomMember.Role.Owner(isCreator = true), userId = creatorUserId)) .plus(aRoomMember(displayName = "CREATOR", role = RoomMember.Role.Owner(isCreator = true), userId = creatorUserId))
.toPersistentList() .toImmutableList()
givenRoomInfo(aRoomInfo(roomCreators = listOf(creatorUserId))) givenRoomInfo(aRoomInfo(roomCreators = listOf(creatorUserId)))
givenRoomMembersState(RoomMembersState.Ready(memberList)) givenRoomMembersState(RoomMembersState.Ready(memberList))
} }
@@ -203,7 +203,7 @@ class ChangeRolesPresenterTest {
assertThat(initialResults?.moderators).hasSize(1) assertThat(initialResults?.moderators).hasSize(1)
assertThat(initialResults?.admins).hasSize(1) assertThat(initialResults?.admins).hasSize(1)
room.givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList().take(1).toPersistentList())) room.givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList().take(1).toImmutableList()))
skipItems(1) skipItems(1)
val searchResults = (awaitItem().searchResults as? SearchBarResultState.Results)?.results val searchResults = (awaitItem().searchResults as? SearchBarResultState.Results)?.results
@@ -552,7 +552,7 @@ class ChangeRolesPresenterTest {
private fun roomPowerLevelsWithRoles(vararg pairs: Pair<UserId, RoomMember.Role>): RoomPowerLevels { private fun roomPowerLevelsWithRoles(vararg pairs: Pair<UserId, RoomMember.Role>): RoomPowerLevels {
return RoomPowerLevels( return RoomPowerLevels(
values = defaultRoomPowerLevelValues(), values = defaultRoomPowerLevelValues(),
users = pairs.associate { (userId, role) -> userId to role.powerLevel }.toPersistentMap() users = pairs.associate { (userId, role) -> userId to role.powerLevel }.toImmutableMap()
) )
} }
} }
@@ -11,7 +11,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionData
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
class CurrentUserWithNeighborsBuilder { class CurrentUserWithNeighborsBuilder {
/** /**
@@ -64,6 +64,6 @@ class CurrentUserWithNeighborsBuilder {
} }
} }
} }
.toPersistentList() .toImmutableList()
} }
} }
@@ -21,7 +21,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class HomeStateProvider : PreviewParameterProvider<HomeState> { open class HomeStateProvider : PreviewParameterProvider<HomeState> {
override val values: Sequence<HomeState> override val values: Sequence<HomeState>
@@ -63,7 +63,7 @@ internal fun aHomeState(
directLogoutState: DirectLogoutState = aDirectLogoutState(), directLogoutState: DirectLogoutState = aDirectLogoutState(),
eventSink: (HomeEvents) -> Unit = {} eventSink: (HomeEvents) -> Unit = {}
) = HomeState( ) = HomeState(
currentUserAndNeighbors = currentUserAndNeighbors.toPersistentList(), currentUserAndNeighbors = currentUserAndNeighbors.toImmutableList(),
showAvatarIndicator = showAvatarIndicator, showAvatarIndicator = showAvatarIndicator,
hasNetworkConnection = hasNetworkConnection, hasNetworkConnection = hasNetworkConnection,
snackbarMessage = snackbarMessage, snackbarMessage = snackbarMessage,
@@ -72,7 +72,7 @@ import io.element.android.libraries.testtags.testTag
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -374,7 +374,7 @@ internal fun DefaultRoomListTopBarWithIndicatorPreview() = ElementPreview {
internal fun DefaultRoomListTopBarMultiAccountPreview() = ElementPreview { internal fun DefaultRoomListTopBarMultiAccountPreview() = ElementPreview {
DefaultRoomListTopBar( DefaultRoomListTopBar(
title = stringResource(R.string.screen_roomlist_main_space_title), title = stringResource(R.string.screen_roomlist_main_space_title),
currentUserAndNeighbors = aMatrixUserList().take(3).toPersistentList(), currentUserAndNeighbors = aMatrixUserList().take(3).toImmutableList(),
showAvatarIndicator = false, showAvatarIndicator = false,
areSearchResultsDisplayed = false, areSearchResultsDisplayed = false,
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()), scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()),
@@ -14,7 +14,7 @@ import dev.zacsweers.metro.Inject
import io.element.android.features.home.impl.filters.selection.FilterSelectionStrategy import io.element.android.features.home.impl.filters.selection.FilterSelectionStrategy
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.roomlist.RoomListService
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter as MatrixRoomListFilter import io.element.android.libraries.matrix.api.roomlist.RoomListFilter as MatrixRoomListFilter
@@ -23,7 +23,7 @@ class RoomListFiltersPresenter(
private val roomListService: RoomListService, private val roomListService: RoomListService,
private val filterSelectionStrategy: FilterSelectionStrategy, private val filterSelectionStrategy: FilterSelectionStrategy,
) : Presenter<RoomListFiltersState> { ) : Presenter<RoomListFiltersState> {
private val initialFilters = filterSelectionStrategy.filterSelectionStates.value.toPersistentList() private val initialFilters = filterSelectionStrategy.filterSelectionStates.value.toImmutableList()
@Composable @Composable
override fun present(): RoomListFiltersState { override fun present(): RoomListFiltersState {
@@ -41,7 +41,7 @@ class RoomListFiltersPresenter(
val filters by produceState(initialValue = initialFilters) { val filters by produceState(initialValue = initialFilters) {
filterSelectionStrategy.filterSelectionStates filterSelectionStrategy.filterSelectionStates
.map { filters -> .map { filters ->
value = filters.toPersistentList() value = filters.toImmutableList()
filters.mapNotNull { filterState -> filters.mapNotNull { filterState ->
if (!filterState.isSelected) { if (!filterState.isSelected) {
return@mapNotNull null return@mapNotNull null
@@ -9,7 +9,7 @@ package io.element.android.features.home.impl.filters
import io.element.android.features.home.impl.filters.selection.FilterSelectionState import io.element.android.features.home.impl.filters.selection.FilterSelectionState
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
data class RoomListFiltersState( data class RoomListFiltersState(
val filterSelectionStates: ImmutableList<FilterSelectionState>, val filterSelectionStates: ImmutableList<FilterSelectionState>,
@@ -21,6 +21,6 @@ data class RoomListFiltersState(
return filterSelectionStates return filterSelectionStates
.filter { it.isSelected } .filter { it.isSelected }
.map { it.filter } .map { it.filter }
.toPersistentList() .toImmutableList()
} }
} }
@@ -16,7 +16,7 @@ import io.element.android.libraries.push.api.battery.BatteryOptimizationState
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentSet import kotlinx.collections.immutable.toImmutableSet
open class RoomListContentStateProvider : PreviewParameterProvider<RoomListContentState> { open class RoomListContentStateProvider : PreviewParameterProvider<RoomListContentState> {
override val values: Sequence<RoomListContentState> override val values: Sequence<RoomListContentState>
@@ -45,7 +45,7 @@ internal fun aRoomsContentState(
fullScreenIntentPermissionsState = fullScreenIntentPermissionsState, fullScreenIntentPermissionsState = fullScreenIntentPermissionsState,
batteryOptimizationState = batteryOptimizationState, batteryOptimizationState = batteryOptimizationState,
summaries = summaries, summaries = summaries,
seenRoomInvites = seenRoomInvites.toPersistentSet(), seenRoomInvites = seenRoomInvites.toImmutableSet(),
) )
internal fun aSkeletonContentState() = RoomListContentState.Skeleton(16) internal fun aSkeletonContentState() = RoomListContentState.Skeleton(16)
@@ -51,8 +51,8 @@ import io.element.android.libraries.push.api.battery.BatteryOptimizationState
import io.element.android.libraries.push.api.notifications.NotificationCleaner import io.element.android.libraries.push.api.notifications.NotificationCleaner
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentSet import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@@ -240,8 +240,8 @@ class RoomListPresenter(
showNewNotificationSoundBanner = showNewNotificationSoundBanner, showNewNotificationSoundBanner = showNewNotificationSoundBanner,
fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(), fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(),
batteryOptimizationState = batteryOptimizationPresenter.present(), batteryOptimizationState = batteryOptimizationPresenter.present(),
summaries = roomSummaries.dataOrNull().orEmpty().toPersistentList(), summaries = roomSummaries.dataOrNull().orEmpty().toImmutableList(),
seenRoomInvites = seenRoomInvites.toPersistentSet(), seenRoomInvites = seenRoomInvites.toImmutableSet(),
) )
} }
} }
@@ -25,7 +25,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class RoomListStateProvider : PreviewParameterProvider<RoomListState> { open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
override val values: Sequence<RoomListState> override val values: Sequence<RoomListState>
@@ -122,5 +122,5 @@ internal fun generateRoomListRoomSummaryList(
avatarData = AvatarData("!id$index", "${(65 + index % 26).toChar()}", size = AvatarSize.RoomListItem), avatarData = AvatarData("!id$index", "${(65 + index % 26).toChar()}", size = AvatarSize.RoomListItem),
id = "!roomId$index:domain", id = "!roomId$index:domain",
) )
}.toPersistentList() }.toImmutableList()
} }
@@ -15,8 +15,8 @@ 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.RoomListFilter
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.loadAllIncrementally import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
@@ -36,11 +36,11 @@ class RoomListSearchDataSource(
source = RoomList.Source.All, source = RoomList.Source.All,
) )
val roomSummaries: Flow<PersistentList<RoomListRoomSummary>> = roomList.filteredSummaries val roomSummaries: Flow<ImmutableList<RoomListRoomSummary>> = roomList.filteredSummaries
.map { roomSummaries -> .map { roomSummaries ->
roomSummaries roomSummaries
.map(roomSummaryFactory::create) .map(roomSummaryFactory::create)
.toPersistentList() .toImmutableList()
} }
.flowOn(coroutineDispatchers.computation) .flowOn(coroutineDispatchers.computation)
@@ -17,7 +17,7 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toPersistentSet import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@Inject @Inject
@@ -30,7 +30,7 @@ class HomeSpacesPresenter(
val hideInvitesAvatar by client.rememberHideInvitesAvatar() val hideInvitesAvatar by client.rememberHideInvitesAvatar()
val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList()) val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList())
val seenSpaceInvites by remember { val seenSpaceInvites by remember {
seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } seenInvitesStore.seenRoomIds().map { it.toImmutableSet() }
}.collectAsState(persistentSetOf()) }.collectAsState(persistentSetOf())
fun handleEvents(event: HomeSpacesEvents) { fun handleEvents(event: HomeSpacesEvents) {
@@ -13,7 +13,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_ROOM_NAME import io.element.android.libraries.matrix.test.A_ROOM_NAME
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import org.junit.Test import org.junit.Test
class RoomListBaseRoomSummaryTest { class RoomListBaseRoomSummaryTest {
@@ -105,7 +105,7 @@ internal fun createRoomListRoomSummary(
canonicalAlias = null, canonicalAlias = null,
inviteSender = null, inviteSender = null,
isDm = false, isDm = false,
heroes = heroes.toPersistentList(), heroes = heroes.toImmutableList(),
isTombstoned = isTombstoned, isTombstoned = isTombstoned,
isSpace = isSpace isSpace = isSpace
) )
@@ -53,7 +53,7 @@ import io.element.android.libraries.matrix.api.spaces.SpaceRoom
import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.libraries.matrix.ui.model.toInviteSender
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.Optional import java.util.Optional
@@ -291,7 +291,7 @@ private fun SpaceRoom.toContentState(): ContentState {
joinRule = joinRule, joinRule = joinRule,
details = LoadedDetails.Space( details = LoadedDetails.Space(
childrenCount = childrenCount, childrenCount = childrenCount,
heroes = heroes.toPersistentList(), heroes = heroes.toImmutableList(),
) )
) )
} }
@@ -24,7 +24,7 @@ import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.model.InviteSender import io.element.android.libraries.matrix.ui.model.InviteSender
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> { open class JoinRoomStateProvider : PreviewParameterProvider<JoinRoomState> {
override val values: Sequence<JoinRoomState> override val values: Sequence<JoinRoomState>
@@ -189,7 +189,7 @@ fun aLoadedDetailsSpace(
heroes: List<MatrixUser> = emptyList(), heroes: List<MatrixUser> = emptyList(),
) = LoadedDetails.Space( ) = LoadedDetails.Space(
childrenCount = childrenCount, childrenCount = childrenCount,
heroes = heroes.toPersistentList() heroes = heroes.toImmutableList()
) )
fun aJoinRoomState( fun aJoinRoomState(
@@ -20,7 +20,7 @@ import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.core.extensions.runCatchingExceptions
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@Inject @Inject
class DependencyLicensesListPresenter( class DependencyLicensesListPresenter(
@@ -37,7 +37,7 @@ class DependencyLicensesListPresenter(
var filter by remember { mutableStateOf("") } var filter by remember { mutableStateOf("") }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
runCatchingExceptions { runCatchingExceptions {
licenses = AsyncData.Success(licensesProvider.provides().toPersistentList()) licenses = AsyncData.Success(licensesProvider.provides().toImmutableList())
}.onFailure { }.onFailure {
licenses = AsyncData.Failure(it) licenses = AsyncData.Failure(it)
} }
@@ -50,7 +50,7 @@ class DependencyLicensesListPresenter(
it.safeName.contains(safeFilter, ignoreCase = true) || it.safeName.contains(safeFilter, ignoreCase = true) ||
it.groupId.contains(safeFilter, ignoreCase = true) || it.groupId.contains(safeFilter, ignoreCase = true) ||
it.artifactId.contains(safeFilter, ignoreCase = true) it.artifactId.contains(safeFilter, ignoreCase = true)
}.toPersistentList()) }.toImmutableList())
} else { } else {
filteredLicenses = licenses filteredLicenses = licenses
} }
@@ -8,7 +8,7 @@
package io.element.android.features.lockscreen.impl.pin.model package io.element.android.features.lockscreen.impl.pin.model
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
data class PinEntry( data class PinEntry(
val digits: ImmutableList<PinDigit>, val digits: ImmutableList<PinDigit>,
@@ -17,7 +17,7 @@ data class PinEntry(
fun createEmpty(size: Int): PinEntry { fun createEmpty(size: Int): PinEntry {
val digits = List(size) { PinDigit.Empty } val digits = List(size) { PinDigit.Empty }
return PinEntry( return PinEntry(
digits = digits.toPersistentList() digits = digits.toImmutableList()
) )
} }
} }
@@ -37,7 +37,7 @@ data class PinEntry(
newDigits[index] = PinDigit.Filled(char) newDigits[index] = PinDigit.Filled(char)
} }
} }
return copy(digits = newDigits.toPersistentList()) return copy(digits = newDigits.toImmutableList())
} }
fun deleteLast(): PinEntry { fun deleteLast(): PinEntry {
@@ -46,7 +46,7 @@ data class PinEntry(
newDigits.indexOfLast { it is PinDigit.Filled }.also { lastFilled -> newDigits.indexOfLast { it is PinDigit.Filled }.also { lastFilled ->
newDigits[lastFilled] = PinDigit.Empty newDigits[lastFilled] = PinDigit.Empty
} }
return copy(digits = newDigits.toPersistentList()) return copy(digits = newDigits.toImmutableList())
} }
fun addDigit(digit: Char): PinEntry { fun addDigit(digit: Char): PinEntry {
@@ -55,7 +55,7 @@ data class PinEntry(
newDigits.indexOfFirst { it is PinDigit.Empty }.also { firstEmpty -> newDigits.indexOfFirst { it is PinDigit.Empty }.also { firstEmpty ->
newDigits[firstEmpty] = PinDigit.Filled(digit) newDigits[firstEmpty] = PinDigit.Filled(digit)
} }
return copy(digits = newDigits.toPersistentList()) return copy(digits = newDigits.toImmutableList())
} }
fun clear(): PinEntry { fun clear(): PinEntry {
@@ -10,7 +10,7 @@ package io.element.android.features.messages.api.timeline.voicemessages.composer
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.media.createFakeWaveform import io.element.android.libraries.designsystem.components.media.createFakeWaveform
import io.element.android.libraries.textcomposer.model.VoiceMessageState import io.element.android.libraries.textcomposer.model.VoiceMessageState
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
open class VoiceMessageComposerStateProvider : PreviewParameterProvider<VoiceMessageComposerState> { open class VoiceMessageComposerStateProvider : PreviewParameterProvider<VoiceMessageComposerState> {
@@ -42,4 +42,4 @@ fun aVoiceMessagePreviewState() = VoiceMessageState.Preview(
waveform = createFakeWaveform(), waveform = createFakeWaveform(),
) )
internal var aWaveformLevels = List(100) { it.toFloat() / 100 }.toPersistentList() internal var aWaveformLevels = List(100) { it.toFloat() / 100 }.toImmutableList()
@@ -89,7 +89,7 @@ import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.MessageComposerMode
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -166,7 +166,7 @@ class MessagesPresenter(
derivedStateOf { roomInfo.avatarData() } derivedStateOf { roomInfo.avatarData() }
} }
val heroes by remember { val heroes by remember {
derivedStateOf { roomInfo.heroes().toPersistentList() } derivedStateOf { roomInfo.heroes().toImmutableList() }
} }
var hasDismissedInviteDialog by rememberSaveable { var hasDismissedInviteDialog by rememberSaveable {
@@ -24,7 +24,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class ActionListStateProvider : PreviewParameterProvider<ActionListState> { open class ActionListStateProvider : PreviewParameterProvider<ActionListState> {
override val values: Sequence<ActionListState> override val values: Sequence<ActionListState>
@@ -209,7 +209,7 @@ fun aTimelineItemActionList(
TimelineItemAction.ViewSource, TimelineItemAction.ViewSource,
) )
.sortedWith(TimelineItemActionComparator()) .sortedWith(TimelineItemActionComparator())
.toPersistentList() .toImmutableList()
} }
fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> { fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> {
@@ -222,5 +222,5 @@ fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> {
TimelineItemAction.Redact, TimelineItemAction.Redact,
) )
.sortedWith(TimelineItemActionComparator()) .sortedWith(TimelineItemActionComparator())
.toPersistentList() .toImmutableList()
} }
@@ -29,7 +29,7 @@ import io.element.android.libraries.mediaviewer.api.local.LocalMedia
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.libraries.preferences.api.store.VideoCompressionPreset
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import timber.log.Timber import timber.log.Timber
import kotlin.math.roundToLong import kotlin.math.roundToLong
@@ -111,7 +111,7 @@ class DefaultMediaOptimizationSelectorPresenter(
canUpload = calculatedSize <= (maxUploadSize as AsyncData.Success).data canUpload = calculatedSize <= (maxUploadSize as AsyncData.Success).data
) )
} }
.toPersistentList() .toImmutableList()
.also { sizes -> .also { sizes ->
Timber.d(sizes.joinToString("\n") { "Calculated size for ${it.preset}: ${it.sizeInBytes} MB. Max upload size: $maxUploadSize" }) Timber.d(sizes.joinToString("\n") { "Calculated size for ${it.preset}: ${it.sizeInBytes} MB. Max upload size: $maxUploadSize" })
} }
@@ -22,7 +22,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.timeline.TimelineProvider import io.element.android.libraries.matrix.api.timeline.TimelineProvider
import io.element.android.libraries.matrix.api.timeline.getActiveTimeline import io.element.android.libraries.matrix.api.timeline.getActiveTimeline
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -43,7 +43,7 @@ class ForwardMessagesPresenter(
private val forwardingActionState: MutableState<AsyncAction<List<RoomId>>> = mutableStateOf(AsyncAction.Uninitialized) private val forwardingActionState: MutableState<AsyncAction<List<RoomId>>> = mutableStateOf(AsyncAction.Uninitialized)
fun onRoomSelected(roomIds: List<RoomId>) { fun onRoomSelected(roomIds: List<RoomId>) {
sessionCoroutineScope.forwardEvent(eventId, roomIds.toPersistentList(), forwardingActionState) sessionCoroutineScope.forwardEvent(eventId, roomIds.toImmutableList(), forwardingActionState)
} }
@Composable @Composable
@@ -79,7 +79,7 @@ import io.element.android.services.analyticsproviders.api.trackers.captureIntera
import io.element.android.wysiwyg.compose.RichTextEditorState import io.element.android.wysiwyg.compose.RichTextEditorState
import io.element.android.wysiwyg.display.TextDisplay import io.element.android.wysiwyg.display.TextDisplay
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
@@ -379,7 +379,7 @@ class MessageComposerPresenter(
showAttachmentSourcePicker = showAttachmentSourcePicker, showAttachmentSourcePicker = showAttachmentSourcePicker,
showTextFormatting = showTextFormatting, showTextFormatting = showTextFormatting,
canShareLocation = canShareLocation.value, canShareLocation = canShareLocation.value,
suggestions = suggestions.toPersistentList(), suggestions = suggestions.toImmutableList(),
resolveMentionDisplay = resolveMentionDisplay, resolveMentionDisplay = resolveMentionDisplay,
resolveAtRoomMentionDisplay = resolveAtRoomMentionDisplay, resolveAtRoomMentionDisplay = resolveAtRoomMentionDisplay,
eventSink = { handleEvents(it) }, eventSink = { handleEvents(it) },
@@ -41,7 +41,6 @@ import io.element.android.libraries.matrix.ui.messages.reply.aProfileTimelineDet
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.collections.immutable.toPersistentList
import java.util.UUID import java.util.UUID
import kotlin.random.Random import kotlin.random.Random
@@ -197,7 +196,7 @@ fun aTimelineItemReactions(
) )
) )
} }
}.toPersistentList() }.toImmutableList()
) )
} }
@@ -33,7 +33,7 @@ import io.element.android.features.messages.impl.timeline.model.event.aTimelineI
import io.element.android.features.messages.impl.timeline.util.defaultTimelineContentPadding import io.element.android.features.messages.impl.timeline.util.defaultTimelineContentPadding
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.persistentListOf
@Composable @Composable
fun TimelineItemStateEventRow( fun TimelineItemStateEventRow(
@@ -100,7 +100,7 @@ internal fun TimelineItemStateEventRowPreview() = ElementPreview {
content = aTimelineItemStateEventContent(), content = aTimelineItemStateEventContent(),
groupPosition = TimelineItemGroupPosition.None, groupPosition = TimelineItemGroupPosition.None,
readReceiptState = TimelineItemReadReceipts( readReceiptState = TimelineItemReadReceipts(
receipts = listOf(aReadReceiptData(0)).toPersistentList(), receipts = persistentListOf(aReadReceiptData(0)),
) )
), ),
renderReadReceipts = true, renderReadReceipts = true,
@@ -21,7 +21,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
@@ -94,7 +94,7 @@ class TimelineItemsFactory(
newTimelineItemStates.add(updatedItem) newTimelineItemStates.add(updatedItem)
} }
} }
val result = timelineItemGrouper.group(newTimelineItemStates).toPersistentList() val result = timelineItemGrouper.group(newTimelineItemStates).toImmutableList()
this._timelineItems.emit(result) this._timelineItems.emit(result)
} }
@@ -8,7 +8,7 @@
package io.element.android.features.messages.impl.timeline.model package io.element.android.features.messages.impl.timeline.model
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
data class TimelineItemReactions( data class TimelineItemReactions(
val reactions: ImmutableList<AggregatedReaction> val reactions: ImmutableList<AggregatedReaction>
@@ -17,5 +17,5 @@ data class TimelineItemReactions(
get() = reactions get() = reactions
.filter { it.isHighlighted } .filter { it.isHighlighted }
.map { it.key } .map { it.key }
.toPersistentList() .toImmutableList()
} }
@@ -7,9 +7,9 @@
package io.element.android.features.messages.impl.timeline.model package io.element.android.features.messages.impl.timeline.model
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
fun aTimelineItemReactions() = TimelineItemReactions( fun aTimelineItemReactions() = TimelineItemReactions(
// Use values from AggregatedReactionProvider // Use values from AggregatedReactionProvider
reactions = AggregatedReactionProvider().values.toPersistentList() reactions = AggregatedReactionProvider().values.toImmutableList()
) )
@@ -11,7 +11,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
@@ -53,7 +53,7 @@ fun aTimelineItemVoiceContent(
duration = duration, duration = duration,
mediaSource = mediaSource, mediaSource = mediaSource,
mimeType = mimeType, mimeType = mimeType,
waveform = waveform.toPersistentList(), waveform = waveform.toImmutableList(),
formattedFileSize = "1.0 MB", formattedFileSize = "1.0 MB",
fileExtension = "ogg", fileExtension = "ogg",
) )
@@ -43,7 +43,6 @@ import io.element.android.libraries.voicerecorder.api.VoiceRecorderState
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
@@ -199,7 +198,7 @@ class DefaultVoiceMessageComposerPresenter(
voiceMessageState = when (val state = recorderState) { voiceMessageState = when (val state = recorderState) {
is VoiceRecorderState.Recording -> VoiceMessageState.Recording( is VoiceRecorderState.Recording -> VoiceMessageState.Recording(
duration = state.elapsedTime, duration = state.elapsedTime,
levels = state.levels.toPersistentList(), levels = state.levels.toImmutableList(),
) )
is VoiceRecorderState.Finished -> is VoiceRecorderState.Finished ->
previewState( previewState(
@@ -36,7 +36,7 @@ import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.setSafeContent import io.element.android.tests.testutils.setSafeContent
import io.element.android.wysiwyg.link.Link import io.element.android.wysiwyg.link.Link
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.TestRule import org.junit.rules.TestRule
@@ -148,7 +148,7 @@ class TimelineViewTest {
eventId = EventId("\$event_$it"), eventId = EventId("\$event_$it"),
content = aTimelineItemUnknownContent(), content = aTimelineItemUnknownContent(),
) )
}.toPersistentList() }.toImmutableList()
rule.setTimelineView( rule.setTimelineView(
state = aTimelineState( state = aTimelineState(
@@ -26,7 +26,7 @@ import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
@@ -92,7 +92,7 @@ class EmojiPickerPresenterTest {
categories: ImmutableList<Pair<EmojibaseCategory, ImmutableList<Emoji>>> = persistentListOf(emojiCategory()), categories: ImmutableList<Pair<EmojibaseCategory, ImmutableList<Emoji>>> = persistentListOf(emojiCategory()),
recentEmojis: ImmutableList<String> = persistentListOf(), recentEmojis: ImmutableList<String> = persistentListOf(),
) = EmojiPickerPresenter( ) = EmojiPickerPresenter(
emojibaseStore = EmojibaseStore(categories.toMap().toPersistentMap()), emojibaseStore = EmojibaseStore(categories.toMap().toImmutableMap()),
recentEmojis = recentEmojis, recentEmojis = recentEmojis,
coroutineDispatchers = testCoroutineDispatchers(), coroutineDispatchers = testCoroutineDispatchers(),
) )
@@ -46,7 +46,6 @@ import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.advanceUntilIdle
@@ -85,7 +84,7 @@ class VoiceMessageComposerPresenterTest {
companion object { companion object {
private val RECORDING_DURATION = 1.seconds private val RECORDING_DURATION = 1.seconds
private val RECORDING_STATE = VoiceMessageState.Recording(RECORDING_DURATION, listOf(0.1f, 0.2f).toPersistentList()) private val RECORDING_STATE = VoiceMessageState.Recording(RECORDING_DURATION, listOf(0.1f, 0.2f).toImmutableList())
} }
@Test @Test
@@ -33,7 +33,6 @@ import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
@@ -79,7 +78,7 @@ class CreatePollPresenter(
repository.getPoll(mode.eventId).onSuccess { repository.getPoll(mode.eventId).onSuccess {
val loadedPoll = PollFormState( val loadedPoll = PollFormState(
question = it.question, question = it.question,
answers = it.answers.map(PollAnswer::text).toPersistentList(), answers = it.answers.map(PollAnswer::text).toImmutableList(),
isDisclosed = it.kind.isDisclosed, isDisclosed = it.kind.isDisclosed,
) )
initialPoll = loadedPoll initialPoll = loadedPoll
@@ -9,8 +9,7 @@ package io.element.android.features.poll.impl.create
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.poll.PollKind
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.persistentListOf
class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> { class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
override val values: Sequence<CreatePollState> override val values: Sequence<CreatePollState>
@@ -20,7 +19,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = false, canCreate = false,
canAddAnswer = true, canAddAnswer = true,
question = "", question = "",
answers = persistentListOf( answers = listOf(
Answer("", false), Answer("", false),
Answer("", false) Answer("", false)
), ),
@@ -33,7 +32,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = true, canCreate = true,
canAddAnswer = true, canAddAnswer = true,
question = "What type of food should we have?", question = "What type of food should we have?",
answers = persistentListOf( answers = listOf(
Answer("Italian \uD83C\uDDEE\uD83C\uDDF9", false), Answer("Italian \uD83C\uDDEE\uD83C\uDDF9", false),
Answer("Chinese \uD83C\uDDE8\uD83C\uDDF3", false), Answer("Chinese \uD83C\uDDE8\uD83C\uDDF3", false),
), ),
@@ -46,7 +45,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = true, canCreate = true,
canAddAnswer = true, canAddAnswer = true,
question = "What type of food should we have?", question = "What type of food should we have?",
answers = persistentListOf( answers = listOf(
Answer("Italian \uD83C\uDDEE\uD83C\uDDF9", false), Answer("Italian \uD83C\uDDEE\uD83C\uDDF9", false),
Answer("Chinese \uD83C\uDDE8\uD83C\uDDF3", false), Answer("Chinese \uD83C\uDDE8\uD83C\uDDF3", false),
), ),
@@ -59,7 +58,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = true, canCreate = true,
canAddAnswer = true, canAddAnswer = true,
question = "What type of food should we have?", question = "What type of food should we have?",
answers = persistentListOf( answers = listOf(
Answer("Italian \uD83C\uDDEE\uD83C\uDDF9", true), Answer("Italian \uD83C\uDDEE\uD83C\uDDF9", true),
Answer("Chinese \uD83C\uDDE8\uD83C\uDDF3", true), Answer("Chinese \uD83C\uDDE8\uD83C\uDDF3", true),
Answer("Brazilian \uD83C\uDDE7\uD83C\uDDF7", true), Answer("Brazilian \uD83C\uDDE7\uD83C\uDDF7", true),
@@ -74,7 +73,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = true, canCreate = true,
canAddAnswer = false, canAddAnswer = false,
question = "Should there be more than 20 answers?", question = "Should there be more than 20 answers?",
answers = persistentListOf( answers = listOf(
Answer("1", true), Answer("1", true),
Answer("2", true), Answer("2", true),
Answer("3", true), Answer("3", true),
@@ -108,7 +107,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
" Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor" + " Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor" +
" in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt" + " in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt" +
" in culpa qui officia deserunt mollit anim id est laborum.", " in culpa qui officia deserunt mollit anim id est laborum.",
answers = persistentListOf( answers = listOf(
Answer( Answer(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." +
" Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis a.", " Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis a.",
@@ -129,7 +128,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = false, canCreate = false,
canAddAnswer = true, canAddAnswer = true,
question = "", question = "",
answers = persistentListOf( answers = listOf(
Answer("", false), Answer("", false),
Answer("", false) Answer("", false)
), ),
@@ -142,7 +141,7 @@ class CreatePollStateProvider : PreviewParameterProvider<CreatePollState> {
canCreate = false, canCreate = false,
canAddAnswer = true, canAddAnswer = true,
question = "", question = "",
answers = persistentListOf( answers = listOf(
Answer("", false), Answer("", false),
Answer("", false) Answer("", false)
), ),
@@ -158,7 +157,7 @@ private fun aCreatePollState(
canCreate: Boolean, canCreate: Boolean,
canAddAnswer: Boolean, canAddAnswer: Boolean,
question: String, question: String,
answers: PersistentList<Answer>, answers: List<Answer>,
showBackConfirmation: Boolean, showBackConfirmation: Boolean,
showDeleteConfirmation: Boolean, showDeleteConfirmation: Boolean,
pollKind: PollKind pollKind: PollKind
@@ -168,7 +167,7 @@ private fun aCreatePollState(
canSave = canCreate, canSave = canCreate,
canAddAnswer = canAddAnswer, canAddAnswer = canAddAnswer,
question = question, question = question,
answers = answers, answers = answers.toImmutableList(),
showBackConfirmation = showBackConfirmation, showBackConfirmation = showBackConfirmation,
showDeleteConfirmation = showDeleteConfirmation, showDeleteConfirmation = showDeleteConfirmation,
pollKind = pollKind, pollKind = pollKind,
@@ -13,7 +13,7 @@ import io.element.android.features.poll.impl.PollConstants
import io.element.android.features.poll.impl.PollConstants.MIN_ANSWERS import io.element.android.features.poll.impl.PollConstants.MIN_ANSWERS
import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.poll.PollKind
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
/** /**
* Represents the state of the poll creation / edit form. * Represents the state of the poll creation / edit form.
@@ -28,7 +28,7 @@ data class PollFormState(
companion object { companion object {
val Empty = PollFormState( val Empty = PollFormState(
question = "", question = "",
answers = MutableList(MIN_ANSWERS) { "" }.toPersistentList(), answers = MutableList(MIN_ANSWERS) { "" }.toImmutableList(),
isDisclosed = true, isDisclosed = true,
) )
} }
@@ -49,7 +49,7 @@ data class PollFormState(
return this return this
} }
return copy(answers = (answers + "").toPersistentList()) return copy(answers = (answers + "").toImmutableList())
} }
/** /**
@@ -66,7 +66,7 @@ data class PollFormState(
return this return this
} }
return copy(answers = answers.filterIndexed { i, _ -> i != index }.toPersistentList()) return copy(answers = answers.filterIndexed { i, _ -> i != index }.toImmutableList())
} }
/** /**
@@ -82,7 +82,7 @@ data class PollFormState(
fun withAnswerChanged(index: Int, rawAnswer: String): PollFormState = fun withAnswerChanged(index: Int, rawAnswer: String): PollFormState =
copy(answers = answers.toMutableList().apply { copy(answers = answers.toMutableList().apply {
this[index] = rawAnswer.take(PollConstants.MAX_ANSWER_LENGTH) this[index] = rawAnswer.take(PollConstants.MAX_ANSWER_LENGTH)
}.toPersistentList()) }.toImmutableList())
/** /**
* Whether a new answer can be added. * Whether a new answer can be added.
@@ -114,7 +114,7 @@ internal val pollFormStateSaver = mapSaver(
restore = { saved -> restore = { saved ->
PollFormState( PollFormState(
question = saved["question"] as String, question = saved["question"] as String,
answers = (saved["answers"] as Array<*>).map { it as String }.toPersistentList(), answers = (saved["answers"] as Array<*>).map { it as String }.toImmutableList(),
isDisclosed = saved["isDisclosed"] as Boolean, isDisclosed = saved["isDisclosed"] as Boolean,
) )
} }
@@ -13,7 +13,7 @@ import io.element.android.features.poll.api.pollcontent.aPollContentState
import io.element.android.features.poll.impl.history.model.PollHistoryFilter import io.element.android.features.poll.impl.history.model.PollHistoryFilter
import io.element.android.features.poll.impl.history.model.PollHistoryItem import io.element.android.features.poll.impl.history.model.PollHistoryItem
import io.element.android.features.poll.impl.history.model.PollHistoryItems import io.element.android.features.poll.impl.history.model.PollHistoryItems
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
class PollHistoryStateProvider : PreviewParameterProvider<PollHistoryState> { class PollHistoryStateProvider : PreviewParameterProvider<PollHistoryState> {
override val values: Sequence<PollHistoryState> override val values: Sequence<PollHistoryState>
@@ -53,8 +53,8 @@ internal fun aPollHistoryState(
hasMoreToLoad = hasMoreToLoad, hasMoreToLoad = hasMoreToLoad,
activeFilter = activeFilter, activeFilter = activeFilter,
pollHistoryItems = PollHistoryItems( pollHistoryItems = PollHistoryItems(
ongoing = currentItems.toPersistentList(), ongoing = currentItems.toImmutableList(),
past = currentItems.toPersistentList(), past = currentItems.toImmutableList(),
), ),
eventSink = eventSink, eventSink = eventSink,
) )
@@ -14,7 +14,7 @@ import io.element.android.libraries.dateformatter.api.DateFormatter
import io.element.android.libraries.dateformatter.api.DateFormatterMode import io.element.android.libraries.dateformatter.api.DateFormatterMode
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@Inject @Inject
@@ -36,8 +36,8 @@ class PollHistoryItemsFactory(
} }
} }
PollHistoryItems( PollHistoryItems(
ongoing = ongoing.toPersistentList(), ongoing = ongoing.toImmutableList(),
past = past.toPersistentList() past = past.toImmutableList()
) )
} }
@@ -9,7 +9,7 @@ package io.element.android.features.poll.impl.create
import androidx.compose.runtime.saveable.SaverScope import androidx.compose.runtime.saveable.SaverScope
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.persistentListOf
import org.junit.Test import org.junit.Test
class PollFormStateSaverTest { class PollFormStateSaverTest {
@@ -21,7 +21,7 @@ class PollFormStateSaverTest {
fun `test save and restore`() { fun `test save and restore`() {
val state = PollFormState( val state = PollFormState(
question = "question", question = "question",
answers = listOf("answer1", "answer2").toPersistentList(), answers = persistentListOf("answer1", "answer2"),
isDisclosed = true, isDisclosed = true,
) )
@@ -10,7 +10,7 @@ package io.element.android.features.poll.impl.create
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.features.poll.impl.PollConstants import io.element.android.features.poll.impl.PollConstants
import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.poll.PollKind
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import org.junit.Test import org.junit.Test
class PollFormStateTest { class PollFormStateTest {
@@ -47,7 +47,7 @@ class PollFormStateTest {
val state = PollFormState.Empty val state = PollFormState.Empty
val newState = state.withAnswerChanged(1, "New answer") val newState = state.withAnswerChanged(1, "New answer")
assertThat(newState).isEqualTo(PollFormState.Empty.copy( assertThat(newState).isEqualTo(PollFormState.Empty.copy(
answers = listOf("", "New answer").toPersistentList() answers = listOf("", "New answer").toImmutableList()
)) ))
} }
@@ -58,7 +58,7 @@ class PollFormStateTest {
val state = PollFormState.Empty val state = PollFormState.Empty
val newState = state.withAnswerChanged(1, tooLongAnswer) val newState = state.withAnswerChanged(1, tooLongAnswer)
assertThat(newState).isEqualTo(PollFormState.Empty.copy( assertThat(newState).isEqualTo(PollFormState.Empty.copy(
answers = listOf("", truncatedAnswer).toPersistentList() answers = listOf("", truncatedAnswer).toImmutableList()
)) ))
} }
@@ -101,7 +101,7 @@ class PollFormStateTest {
@Test @Test
fun `is valid is false when not enough answers`() { fun `is valid is false when not enough answers`() {
val state = aValidPollFormState().copy(answers = listOf("").toPersistentList()) val state = aValidPollFormState().copy(answers = listOf("").toImmutableList())
assertThat(state.isValid).isFalse() assertThat(state.isValid).isFalse()
} }
@@ -127,10 +127,10 @@ class PollFormStateTest {
private fun aValidPollFormState(): PollFormState { private fun aValidPollFormState(): PollFormState {
return PollFormState.Empty.copy( return PollFormState.Empty.copy(
question = "question", question = "question",
answers = listOf("answer1", "answer2").toPersistentList(), answers = listOf("answer1", "answer2").toImmutableList(),
isDisclosed = true, isDisclosed = true,
) )
} }
private fun PollFormState.withBlankAnswers(numAnswers: Int): PollFormState = private fun PollFormState.withBlankAnswers(numAnswers: Int): PollFormState =
copy(answers = List(numAnswers) { "" }.toPersistentList()) copy(answers = List(numAnswers) { "" }.toImmutableList())
@@ -45,7 +45,7 @@ import io.element.android.libraries.preferences.api.store.VideoCompressionPreset
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.compose.LocalAnalyticsService import io.element.android.services.analytics.compose.LocalAnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@Composable @Composable
fun AdvancedSettingsView( fun AdvancedSettingsView(
@@ -73,7 +73,7 @@ fun AdvancedSettingsView(
PreferenceDropdown( PreferenceDropdown(
title = stringResource(id = CommonStrings.common_appearance), title = stringResource(id = CommonStrings.common_appearance),
selectedOption = state.theme, selectedOption = state.theme,
options = ThemeOption.entries.toPersistentList(), options = ThemeOption.entries.toImmutableList(),
onSelectOption = { themeOption -> onSelectOption = { themeOption ->
state.eventSink(AdvancedSettingsEvents.SetTheme(themeOption)) state.eventSink(AdvancedSettingsEvents.SetTheme(themeOption))
} }
@@ -25,7 +25,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -83,7 +83,7 @@ class BlockedUsersPresenter(
} }
} }
return BlockedUsersState( return BlockedUsersState(
blockedUsers = ignoredMatrixUser.toPersistentList(), blockedUsers = ignoredMatrixUser.toImmutableList(),
unblockUserAction = unblockUserAction.value, unblockUserAction = unblockUserAction.value,
eventSink = ::handleEvents eventSink = ::handleEvents
) )
@@ -11,7 +11,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
class BlockedUsersStateProvider : PreviewParameterProvider<BlockedUsersState> { class BlockedUsersStateProvider : PreviewParameterProvider<BlockedUsersState> {
override val values: Sequence<BlockedUsersState> override val values: Sequence<BlockedUsersState>
@@ -32,7 +32,7 @@ internal fun aBlockedUsersState(
eventSink: (BlockedUsersEvents) -> Unit = {}, eventSink: (BlockedUsersEvents) -> Unit = {},
): BlockedUsersState { ): BlockedUsersState {
return BlockedUsersState( return BlockedUsersState(
blockedUsers = blockedUsers.toPersistentList(), blockedUsers = blockedUsers.toImmutableList(),
unblockUserAction = unblockUserAction, unblockUserAction = unblockUserAction,
eventSink = eventSink, eventSink = eventSink,
) )
@@ -37,11 +37,9 @@ import io.element.android.libraries.featureflag.api.Feature
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
import io.element.android.libraries.matrix.api.tracing.TraceLogPack
import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@@ -82,11 +80,11 @@ class DeveloperSettingsPresenter(
appPreferencesStore.getTracingLogLevelFlow().map { AsyncData.Success(it.toLogLevelItem()) } appPreferencesStore.getTracingLogLevelFlow().map { AsyncData.Success(it.toLogLevelItem()) }
} }
val tracingLogLevel by tracingLogLevelFlow.collectAsState(initial = AsyncData.Uninitialized) val tracingLogLevel by tracingLogLevelFlow.collectAsState(initial = AsyncData.Uninitialized)
val tracingLogPacks by produceState(persistentListOf<TraceLogPack>()) { val tracingLogPacks by produceState(persistentListOf()) {
appPreferencesStore.getTracingLogPacksFlow() appPreferencesStore.getTracingLogPacksFlow()
// Sort the entries alphabetically by its title // Sort the entries alphabetically by its title
.map { it.sortedBy { it.title }.toPersistentList() } .map { it.sortedBy { it.title } }
.collectLatest { value = it } .collectLatest { value = it.toImmutableList() }
} }
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
@@ -14,7 +14,7 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList
import io.element.android.libraries.matrix.api.tracing.TraceLogPack import io.element.android.libraries.matrix.api.tracing.TraceLogPack
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSettingsState> { open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSettingsState> {
override val values: Sequence<DeveloperSettingsState> override val values: Sequence<DeveloperSettingsState>
@@ -43,7 +43,7 @@ fun aDeveloperSettingsState(
clearCacheAction = clearCacheAction, clearCacheAction = clearCacheAction,
customElementCallBaseUrlState = customElementCallBaseUrlState, customElementCallBaseUrlState = customElementCallBaseUrlState,
tracingLogLevel = AsyncData.Success(LogLevelItem.INFO), tracingLogLevel = AsyncData.Success(LogLevelItem.INFO),
tracingLogPacks = traceLogPacks.toPersistentList(), tracingLogPacks = traceLogPacks.toImmutableList(),
eventSink = eventSink, eventSink = eventSink,
) )
@@ -36,7 +36,7 @@ import io.element.android.libraries.featureflag.ui.FeatureListView
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
import io.element.android.libraries.matrix.api.tracing.TraceLogPack import io.element.android.libraries.matrix.api.tracing.TraceLogPack
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@Composable @Composable
fun DeveloperSettingsView( fun DeveloperSettingsView(
@@ -66,7 +66,7 @@ fun DeveloperSettingsView(
title = "Tracing log level", title = "Tracing log level",
supportingText = "Requires app reboot", supportingText = "Requires app reboot",
selectedOption = state.tracingLogLevel.dataOrNull(), selectedOption = state.tracingLogLevel.dataOrNull(),
options = LogLevelItem.entries.toPersistentList(), options = LogLevelItem.entries.toImmutableList(),
onSelectOption = { logLevel -> onSelectOption = { logLevel ->
state.eventSink(DeveloperSettingsEvents.SetTracingLogLevel(logLevel)) state.eventSink(DeveloperSettingsEvents.SetTracingLogLevel(logLevel))
} }
@@ -35,7 +35,7 @@ import io.element.android.libraries.matrix.api.verification.SessionVerificationS
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@@ -80,7 +80,7 @@ class PreferencesRootPresenter(
avatarUrl = it.userAvatarUrl, avatarUrl = it.userAvatarUrl,
) )
} }
.toPersistentList() .toImmutableList()
} }
}.collectAsState(initial = persistentListOf()) }.collectAsState(initial = persistentListOf())
@@ -13,7 +13,7 @@ import io.element.android.libraries.matrix.api.core.DeviceId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
fun aPreferencesRootState( fun aPreferencesRootState(
myUser: MatrixUser = aMatrixUser(), myUser: MatrixUser = aMatrixUser(),
@@ -24,7 +24,7 @@ fun aPreferencesRootState(
version = "Version 1.1 (1)", version = "Version 1.1 (1)",
deviceId = DeviceId("ILAKNDNASDLK"), deviceId = DeviceId("ILAKNDNASDLK"),
isMultiAccountEnabled = true, isMultiAccountEnabled = true,
otherSessions = otherSessions.toPersistentList(), otherSessions = otherSessions.toImmutableList(),
showSecureBackup = true, showSecureBackup = true,
showSecureBackupBadge = true, showSecureBackupBadge = true,
accountManagementUrl = "aUrl", accountManagementUrl = "aUrl",
@@ -51,7 +51,7 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@@ -194,7 +194,7 @@ class RoomDetailsPresenter(
isFavorite = isFavorite, isFavorite = isFavorite,
displayRolesAndPermissionsSettings = !isDm && isUserAdmin, displayRolesAndPermissionsSettings = !isDm && isUserAdmin,
isPublic = joinRule == JoinRule.Public, isPublic = joinRule == JoinRule.Public,
heroes = roomInfo.heroes.toPersistentList(), heroes = roomInfo.heroes.toImmutableList(),
pinnedMessagesCount = pinnedMessagesCount, pinnedMessagesCount = pinnedMessagesCount,
snackbarMessage = snackbarMessage, snackbarMessage = snackbarMessage,
canShowKnockRequests = canShowKnockRequests, canShowKnockRequests = canShowKnockRequests,
@@ -18,7 +18,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
data class RoomDetailsState( data class RoomDetailsState(
val roomId: RoomId, val roomId: RoomId,
@@ -59,7 +59,7 @@ data class RoomDetailsState(
if (isPublic) { if (isPublic) {
add(RoomBadge.PUBLIC) add(RoomBadge.PUBLIC)
} }
}.toPersistentList() }.toImmutableList()
} }
@Immutable @Immutable
@@ -27,7 +27,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState> { open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState> {
override val values: Sequence<RoomDetailsState> override val values: Sequence<RoomDetailsState>
@@ -135,7 +135,7 @@ fun aRoomDetailsState(
isFavorite = isFavorite, isFavorite = isFavorite,
displayRolesAndPermissionsSettings = displayAdminSettings, displayRolesAndPermissionsSettings = displayAdminSettings,
isPublic = isPublic, isPublic = isPublic,
heroes = heroes.toPersistentList(), heroes = heroes.toImmutableList(),
pinnedMessagesCount = pinnedMessagesCount, pinnedMessagesCount = pinnedMessagesCount,
snackbarMessage = snackbarMessage, snackbarMessage = snackbarMessage,
canShowKnockRequests = canShowKnockRequests, canShowKnockRequests = canShowKnockRequests,
@@ -89,7 +89,6 @@ import io.element.android.services.analytics.compose.LocalAnalyticsService
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
@Composable @Composable
fun RoomDetailsView( fun RoomDetailsView(
@@ -400,7 +399,7 @@ private fun RoomHeaderSection(
avatarType = AvatarType.Room( avatarType = AvatarType.Room(
heroes = heroes.map { user -> heroes = heroes.map { user ->
user.getAvatarData(size = AvatarSize.RoomDetailsHeader) user.getAvatarData(size = AvatarSize.RoomDetailsHeader)
}.toPersistentList(), }.toImmutableList(),
isTombstoned = isTombstoned, isTombstoned = isTombstoned,
), ),
contentDescription = avatarUrl?.let { stringResource(CommonStrings.a11y_room_avatar) }, contentDescription = avatarUrl?.let { stringResource(CommonStrings.a11y_room_avatar) },
@@ -38,7 +38,7 @@ import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange
import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@@ -69,10 +69,10 @@ class RoomMemberListPresenter(
val canInvite by room.canInviteAsState(syncUpdateFlow.value) val canInvite by room.canInviteAsState(syncUpdateFlow.value)
val roomModerationState = roomMembersModerationPresenter.present() val roomModerationState = roomMembersModerationPresenter.present()
val roomMemberIdentityStates by produceState(persistentMapOf<UserId, IdentityState>()) { val roomMemberIdentityStates by produceState(persistentMapOf()) {
room.roomMemberIdentityStateChange(waitForEncryption = true) room.roomMemberIdentityStateChange(waitForEncryption = true)
.onEach { identities -> .onEach { identities ->
value = identities.associateBy({ it.identityRoomMember.userId }, { it.identityState }).toPersistentMap() value = identities.associateBy({ it.identityRoomMember.userId }, { it.identityState }).toImmutableMap()
} }
.launchIn(this) .launchIn(this)
} }
@@ -11,7 +11,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
class ChangeRoomPermissionsStateProvider : PreviewParameterProvider<ChangeRoomPermissionsState> { class ChangeRoomPermissionsStateProvider : PreviewParameterProvider<ChangeRoomPermissionsState> {
override val values: Sequence<ChangeRoomPermissionsState> override val values: Sequence<ChangeRoomPermissionsState>
@@ -45,7 +45,7 @@ internal fun aChangeRoomPermissionsState(
) = ChangeRoomPermissionsState( ) = ChangeRoomPermissionsState(
section = section, section = section,
currentPermissions = currentPermissions, currentPermissions = currentPermissions,
items = items.toPersistentList(), items = items.toImmutableList(),
hasChanges = hasChanges, hasChanges = hasChanges,
saveAction = saveAction, saveAction = saveAction,
confirmExitAction = confirmExitAction, confirmExitAction = confirmExitAction,
@@ -14,7 +14,7 @@ import io.element.android.features.roommembermoderation.api.RoomMemberModeration
import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
class InternalRoomMemberModerationStateProvider : PreviewParameterProvider<InternalRoomMemberModerationState> { class InternalRoomMemberModerationStateProvider : PreviewParameterProvider<InternalRoomMemberModerationState> {
override val values: Sequence<InternalRoomMemberModerationState> override val values: Sequence<InternalRoomMemberModerationState>
@@ -86,7 +86,7 @@ fun aRoomMembersModerationState(
canKick = canKick, canKick = canKick,
canBan = canBan, canBan = canBan,
selectedUser = selectedUser, selectedUser = selectedUser,
actions = actions.toPersistentList(), actions = actions.toImmutableList(),
kickUserAsyncAction = kickUserAsyncAction, kickUserAsyncAction = kickUserAsyncAction,
banUserAsyncAction = banUserAsyncAction, banUserAsyncAction = banUserAsyncAction,
unbanUserAsyncAction = unbanUserAsyncAction, unbanUserAsyncAction = unbanUserAsyncAction,
@@ -35,9 +35,9 @@ import io.element.android.libraries.matrix.ui.room.canBanAsState
import io.element.android.libraries.matrix.ui.room.canKickAsState import io.element.android.libraries.matrix.ui.room.canKickAsState
import io.element.android.libraries.matrix.ui.room.userPowerLevelAsState import io.element.android.libraries.matrix.ui.room.userPowerLevelAsState
import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
@@ -68,7 +68,7 @@ class RoomMemberModerationPresenter(
var selectedUser by remember { var selectedUser by remember {
mutableStateOf<MatrixUser?>(null) mutableStateOf<MatrixUser?>(null)
} }
val moderationActions = remember { mutableStateOf(persistentListOf<ModerationActionState>()) } val moderationActions = remember { mutableStateOf<ImmutableList<ModerationActionState>>(persistentListOf()) }
fun handleEvent(event: RoomMemberModerationEvents) { fun handleEvent(event: RoomMemberModerationEvents) {
when (event) { when (event) {
@@ -149,7 +149,7 @@ class RoomMemberModerationPresenter(
canKick: Boolean, canKick: Boolean,
canBan: Boolean, canBan: Boolean,
currentUserMemberPowerLevel: Long, currentUserMemberPowerLevel: Long,
): PersistentList<ModerationActionState> { ): ImmutableList<ModerationActionState> {
return buildList { return buildList {
add(ModerationActionState(action = ModerationAction.DisplayProfile, isEnabled = true)) add(ModerationActionState(action = ModerationAction.DisplayProfile, isEnabled = true))
// Assume the member is a regular user when it's unknown // Assume the member is a regular user when it's unknown
@@ -168,7 +168,7 @@ class RoomMemberModerationPresenter(
add(ModerationActionState(action = ModerationAction.BanUser, isEnabled = canModerateThisUser)) add(ModerationActionState(action = ModerationAction.BanUser, isEnabled = canModerateThisUser))
} }
} }
}.toPersistentList() }.toImmutableList()
} }
private fun CoroutineScope.kickUser( private fun CoroutineScope.kickUser(
@@ -30,7 +30,7 @@ import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.test import io.element.android.tests.testutils.test
import io.element.android.tests.testutils.testCoroutineDispatchers import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
@@ -360,7 +360,7 @@ class RoomMemberModerationPresenterTest {
updateMembersResult = { Result.success(Unit) } updateMembersResult = { Result.success(Unit) }
), ),
).apply { ).apply {
val roomMembers = listOfNotNull(targetRoomMember).toPersistentList() val roomMembers = listOfNotNull(targetRoomMember).toImmutableList()
givenRoomMembersState(state = RoomMembersState.Ready(roomMembers)) givenRoomMembersState(state = RoomMembersState.Ready(roomMembers))
} }
} }
@@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.api.spaces.SpaceRoom
import io.element.android.libraries.previewutils.room.aSpaceRoom import io.element.android.libraries.previewutils.room.aSpaceRoom
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
class LeaveSpaceStateProvider : PreviewParameterProvider<LeaveSpaceState> { class LeaveSpaceStateProvider : PreviewParameterProvider<LeaveSpaceState> {
override val values: Sequence<LeaveSpaceState> override val values: Sequence<LeaveSpaceState>
@@ -92,13 +92,13 @@ class LeaveSpaceStateProvider : PreviewParameterProvider<LeaveSpaceState> {
), ),
aLeaveSpaceState( aLeaveSpaceState(
selectableSpaceRooms = AsyncData.Success( selectableSpaceRooms = AsyncData.Success(
List(10) { aSelectableSpaceRoom() }.toPersistentList() List(10) { aSelectableSpaceRoom() }.toImmutableList()
), ),
leaveSpaceAction = AsyncAction.Loading, leaveSpaceAction = AsyncAction.Loading,
), ),
aLeaveSpaceState( aLeaveSpaceState(
selectableSpaceRooms = AsyncData.Success( selectableSpaceRooms = AsyncData.Success(
List(10) { aSelectableSpaceRoom() }.toPersistentList() List(10) { aSelectableSpaceRoom() }.toImmutableList()
), ),
leaveSpaceAction = AsyncAction.Failure(Exception("An error")), leaveSpaceAction = AsyncAction.Failure(Exception("An error")),
), ),
@@ -33,11 +33,12 @@ import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.matrix.api.spaces.SpaceRoom import io.element.android.libraries.matrix.api.spaces.SpaceRoom
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toImmutableMap
import kotlinx.collections.immutable.toPersistentSet import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -52,18 +53,18 @@ class SpacePresenter(
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>, private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
@SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope,
) : Presenter<SpaceState> { ) : Presenter<SpaceState> {
private var children by mutableStateOf(persistentListOf<SpaceRoom>()) private var children by mutableStateOf<ImmutableList<SpaceRoom>>(persistentListOf())
@Composable @Composable
override fun present(): SpaceState { override fun present(): SpaceState {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
paginate() paginate()
spaceRoomList.spaceRoomsFlow.collect { children = it.toPersistentList() } spaceRoomList.spaceRoomsFlow.collect { children = it.toImmutableList() }
} }
val hideInvitesAvatar by client.rememberHideInvitesAvatar() val hideInvitesAvatar by client.rememberHideInvitesAvatar()
val seenSpaceInvites by remember { val seenSpaceInvites by remember {
seenInvitesStore.seenRoomIds().map { it.toPersistentSet() } seenInvitesStore.seenRoomIds().map { it.toImmutableSet() }
}.collectAsState(persistentSetOf()) }.collectAsState(persistentSetOf())
val localCoroutineScope = rememberCoroutineScope() val localCoroutineScope = rememberCoroutineScope()
@@ -120,7 +121,7 @@ class SpacePresenter(
seenSpaceInvites = seenSpaceInvites, seenSpaceInvites = seenSpaceInvites,
hideInvitesAvatar = hideInvitesAvatar, hideInvitesAvatar = hideInvitesAvatar,
hasMoreToLoad = hasMoreToLoad, hasMoreToLoad = hasMoreToLoad,
joinActions = joinActions.toPersistentMap(), joinActions = joinActions.toImmutableMap(),
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
eventSink = ::handleEvents, eventSink = ::handleEvents,
) )
@@ -10,7 +10,7 @@ package io.element.android.features.space.impl.leave
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import org.junit.Test import org.junit.Test
class LeaveSpaceStateTest { class LeaveSpaceStateTest {
@@ -64,7 +64,7 @@ class LeaveSpaceStateTest {
listOf( listOf(
aSelectableSpaceRoom(isLastAdmin = false, isSelected = true), aSelectableSpaceRoom(isLastAdmin = false, isSelected = true),
aSelectableSpaceRoom(isLastAdmin = false, isSelected = false), aSelectableSpaceRoom(isLastAdmin = false, isSelected = false),
).toPersistentList() ).toImmutableList()
) )
) )
assertThat(sut.showQuickAction).isTrue() assertThat(sut.showQuickAction).isTrue()
@@ -81,7 +81,7 @@ class LeaveSpaceStateTest {
listOf( listOf(
aSelectableSpaceRoom(isLastAdmin = false, isSelected = true), aSelectableSpaceRoom(isLastAdmin = false, isSelected = true),
aSelectableSpaceRoom(isLastAdmin = false, isSelected = true), aSelectableSpaceRoom(isLastAdmin = false, isSelected = true),
).toPersistentList() ).toImmutableList()
) )
) )
assertThat(sut.showQuickAction).isTrue() assertThat(sut.showQuickAction).isTrue()
@@ -95,11 +95,11 @@ class LeaveSpaceStateTest {
fun `test 1 last admin, 2 selected`() { fun `test 1 last admin, 2 selected`() {
val sut = aLeaveSpaceState( val sut = aLeaveSpaceState(
selectableSpaceRooms = AsyncData.Success( selectableSpaceRooms = AsyncData.Success(
listOf( persistentListOf(
aSelectableSpaceRoom(isLastAdmin = true, isSelected = false), aSelectableSpaceRoom(isLastAdmin = true, isSelected = false),
aSelectableSpaceRoom(isLastAdmin = false, isSelected = true), aSelectableSpaceRoom(isLastAdmin = false, isSelected = true),
aSelectableSpaceRoom(isLastAdmin = false, isSelected = true), aSelectableSpaceRoom(isLastAdmin = false, isSelected = true),
).toPersistentList() )
) )
) )
assertThat(sut.showQuickAction).isTrue() assertThat(sut.showQuickAction).isTrue()
@@ -116,7 +116,7 @@ class LeaveSpaceStateTest {
listOf( listOf(
aSelectableSpaceRoom(isLastAdmin = true, isSelected = false), aSelectableSpaceRoom(isLastAdmin = true, isSelected = false),
aSelectableSpaceRoom(isLastAdmin = true, isSelected = false), aSelectableSpaceRoom(isLastAdmin = true, isSelected = false),
).toPersistentList() ).toImmutableList()
) )
) )
assertThat(sut.showQuickAction).isFalse() assertThat(sut.showQuickAction).isFalse()
@@ -19,8 +19,9 @@ import dev.zacsweers.metro.AssistedInject
import io.element.android.features.viewfolder.impl.model.Item import io.element.android.features.viewfolder.impl.model.Item
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@AssistedInject @AssistedInject
class ViewFolderPresenter( class ViewFolderPresenter(
@@ -36,7 +37,7 @@ class ViewFolderPresenter(
@Composable @Composable
override fun present(): ViewFolderState { override fun present(): ViewFolderState {
var content by remember { mutableStateOf(persistentListOf<Item>()) } var content by remember { mutableStateOf<ImmutableList<Item>>(persistentListOf()) }
val title = remember { val title = remember {
buildString { buildString {
if (path.contains(buildMeta.applicationId)) { if (path.contains(buildMeta.applicationId)) {
@@ -49,7 +50,7 @@ class ViewFolderPresenter(
content = buildList { content = buildList {
if (canGoUp) add(Item.Parent) if (canGoUp) add(Item.Parent)
addAll(folderExplorer.getItems(path)) addAll(folderExplorer.getItems(path))
}.toPersistentList() }.toImmutableList()
} }
return ViewFolderState( return ViewFolderState(
title = title, title = title,
@@ -15,8 +15,9 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@Inject @Inject
class AccountSelectPresenter( class AccountSelectPresenter(
@@ -24,7 +25,7 @@ class AccountSelectPresenter(
) : Presenter<AccountSelectState> { ) : Presenter<AccountSelectState> {
@Composable @Composable
override fun present(): AccountSelectState { override fun present(): AccountSelectState {
val accounts by produceState(persistentListOf()) { val accounts by produceState<ImmutableList<MatrixUser>>(persistentListOf()) {
// Do not use sessionStore.sessionsFlow() to not make it change when an account is selected. // Do not use sessionStore.sessionsFlow() to not make it change when an account is selected.
value = sessionStore.getAllSessions() value = sessionStore.getAllSessions()
.map { .map {
@@ -34,7 +35,7 @@ class AccountSelectPresenter(
avatarUrl = it.userAvatarUrl, avatarUrl = it.userAvatarUrl,
) )
} }
.toPersistentList() .toImmutableList()
} }
return AccountSelectState( return AccountSelectState(
@@ -10,7 +10,7 @@ package io.element.android.libraries.accountselect.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class AccountSelectStateProvider : PreviewParameterProvider<AccountSelectState> { open class AccountSelectStateProvider : PreviewParameterProvider<AccountSelectState> {
override val values: Sequence<AccountSelectState> override val values: Sequence<AccountSelectState>
@@ -23,5 +23,5 @@ open class AccountSelectStateProvider : PreviewParameterProvider<AccountSelectSt
private fun anAccountSelectState( private fun anAccountSelectState(
accounts: List<MatrixUser> = listOf(), accounts: List<MatrixUser> = listOf(),
) = AccountSelectState( ) = AccountSelectState(
accounts = accounts.toPersistentList(), accounts = accounts.toImmutableList(),
) )
@@ -27,7 +27,7 @@ import io.element.android.libraries.designsystem.components.avatar.avatarShape
import io.element.android.libraries.designsystem.preview.ElementThemedPreview import io.element.android.libraries.designsystem.preview.ElementThemedPreview
import io.element.android.libraries.designsystem.preview.PreviewGroup import io.element.android.libraries.designsystem.preview.PreviewGroup
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import java.util.Collections import java.util.Collections
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.cos import kotlin.math.cos
@@ -134,7 +134,7 @@ internal fun AvatarClusterPreview() = ElementThemedPreview {
) { ) {
for (ngOfAvatars in 1..5) { for (ngOfAvatars in 1..5) {
AvatarCluster( AvatarCluster(
avatars = List(ngOfAvatars) { anAvatarData(it) }.toPersistentList(), avatars = List(ngOfAvatars) { anAvatarData(it) }.toImmutableList(),
avatarType = avatarType, avatarType = avatarType,
) )
} }
@@ -8,7 +8,7 @@
package io.element.android.libraries.designsystem.components.media package io.element.android.libraries.designsystem.components.media
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlin.random.Random import kotlin.random.Random
/** /**
@@ -21,5 +21,5 @@ import kotlin.random.Random
fun createFakeWaveform(length: Int = 1000): ImmutableList<Float> { fun createFakeWaveform(length: Int = 1000): ImmutableList<Float> {
val random = Random(seed = 2) val random = Random(seed = 2)
return List(length) { random.nextFloat() } return List(length) { random.nextFloat() }
.toPersistentList() .toImmutableList()
} }
@@ -39,7 +39,7 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlin.math.roundToInt import kotlin.math.roundToInt
private const val DEFAULT_GRAPHICS_LAYER_ALPHA: Float = 0.99F private const val DEFAULT_GRAPHICS_LAYER_ALPHA: Float = 0.99F
@@ -187,14 +187,14 @@ internal fun WaveformPlaybackViewPreview() = ElementPreview {
showCursor = false, showCursor = false,
playbackProgress = 0.5f, playbackProgress = 0.5f,
onSeek = {}, onSeek = {},
waveform = aWaveForm().toPersistentList(), waveform = aWaveForm().toImmutableList(),
) )
WaveformPlaybackView( WaveformPlaybackView(
modifier = Modifier.height(34.dp), modifier = Modifier.height(34.dp),
showCursor = true, showCursor = true,
playbackProgress = 0.5f, playbackProgress = 0.5f,
onSeek = {}, onSeek = {},
waveform = List(1024) { it / 1024f }.toPersistentList(), waveform = List(1024) { it / 1024f }.toImmutableList(),
) )
} }
} }
@@ -215,7 +215,7 @@ private fun ImmutableList<Float>.normalisedData(maxSamplesCount: Int): Immutable
this this
} }
return result.toPersistentList() return result.toImmutableList()
} }
fun aWaveForm(): List<Float> { fun aWaveForm(): List<Float> {
@@ -28,14 +28,14 @@ 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.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
internal class CompoundIconChunkProvider : PreviewParameterProvider<IconChunk> { internal class CompoundIconChunkProvider : PreviewParameterProvider<IconChunk> {
override val values: Sequence<IconChunk> override val values: Sequence<IconChunk>
get() { get() {
val chunks = CompoundIcons.allResIds.chunked(36) val chunks = CompoundIcons.allResIds.chunked(36)
return chunks.mapIndexed { index, chunk -> return chunks.mapIndexed { index, chunk ->
IconChunk(index = index + 1, total = chunks.size, icons = chunk.toPersistentList()) IconChunk(index = index + 1, total = chunks.size, icons = chunk.toImmutableList())
} }
.asSequence() .asSequence()
} }
@@ -46,7 +46,7 @@ internal class OtherIconChunkProvider : PreviewParameterProvider<IconChunk> {
get() { get() {
val chunks = iconsOther.chunked(36) val chunks = iconsOther.chunked(36)
return chunks.mapIndexed { index, chunk -> return chunks.mapIndexed { index, chunk ->
IconChunk(index = index + 1, total = chunks.size, icons = chunk.toPersistentList()) IconChunk(index = index + 1, total = chunks.size, icons = chunk.toImmutableList())
} }
.asSequence() .asSequence()
} }
@@ -12,7 +12,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.activeRoomMembers import io.element.android.libraries.matrix.api.room.activeRoomMembers
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
@@ -38,7 +38,7 @@ fun BaseRoom.usersWithRole(role: RoomMember.Role): Flow<ImmutableList<RoomMember
.combine(readyMembersFlow) { powerLevels, membersState -> .combine(readyMembersFlow) { powerLevels, membersState ->
membersState.activeRoomMembers() membersState.activeRoomMembers()
.filter { powerLevels.contains(it.userId) } .filter { powerLevels.contains(it.userId) }
.toPersistentList() .toImmutableList()
} }
.distinctUntilChanged() .distinctUntilChanged()
} }
@@ -77,7 +77,7 @@ import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@@ -238,11 +238,11 @@ class RustMatrixClient(
override val ignoredUsersFlow = mxCallbackFlow<ImmutableList<UserId>> { override val ignoredUsersFlow = mxCallbackFlow<ImmutableList<UserId>> {
// Fetch the initial value manually, the SDK won't return it automatically // Fetch the initial value manually, the SDK won't return it automatically
channel.trySend(innerClient.ignoredUsers().map(::UserId).toPersistentList()) channel.trySend(innerClient.ignoredUsers().map(::UserId).toImmutableList())
innerClient.subscribeToIgnoredUsers(object : IgnoredUsersListener { innerClient.subscribeToIgnoredUsers(object : IgnoredUsersListener {
override fun call(ignoredUserIds: List<String>) { override fun call(ignoredUserIds: List<String>) {
channel.trySend(ignoredUserIds.map(::UserId).toPersistentList()) channel.trySend(ignoredUserIds.map(::UserId).toImmutableList())
} }
}) })
} }
@@ -22,7 +22,7 @@ import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsValuesMapper import io.element.android.libraries.matrix.impl.room.powerlevels.RoomPowerLevelsValuesMapper
import io.element.android.libraries.matrix.impl.room.tombstone.map import io.element.android.libraries.matrix.impl.room.tombstone.map
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentMap import kotlinx.collections.immutable.toImmutableMap
import org.matrix.rustcomponents.sdk.Membership import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.RoomHero import org.matrix.rustcomponents.sdk.RoomHero
import uniffi.matrix_sdk_base.EncryptionState import uniffi.matrix_sdk_base.EncryptionState
@@ -103,6 +103,6 @@ fun RoomHero.map(): MatrixUser = MatrixUser(
fun mapPowerLevels(roomPowerLevels: RustRoomPowerLevels): RoomPowerLevels { fun mapPowerLevels(roomPowerLevels: RustRoomPowerLevels): RoomPowerLevels {
return RoomPowerLevels( return RoomPowerLevels(
values = RoomPowerLevelsValuesMapper.map(roomPowerLevels.values()), values = RoomPowerLevelsValuesMapper.map(roomPowerLevels.values()),
users = roomPowerLevels.userPowerLevels().mapKeys { (key, _) -> UserId(key) }.toPersistentMap() users = roomPowerLevels.userPowerLevels().mapKeys { (key, _) -> UserId(key) }.toImmutableMap()
) )
} }
@@ -8,7 +8,7 @@
package io.element.android.libraries.matrix.impl.room.join package io.element.android.libraries.matrix.impl.room.join
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
fun RustJoinRule.map(): JoinRule { fun RustJoinRule.map(): JoinRule {
@@ -17,9 +17,9 @@ fun RustJoinRule.map(): JoinRule {
RustJoinRule.Private -> JoinRule.Private RustJoinRule.Private -> JoinRule.Private
RustJoinRule.Knock -> JoinRule.Knock RustJoinRule.Knock -> JoinRule.Knock
RustJoinRule.Invite -> JoinRule.Invite RustJoinRule.Invite -> JoinRule.Invite
is RustJoinRule.Restricted -> JoinRule.Restricted(rules.map { it.map() }.toPersistentList()) is RustJoinRule.Restricted -> JoinRule.Restricted(rules.map { it.map() }.toImmutableList())
is RustJoinRule.Custom -> JoinRule.Custom(repr) is RustJoinRule.Custom -> JoinRule.Custom(repr)
is RustJoinRule.KnockRestricted -> JoinRule.KnockRestricted(rules.map { it.map() }.toPersistentList()) is RustJoinRule.KnockRestricted -> JoinRule.KnockRestricted(rules.map { it.map() }.toImmutableList())
} }
} }
@@ -8,9 +8,6 @@
package io.element.android.libraries.matrix.impl.room package io.element.android.libraries.matrix.impl.room
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationMode
@@ -34,7 +31,6 @@ import io.element.android.libraries.matrix.test.room.defaultRoomPowerLevelValues
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
import org.junit.Test import org.junit.Test
import org.matrix.rustcomponents.sdk.Membership import org.matrix.rustcomponents.sdk.Membership
import uniffi.matrix_sdk_base.EncryptionState import uniffi.matrix_sdk_base.EncryptionState
@@ -113,15 +109,15 @@ class RoomInfoMapperTest {
notificationCount = 11L, notificationCount = 11L,
userDefinedNotificationMode = RoomNotificationMode.MUTE, userDefinedNotificationMode = RoomNotificationMode.MUTE,
hasRoomCall = true, hasRoomCall = true,
activeRoomCallParticipants = listOf(A_USER_ID_3).toImmutableList(), activeRoomCallParticipants = persistentListOf(A_USER_ID_3),
heroes = listOf( heroes = persistentListOf(
MatrixUser( MatrixUser(
userId = A_USER_ID, userId = A_USER_ID,
displayName = "displayName", displayName = "displayName",
avatarUrl = "avatarUrl", avatarUrl = "avatarUrl",
) )
).toImmutableList(), ),
pinnedEventIds = listOf(AN_EVENT_ID).toPersistentList(), pinnedEventIds = persistentListOf(AN_EVENT_ID),
creators = persistentListOf(A_USER_ID), creators = persistentListOf(A_USER_ID),
isMarkedUnread = false, isMarkedUnread = false,
numUnreadMessages = 12L, numUnreadMessages = 12L,
@@ -191,7 +187,7 @@ class RoomInfoMapperTest {
successorRoom = null, successorRoom = null,
isFavorite = true, isFavorite = true,
canonicalAlias = null, canonicalAlias = null,
alternativeAliases = emptyList<RoomAlias>().toPersistentList(), alternativeAliases = persistentListOf(),
currentUserMembership = CurrentUserMembership.INVITED, currentUserMembership = CurrentUserMembership.INVITED,
inviter = null, inviter = null,
activeMembersCount = 2L, activeMembersCount = 2L,
@@ -205,9 +201,9 @@ class RoomInfoMapperTest {
notificationCount = 11L, notificationCount = 11L,
userDefinedNotificationMode = null, userDefinedNotificationMode = null,
hasRoomCall = false, hasRoomCall = false,
activeRoomCallParticipants = emptyList<UserId>().toImmutableList(), activeRoomCallParticipants = persistentListOf(),
heroes = emptyList<MatrixUser>().toImmutableList(), heroes = persistentListOf(),
pinnedEventIds = emptyList<EventId>().toPersistentList(), pinnedEventIds = persistentListOf(),
creators = persistentListOf(), creators = persistentListOf(),
isMarkedUnread = true, isMarkedUnread = true,
numUnreadMessages = 12L, numUnreadMessages = 12L,
@@ -32,7 +32,6 @@ import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toPersistentList
fun aRoomSummary( fun aRoomSummary(
info: RoomInfo = aRoomInfo(), info: RoomInfo = aRoomInfo(),
@@ -109,7 +108,7 @@ fun aRoomSummary(
userDefinedNotificationMode = userDefinedNotificationMode, userDefinedNotificationMode = userDefinedNotificationMode,
hasRoomCall = hasRoomCall, hasRoomCall = hasRoomCall,
activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(), activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(),
heroes = heroes.toPersistentList(), heroes = heroes.toImmutableList(),
pinnedEventIds = pinnedEventIds.toImmutableList(), pinnedEventIds = pinnedEventIds.toImmutableList(),
creators = roomCreators.toImmutableList(), creators = roomCreators.toImmutableList(),
isMarkedUnread = isMarkedUnread, isMarkedUnread = isMarkedUnread,
@@ -16,7 +16,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getAvatarData
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@@ -46,7 +46,7 @@ fun JoinedRoom.roomMemberIdentityStateChange(waitForEncryption: Boolean): Flow<I
identityRoomMember = member, identityRoomMember = member,
identityState = identityStateChange.identityState, identityState = identityStateChange.identityState,
) )
}.toPersistentList() }.toImmutableList()
}.distinctUntilChanged() }.distinctUntilChanged()
} }
} }
@@ -15,7 +15,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.mediaviewer.impl.model.MediaItem import io.element.android.libraries.mediaviewer.impl.model.MediaItem
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
@@ -69,7 +69,7 @@ class TimelineMediaItemsFactory(
newTimelineItemStates.add(cacheItem) newTimelineItemStates.add(cacheItem)
} }
} }
_timelineItems.emit(newTimelineItemStates.toPersistentList()) _timelineItems.emit(newTimelineItemStates.toImmutableList())
} }
private fun buildAndCacheItem( private fun buildAndCacheItem(
@@ -53,7 +53,7 @@ import io.element.android.libraries.voiceplayer.api.VoiceMessageEvents
import io.element.android.libraries.voiceplayer.api.VoiceMessageState import io.element.android.libraries.voiceplayer.api.VoiceMessageState
import io.element.android.libraries.voiceplayer.api.VoiceMessageStateProvider import io.element.android.libraries.voiceplayer.api.VoiceMessageStateProvider
import io.element.android.libraries.voiceplayer.api.aVoiceMessageState import io.element.android.libraries.voiceplayer.api.aVoiceMessageState
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@Composable @Composable
@@ -133,7 +133,7 @@ private fun VoiceInfoRow(
.height(34.dp), .height(34.dp),
showCursor = state.showCursor, showCursor = state.showCursor,
playbackProgress = state.progress, playbackProgress = state.progress,
waveform = voice.mediaInfo.waveform.orEmpty().toPersistentList(), waveform = voice.mediaInfo.waveform.orEmpty().toImmutableList(),
onSeek = { onSeek = {
state.eventSink(VoiceMessageEvents.Seek(it)) state.eventSink(VoiceMessageEvents.Seek(it))
}, },
@@ -71,7 +71,7 @@ import io.element.android.libraries.mediaviewer.impl.local.player.rememberExoPla
import io.element.android.libraries.mediaviewer.impl.local.player.seekToEnsurePlaying import io.element.android.libraries.mediaviewer.impl.local.player.seekToEnsurePlaying
import io.element.android.libraries.mediaviewer.impl.local.player.togglePlay import io.element.android.libraries.mediaviewer.impl.local.player.togglePlay
import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@SuppressLint("UnsafeOptInUsageError") @SuppressLint("UnsafeOptInUsageError")
@@ -252,7 +252,7 @@ private fun ExoPlayerMediaAudioView(
.height(48.dp), .height(48.dp),
playbackProgress = mediaPlayerControllerState.progressAsFloat, playbackProgress = mediaPlayerControllerState.progressAsFloat,
showCursor = true, showCursor = true,
waveform = waveform.toPersistentList(), waveform = waveform.toImmutableList(),
onSeek = { onSeek = {
exoPlayer.seekToEnsurePlaying((it * exoPlayer.duration).toLong()) exoPlayer.seekToEnsurePlaying((it * exoPlayer.duration).toLong())
}, },
@@ -30,9 +30,9 @@ import io.element.android.libraries.mediaviewer.impl.model.mediaInfo
import io.element.android.libraries.mediaviewer.impl.model.mediaSource import io.element.android.libraries.mediaviewer.impl.model.mediaSource
import io.element.android.libraries.mediaviewer.impl.model.thumbnailSource import io.element.android.libraries.mediaviewer.impl.model.thumbnailSource
import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@@ -72,12 +72,12 @@ class MediaViewerDataSource(
} }
@Composable @Composable
fun collectAsState(): State<PersistentList<MediaViewerPageData>> { fun collectAsState(): State<ImmutableList<MediaViewerPageData>> {
return remember { dataFlow() }.collectAsState(initialData()) return remember { dataFlow() }.collectAsState(initialData())
} }
@VisibleForTesting @VisibleForTesting
internal fun dataFlow(): Flow<PersistentList<MediaViewerPageData>> { internal fun dataFlow(): Flow<ImmutableList<MediaViewerPageData>> {
return galleryDataSource.groupedMediaItemsFlow() return galleryDataSource.groupedMediaItemsFlow()
.map { groupedItems -> .map { groupedItems ->
when (groupedItems) { when (groupedItems) {
@@ -106,7 +106,7 @@ class MediaViewerDataSource(
} }
} }
private fun initialData(): PersistentList<MediaViewerPageData> { private fun initialData(): ImmutableList<MediaViewerPageData> {
val initialMediaItems = val initialMediaItems =
galleryDataSource.getLastData().dataOrNull()?.getItems(galleryMode).orEmpty() galleryDataSource.getLastData().dataOrNull()?.getItems(galleryMode).orEmpty()
return buildMediaViewerPageList(initialMediaItems) return buildMediaViewerPageList(initialMediaItems)
@@ -149,7 +149,7 @@ class MediaViewerDataSource(
) )
} }
} }
}.toPersistentList() }.toImmutableList()
fun clearLoadingError(data: MediaViewerPageData.MediaViewerData) { fun clearLoadingError(data: MediaViewerPageData.MediaViewerData) {
localMediaStates[data.mediaSource.url]?.value = AsyncData.Uninitialized localMediaStates[data.mediaSource.url]?.value = AsyncData.Uninitialized
@@ -40,7 +40,7 @@ import io.element.android.libraries.mediaviewer.impl.R
import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState
import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions import io.element.android.libraries.mediaviewer.impl.local.LocalMediaActions
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
@@ -162,7 +162,7 @@ class MediaViewerPresenter(
@Composable @Composable
private fun NoMoreItemsBackwardSnackBarDisplayer( private fun NoMoreItemsBackwardSnackBarDisplayer(
currentIndex: IntState, currentIndex: IntState,
data: State<PersistentList<MediaViewerPageData>>, data: State<ImmutableList<MediaViewerPageData>>,
) { ) {
val isRenderingLoadingBackward by remember { val isRenderingLoadingBackward by remember {
derivedStateOf { derivedStateOf {
@@ -186,7 +186,7 @@ class MediaViewerPresenter(
@Composable @Composable
private fun NoMoreItemsForwardSnackBarDisplayer( private fun NoMoreItemsForwardSnackBarDisplayer(
currentIndex: IntState, currentIndex: IntState,
data: State<PersistentList<MediaViewerPageData>>, data: State<ImmutableList<MediaViewerPageData>>,
) { ) {
val isRenderingLoadingForward by remember { val isRenderingLoadingForward by remember {
derivedStateOf { derivedStateOf {
@@ -26,7 +26,7 @@ import io.element.android.libraries.mediaviewer.api.local.LocalMedia
import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.MediaBottomSheetState
import io.element.android.libraries.mediaviewer.impl.details.aMediaDeleteConfirmationState import io.element.android.libraries.mediaviewer.impl.details.aMediaDeleteConfirmationState
import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState import io.element.android.libraries.mediaviewer.impl.details.aMediaDetailsBottomSheetState
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
open class MediaViewerStateProvider : PreviewParameterProvider<MediaViewerState> { open class MediaViewerStateProvider : PreviewParameterProvider<MediaViewerState> {
override val values: Sequence<MediaViewerState> override val values: Sequence<MediaViewerState>
@@ -204,7 +204,7 @@ fun aMediaViewerState(
eventSink: (MediaViewerEvents) -> Unit = {}, eventSink: (MediaViewerEvents) -> Unit = {},
) = MediaViewerState( ) = MediaViewerState(
initiallySelectedEventId = EventId("\$a:b"), initiallySelectedEventId = EventId("\$a:b"),
listData = listData.toPersistentList(), listData = listData.toImmutableList(),
currentIndex = currentIndex, currentIndex = currentIndex,
snackbarMessage = null, snackbarMessage = null,
canShowInfo = canShowInfo, canShowInfo = canShowInfo,
@@ -16,8 +16,8 @@ import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally
import io.element.android.libraries.matrix.ui.model.SelectRoomInfo import io.element.android.libraries.matrix.ui.model.SelectRoomInfo
import io.element.android.libraries.matrix.ui.model.toSelectRoomInfo import io.element.android.libraries.matrix.ui.model.toSelectRoomInfo
import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
@@ -40,13 +40,13 @@ class RoomSelectSearchDataSource(
source = RoomList.Source.All, source = RoomList.Source.All,
) )
val roomInfoList: Flow<PersistentList<SelectRoomInfo>> = roomList.filteredSummaries val roomInfoList: Flow<ImmutableList<SelectRoomInfo>> = roomList.filteredSummaries
.map { roomSummaries -> .map { roomSummaries ->
roomSummaries roomSummaries
.filter { it.info.currentUserMembership == CurrentUserMembership.JOINED } .filter { it.info.currentUserMembership == CurrentUserMembership.JOINED }
.distinctBy { it.roomId } // This should be removed once we're sure no duplicate Rooms can be received .distinctBy { it.roomId } // This should be removed once we're sure no duplicate Rooms can be received
.map { roomSummary -> roomSummary.toSelectRoomInfo() } .map { roomSummary -> roomSummary.toSelectRoomInfo() }
.toPersistentList() .toImmutableList()
} }
.flowOn(coroutineDispatchers.computation) .flowOn(coroutineDispatchers.computation)
@@ -53,7 +53,7 @@ import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.libraries.roomselect.api.RoomSelectMode import io.element.android.libraries.roomselect.api.RoomSelectMode
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
@Suppress("MultipleEmitters") // False positive @Suppress("MultipleEmitters") // False positive
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -214,7 +214,7 @@ private fun RoomSummaryView(
avatarType = AvatarType.Room( avatarType = AvatarType.Room(
heroes = roomInfo.heroes.map { user -> heroes = roomInfo.heroes.map { user ->
user.getAvatarData(size = AvatarSize.RoomSelectRoomListItem) user.getAvatarData(size = AvatarSize.RoomSelectRoomListItem)
}.toPersistentList(), }.toImmutableList(),
isTombstoned = roomInfo.isTombstoned, isTombstoned = roomInfo.isTombstoned,
), ),
) )
@@ -35,7 +35,7 @@ import io.element.android.libraries.designsystem.components.media.drawWaveform
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import java.lang.Float.min import java.lang.Float.min
private const val DEFAULT_GRAPHICS_LAYER_ALPHA: Float = 0.99F private const val DEFAULT_GRAPHICS_LAYER_ALPHA: Float = 0.99F
@@ -62,21 +62,21 @@ fun LiveWaveformView(
Box( Box(
contentAlignment = Alignment.CenterEnd, contentAlignment = Alignment.CenterEnd,
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.height(waveFormHeight) .height(waveFormHeight)
.onSizeChanged { parentWidth = it.width } .onSizeChanged { parentWidth = it.width }
) { ) {
Canvas( Canvas(
modifier = Modifier modifier = Modifier
.width(Dp(waveformWidth)) .width(Dp(waveformWidth))
.graphicsLayer(alpha = DEFAULT_GRAPHICS_LAYER_ALPHA) .graphicsLayer(alpha = DEFAULT_GRAPHICS_LAYER_ALPHA)
.then(modifier) .then(modifier)
) { ) {
val width = min(waveformWidth, parentWidth.toFloat()) val width = min(waveformWidth, parentWidth.toFloat())
canvasSize = DpSize(width.dp, size.height.toDp()) canvasSize = DpSize(width.dp, size.height.toDp())
val countThatFitsWidth = (parentWidth.toFloat() / (lineWidth.toPx() + linePadding.toPx())).toInt() val countThatFitsWidth = (parentWidth.toFloat() / (lineWidth.toPx() + linePadding.toPx())).toInt()
drawWaveform( drawWaveform(
waveformData = levels.takeLast(countThatFitsWidth).toPersistentList(), waveformData = levels.takeLast(countThatFitsWidth).toImmutableList(),
canvasSizePx = Size(canvasSize.width.toPx(), size.height), canvasSizePx = Size(canvasSize.width.toPx(), size.height),
brush = brush, brush = brush,
lineWidth = lineWidth, lineWidth = lineWidth,
@@ -91,11 +91,11 @@ fun LiveWaveformView(
internal fun LiveWaveformViewPreview() = ElementPreview { internal fun LiveWaveformViewPreview() = ElementPreview {
Column { Column {
LiveWaveformView( LiveWaveformView(
levels = List(100) { it.toFloat() / 100 }.toPersistentList(), levels = List(100) { it.toFloat() / 100 }.toImmutableList(),
modifier = Modifier.height(34.dp), modifier = Modifier.height(34.dp),
) )
LiveWaveformView( LiveWaveformView(
levels = List(40) { it.toFloat() / 40 }.toPersistentList(), levels = List(40) { it.toFloat() / 40 }.toImmutableList(),
modifier = Modifier.height(34.dp), modifier = Modifier.height(34.dp),
) )
} }
@@ -35,7 +35,7 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.ui.utils.time.formatShort import io.element.android.libraries.ui.utils.time.formatShort
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toPersistentList import kotlinx.collections.immutable.toImmutableList
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@@ -101,5 +101,5 @@ private fun RedRecordingDot() {
@PreviewsDayNight @PreviewsDayNight
@Composable @Composable
internal fun VoiceMessageRecordingPreview() = ElementPreview { internal fun VoiceMessageRecordingPreview() = ElementPreview {
VoiceMessageRecording(List(100) { it.toFloat() / 100 }.toPersistentList(), 0.seconds) VoiceMessageRecording(List(100) { it.toFloat() / 100 }.toImmutableList(), 0.seconds)
} }
@@ -0,0 +1,63 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.tests.konsist
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.withoutName
import com.lemonappdev.konsist.api.verify.assertFalse
import org.junit.Test
class KonsistImmutableTest {
/**
* toPersistentList() returns a PersistentList which allow mutations, while toImmutableList() returns
* an ImmutableList which does not allow mutations. Generally, we do not use the mutation features,
* so we should prefer toImmutableList.
*/
@Test
fun `toPersistentList() should not be used instead of toImmutableList()`() {
Konsist
.scopeFromProject()
.functions()
.withoutName("toPersistentList() should not be used instead of toImmutableList()")
.assertFalse(additionalMessage = "Please use toImmutableList() instead of toPersistentList()") {
it.text.contains(".toPersistentList()")
}
}
/**
* toPersistentSet() returns a PersistentSet which allow mutations, while toImmutableSet() returns
* an ImmutableSet which does not allow mutations. Generally, we do not use the mutation features,
* so we should prefer toImmutableSet.
*/
@Test
fun `toPersistentSet() should not be used instead of toImmutableSet()`() {
Konsist
.scopeFromProject()
.functions()
.withoutName("toPersistentSet() should not be used instead of toImmutableSet()")
.assertFalse(additionalMessage = "Please use toImmutableSet() instead of toPersistentSet()") {
it.text.contains(".toPersistentSet()")
}
}
/**
* toPersistentMap() returns a PersistentMap which allow mutations, while toImmutableMap() returns
* an ImmutableMap which does not allow mutations. Generally, we do not use the mutation features,
* so we should prefer toImmutableMap.
*/
@Test
fun `toPersistentMap() should not be used instead of toImmutableMap()`() {
Konsist
.scopeFromProject()
.functions()
.withoutName("toPersistentMap() should not be used instead of toImmutableMap()")
.assertFalse(additionalMessage = "Please use toImmutableMap() instead of toPersistentMap()") {
it.text.contains(".toPersistentMap()")
}
}
}