Merge branch 'develop' into feature/fga/user_detail_direct_chat

This commit is contained in:
ganfra 2023-11-30 18:10:51 +01:00
commit 03a2e31d46
76 changed files with 329 additions and 148 deletions

View file

@ -79,6 +79,7 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
import io.element.android.libraries.matrix.ui.room.canRedactAsState
@ -108,6 +109,7 @@ class MessagesPresenter @AssistedInject constructor(
private val featureFlagsService: FeatureFlagService,
@Assisted private val navigator: MessagesNavigator,
private val buildMeta: BuildMeta,
private val currentSessionIdHolder: CurrentSessionIdHolder,
) : Presenter<MessagesState> {
private val timelinePresenter = timelinePresenterFactory.create(navigator = navigator)
@ -133,10 +135,10 @@ class MessagesPresenter @AssistedInject constructor(
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
val userHasPermissionToSendMessage by room.canSendMessageAsState(type = MessageEventType.ROOM_MESSAGE, updateKey = syncUpdateFlow.value)
val userHasPermissionToRedact by room.canRedactAsState(updateKey = syncUpdateFlow.value)
val roomName: Async<String> by remember(roomInfo?.name) {
val roomName: Async<String> by remember {
derivedStateOf { roomInfo?.name?.let { Async.Success(it) } ?: Async.Uninitialized }
}
val roomAvatar: Async<AvatarData> by remember(roomInfo?.avatarUrl) {
val roomAvatar: Async<AvatarData> by remember {
derivedStateOf { roomInfo?.avatarData()?.let { Async.Success(it) } ?: Async.Uninitialized }
}
@ -144,6 +146,16 @@ class MessagesPresenter @AssistedInject constructor(
mutableStateOf(false)
}
var canJoinCall by rememberSaveable {
mutableStateOf(false)
}
LaunchedEffect(currentSessionIdHolder.current) {
withContext(dispatchers.io) {
canJoinCall = room.canUserJoinCall(userId = currentSessionIdHolder.current).getOrDefault(false)
}
}
val inviteProgress = remember { mutableStateOf<Async<Unit>>(Async.Uninitialized) }
var showReinvitePrompt by remember { mutableStateOf(false) }
LaunchedEffect(hasDismissedInviteDialog, composerState.hasFocus, syncUpdateFlow) {
@ -162,8 +174,6 @@ class MessagesPresenter @AssistedInject constructor(
val enableTextFormatting by preferencesStore.isRichTextEditorEnabledFlow().collectAsState(initial = true)
var enableVoiceMessages by remember { mutableStateOf(false) }
// TODO add min power level to use this feature in the future?
val enableInRoomCalls = true
LaunchedEffect(featureFlagsService) {
enableVoiceMessages = featureFlagsService.isFeatureEnabled(FeatureFlags.VoiceMessages)
}
@ -193,6 +203,12 @@ class MessagesPresenter @AssistedInject constructor(
}
}
val callState = when {
!canJoinCall -> RoomCallState.DISABLED
roomInfo?.hasRoomCall == true -> RoomCallState.ONGOING
else -> RoomCallState.ENABLED
}
return MessagesState(
roomId = room.roomId,
roomName = roomName,
@ -213,9 +229,8 @@ class MessagesPresenter @AssistedInject constructor(
inviteProgress = inviteProgress.value,
enableTextFormatting = enableTextFormatting,
enableVoiceMessages = enableVoiceMessages,
enableInRoomCalls = enableInRoomCalls,
appName = buildMeta.applicationName,
isCallOngoing = roomInfo?.hasRoomCall ?: false,
callState = callState,
eventSink = { handleEvents(it) }
)
}

View file

@ -51,8 +51,13 @@ data class MessagesState(
val showReinvitePrompt: Boolean,
val enableTextFormatting: Boolean,
val enableVoiceMessages: Boolean,
val enableInRoomCalls: Boolean,
val isCallOngoing: Boolean,
val callState: RoomCallState,
val appName: String,
val eventSink: (MessagesEvents) -> Unit
)
enum class RoomCallState {
ENABLED,
ONGOING,
DISABLED
}

View file

@ -66,7 +66,7 @@ open class MessagesStateProvider : PreviewParameterProvider<MessagesState> {
),
),
aMessagesState().copy(
isCallOngoing = true,
callState = RoomCallState.ONGOING,
),
aMessagesState().copy(
enableVoiceMessages = true,
@ -75,6 +75,9 @@ open class MessagesStateProvider : PreviewParameterProvider<MessagesState> {
showSendFailureDialog = true
),
),
aMessagesState().copy(
callState = RoomCallState.DISABLED,
),
)
}
@ -117,8 +120,7 @@ fun aMessagesState() = MessagesState(
showReinvitePrompt = false,
enableTextFormatting = true,
enableVoiceMessages = true,
enableInRoomCalls = true,
isCallOngoing = false,
callState = RoomCallState.ENABLED,
appName = "Element",
eventSink = {}
)

View file

@ -191,10 +191,9 @@ fun MessagesView(
MessagesViewTopBar(
roomName = state.roomName.dataOrNull(),
roomAvatar = state.roomAvatar.dataOrNull(),
inRoomCallsEnabled = state.enableInRoomCalls,
callState = state.callState,
onBackPressed = onBackPressed,
onRoomDetailsClicked = onRoomDetailsClicked,
isCallOngoing = state.isCallOngoing,
onJoinCallClicked = onJoinCallClicked,
)
}
@ -449,8 +448,7 @@ private fun MessagesViewComposerBottomSheetContents(
private fun MessagesViewTopBar(
roomName: String?,
roomAvatar: AvatarData?,
inRoomCallsEnabled: Boolean,
isCallOngoing: Boolean,
callState: RoomCallState,
onRoomDetailsClicked: () -> Unit,
onJoinCallClicked: () -> Unit,
onBackPressed: () -> Unit,
@ -477,13 +475,11 @@ private fun MessagesViewTopBar(
}
},
actions = {
if (inRoomCallsEnabled) {
if (isCallOngoing) {
JoinCallMenuItem(onJoinCallClicked = onJoinCallClicked)
} else {
IconButton(onClick = onJoinCallClicked) {
Icon(CompoundIcons.VideoCall, contentDescription = stringResource(CommonStrings.a11y_start_call))
}
if (callState == RoomCallState.ONGOING) {
JoinCallMenuItem(onJoinCallClicked = onJoinCallClicked)
} else {
IconButton(onClick = onJoinCallClicked, enabled = callState != RoomCallState.DISABLED) {
Icon(CompoundIcons.VideoCall, contentDescription = stringResource(CommonStrings.a11y_start_call))
}
}
Spacer(Modifier.width(8.dp))

View file

@ -45,6 +45,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
@PreviewsDayNight
@Composable
@ -127,8 +129,8 @@ class InReplyToDetailsProvider : PreviewParameterProvider<InReplyToDetails> {
question = "Poll which are being replied.",
kind = PollKind.Disclosed,
maxSelections = 1u,
answers = emptyList(),
votes = emptyMap(),
answers = persistentListOf(),
votes = persistentMapOf(),
endTime = null
),
).map {

View file

@ -17,7 +17,6 @@
package io.element.android.features.messages.impl.timeline.components.reactionsummary
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
@ -38,10 +37,6 @@ class ReactionSummaryPresenter @Inject constructor(
) : Presenter<ReactionSummaryState> {
@Composable
override fun present(): ReactionSummaryState {
LaunchedEffect(Unit) {
room.updateMembers()
}
val membersState by room.membersStateFlow.collectAsState()
val target: MutableState<ReactionSummaryState.Summary?> = remember {

View file

@ -92,12 +92,14 @@ import io.element.android.tests.testutils.consumeItemsUntilTimeout
import io.element.android.tests.testutils.testCoroutineDispatchers
import io.element.android.tests.testutils.waitForPredicate
import io.mockk.mockk
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
import kotlin.time.Duration.Companion.milliseconds
@Suppress("LargeClass")
class MessagesPresenterTest {
@get:Rule
@ -125,6 +127,21 @@ class MessagesPresenterTest {
}
}
@Test
fun `present - call is disabled if user cannot join it even if there is an ongoing call`() = runTest {
val room = FakeMatrixRoom().apply {
givenCanUserJoinCall(Result.success(false))
givenRoomInfo(aRoomInfo(hasRoomCall = true))
}
val presenter = createMessagesPresenter(matrixRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = consumeItemsUntilTimeout().last()
assertThat(initialState.callState).isEqualTo(RoomCallState.DISABLED)
}
}
@Test
fun `present - handle toggling a reaction`() = runTest {
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
@ -462,7 +479,7 @@ class MessagesPresenterTest {
val room = FakeMatrixRoom(sessionId = A_SESSION_ID)
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
listOf(
persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
@ -489,7 +506,7 @@ class MessagesPresenterTest {
room.givenRoomMembersState(
MatrixRoomMembersState.Error(
failure = Throwable(),
prevRoomMembers = listOf(
prevRoomMembers = persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
@ -535,7 +552,7 @@ class MessagesPresenterTest {
val room = FakeMatrixRoom(sessionId = A_SESSION_ID)
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
listOf(
persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
@ -655,6 +672,7 @@ class MessagesPresenterTest {
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
currentSessionIdHolder: CurrentSessionIdHolder = CurrentSessionIdHolder(FakeMatrixClient(A_SESSION_ID)),
): MessagesPresenter {
val mediaSender = MediaSender(FakeMediaPreProcessor(), matrixRoom)
val permissionsPresenterFactory = FakePermissionsPresenterFactory(permissionsPresenter)
@ -723,6 +741,7 @@ class MessagesPresenterTest {
featureFlagsService = FakeFeatureFlagService(),
buildMeta = aBuildMeta(),
dispatchers = coroutineDispatchers,
currentSessionIdHolder = currentSessionIdHolder,
)
}
}

View file

@ -78,11 +78,11 @@ import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.waitForPredicate
import io.mockk.mockk
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import okhttp3.internal.immutableListOf
import org.junit.Rule
import org.junit.Test
import uniffi.wysiwyg_composer.MentionsState
@ -734,7 +734,7 @@ class MessageComposerPresenterTest {
isOneToOne = false,
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(
immutableListOf(currentUser, invitedUser, bob, david),
persistentListOf(currentUser, invitedUser, bob, david),
))
givenCanTriggerRoomNotification(Result.success(true))
}
@ -798,7 +798,7 @@ class MessageComposerPresenterTest {
isOneToOne = true,
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(
immutableListOf(currentUser, invitedUser, bob, david),
persistentListOf(currentUser, invitedUser, bob, david),
))
givenCanTriggerRoomNotification(Result.success(true))
}

View file

@ -55,6 +55,7 @@ import io.element.android.tests.testutils.awaitWithLatch
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.testCoroutineDispatchers
import io.element.android.tests.testutils.waitForPredicate
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@ -254,18 +255,18 @@ class TimelinePresenterTest {
val (alice, bob, charlie) = aMatrixUserList().take(3).mapIndexed { i, user ->
ReactionSender(senderId = user.userId, timestamp = now + i * minuteInMillis)
}
val oneReaction = listOf(
val oneReaction = persistentListOf(
EventReaction(
key = "❤️",
senders = listOf(alice, charlie)
senders = persistentListOf(alice, charlie)
),
EventReaction(
key = "👍",
senders = listOf(alice, bob)
senders = persistentListOf(alice, bob)
),
EventReaction(
key = "🐶",
senders = listOf(charlie)
senders = persistentListOf(charlie)
),
)
timeline.updateTimelineItems {

View file

@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -42,7 +43,7 @@ class ReactionSummaryPresenterTests {
private val roomMember = aRoomMember(userId = A_USER_ID, avatarUrl = AN_AVATAR_URL, displayName = A_USER_NAME)
private val summaryEvent = ReactionSummaryEvents.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key)
private val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
private val presenter = ReactionSummaryPresenter(room)

View file

@ -55,6 +55,7 @@ import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageT
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.ui.components.A_BLUR_HASH
import io.element.android.libraries.mediaviewer.api.util.FileExtensionExtractorWithoutValidation
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -280,7 +281,7 @@ class TimelineItemContentMessageFactoryTest {
),
details = AudioDetails(
duration = 1.minutes,
waveform = listOf(1f, 2f),
waveform = persistentListOf(1f, 2f),
),
)
),
@ -293,7 +294,7 @@ class TimelineItemContentMessageFactoryTest {
duration = 1.minutes,
mediaSource = MediaSource(url = "url", json = null),
mimeType = MimeTypes.Ogg,
waveform = listOf(1f, 2f).toImmutableList()
waveform = persistentListOf(1f, 2f)
)
assertThat(result).isEqualTo(expected)
}

View file

@ -38,6 +38,11 @@ import io.element.android.libraries.matrix.test.A_USER_ID_7
import io.element.android.libraries.matrix.test.A_USER_ID_8
import io.element.android.libraries.matrix.test.A_USER_ID_9
import io.element.android.libraries.matrix.test.FakeMatrixClient
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -55,7 +60,7 @@ internal class TimelineItemContentPollFactoryTest {
@Test
fun `Disclosed poll - not ended, some votes, including one from current user`() = runTest {
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }.toImmutableMap()
Truth.assertThat(
factory.create(aPollContent(votes = votes), eventId = null)
)
@ -87,7 +92,7 @@ internal class TimelineItemContentPollFactoryTest {
@Test
fun `Disclosed poll - ended, some votes, including one from current user (winner)`() = runTest {
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }.toImmutableMap()
Truth.assertThat(
factory.create(aPollContent(votes = votes, endTime = 1UL), eventId = null)
)
@ -106,7 +111,7 @@ internal class TimelineItemContentPollFactoryTest {
@Test
fun `Disclosed poll - ended, some votes, including one from current user (not winner) and two winning votes`() = runTest {
val votes = OTHER_WINNING_VOTES.mapKeys { it.key.id }
val votes = OTHER_WINNING_VOTES.mapKeys { it.key.id }.toImmutableMap()
Truth.assertThat(
factory.create(aPollContent(votes = votes, endTime = 1UL), eventId = null)
)
@ -136,7 +141,7 @@ internal class TimelineItemContentPollFactoryTest {
@Test
fun `Undisclosed poll - not ended, some votes, including one from current user`() = runTest {
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }.toImmutableMap()
Truth.assertThat(
factory.create(aPollContent(pollKind = PollKind.Undisclosed, votes = votes), eventId = null)
)
@ -172,7 +177,7 @@ internal class TimelineItemContentPollFactoryTest {
@Test
fun `Undisclosed poll - ended, some votes, including one from current user (winner)`() = runTest {
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }
val votes = MY_USER_WINNING_VOTES.mapKeys { it.key.id }.toImmutableMap()
Truth.assertThat(
factory.create(aPollContent(pollKind = PollKind.Undisclosed, votes = votes, endTime = 1UL), eventId = null)
)
@ -192,7 +197,7 @@ internal class TimelineItemContentPollFactoryTest {
@Test
fun `Undisclosed poll - ended, some votes, including one from current user (not winner) and two winning votes`() = runTest {
val votes = OTHER_WINNING_VOTES.mapKeys { it.key.id }
val votes = OTHER_WINNING_VOTES.mapKeys { it.key.id }.toImmutableMap()
Truth.assertThat(
factory.create(aPollContent(PollKind.Undisclosed).copy(votes = votes, endTime = 1UL), eventId = null)
)
@ -221,13 +226,13 @@ internal class TimelineItemContentPollFactoryTest {
private fun aPollContent(
pollKind: PollKind = PollKind.Disclosed,
votes: Map<String, List<UserId>> = emptyMap(),
votes: ImmutableMap<String, ImmutableList<UserId>> = persistentMapOf(),
endTime: ULong? = null,
): PollContent = PollContent(
question = A_POLL_QUESTION,
kind = pollKind,
maxSelections = 1UL,
answers = listOf(A_POLL_ANSWER_1, A_POLL_ANSWER_2, A_POLL_ANSWER_3, A_POLL_ANSWER_4),
answers = persistentListOf(A_POLL_ANSWER_1, A_POLL_ANSWER_2, A_POLL_ANSWER_3, A_POLL_ANSWER_4),
votes = votes,
endTime = endTime,
)
@ -275,17 +280,17 @@ internal class TimelineItemContentPollFactoryTest {
private val A_POLL_ANSWER_3 = PollAnswer("id_3", "French Fries")
private val A_POLL_ANSWER_4 = PollAnswer("id_4", "Hamburger")
private val MY_USER_WINNING_VOTES = mapOf(
A_POLL_ANSWER_1 to listOf(A_USER_ID_2, A_USER_ID_3, A_USER_ID_4),
A_POLL_ANSWER_2 to listOf(A_USER_ID /* my vote */, A_USER_ID_5, A_USER_ID_6, A_USER_ID_7, A_USER_ID_8, A_USER_ID_9), // winner
A_POLL_ANSWER_3 to emptyList(),
A_POLL_ANSWER_4 to listOf(A_USER_ID_10),
private val MY_USER_WINNING_VOTES = persistentMapOf(
A_POLL_ANSWER_1 to persistentListOf(A_USER_ID_2, A_USER_ID_3, A_USER_ID_4),
A_POLL_ANSWER_2 to persistentListOf(A_USER_ID /* my vote */, A_USER_ID_5, A_USER_ID_6, A_USER_ID_7, A_USER_ID_8, A_USER_ID_9), // winner
A_POLL_ANSWER_3 to persistentListOf(),
A_POLL_ANSWER_4 to persistentListOf(A_USER_ID_10),
)
private val OTHER_WINNING_VOTES = mapOf(
A_POLL_ANSWER_1 to listOf(A_USER_ID_2, A_USER_ID_3, A_USER_ID_4, A_USER_ID_5), // winner
A_POLL_ANSWER_2 to listOf(A_USER_ID /* my vote */, A_USER_ID_6),
A_POLL_ANSWER_3 to emptyList(),
A_POLL_ANSWER_4 to listOf(A_USER_ID_7, A_USER_ID_8, A_USER_ID_9, A_USER_ID_10), // winner
private val OTHER_WINNING_VOTES = persistentMapOf(
A_POLL_ANSWER_1 to persistentListOf(A_USER_ID_2, A_USER_ID_3, A_USER_ID_4, A_USER_ID_5), // winner
A_POLL_ANSWER_2 to persistentListOf(A_USER_ID /* my vote */, A_USER_ID_6),
A_POLL_ANSWER_3 to persistentListOf(),
A_POLL_ANSWER_4 to persistentListOf(A_USER_ID_7, A_USER_ID_8, A_USER_ID_9, A_USER_ID_10), // winner
)
}
}

View file

@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.mediaplayer.api.MediaPlayer
import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -88,8 +89,8 @@ fun aRedactedMatrixTimeline(eventId: EventId) = listOf<MatrixTimelineItem>(
isOwn = false,
isRemote = false,
localSendState = null,
reactions = listOf(),
receipts = listOf(),
reactions = persistentListOf(),
receipts = persistentListOf(),
sender = A_USER_ID,
senderProfile = ProfileTimelineDetails.Unavailable,
timestamp = 9442,

View file

@ -39,6 +39,7 @@ import io.element.android.libraries.matrix.test.room.anEventTimelineItem
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@ -539,7 +540,7 @@ class CreatePollPresenterTest {
private fun anExistingPoll() = aPollContent(
question = "Do you like polls?",
answers = listOf(
answers = persistentListOf(
PollAnswer("1", "Yes"),
PollAnswer("2", "No"),
PollAnswer("2", "Maybe"),

View file

@ -33,6 +33,7 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.debounce
@ -84,7 +85,7 @@ class EditDefaultNotificationSettingPresenter @AssistedInject constructor(
return EditDefaultNotificationSettingState(
isOneToOne = isOneToOne,
mode = mode.value,
roomsWithUserDefinedMode = roomsWithUserDefinedMode.value,
roomsWithUserDefinedMode = roomsWithUserDefinedMode.value.toImmutableList(),
changeNotificationSettingAction = changeNotificationSettingAction.value,
eventSink = ::handleEvents
)

View file

@ -19,11 +19,12 @@ package io.element.android.features.preferences.impl.notifications.edit
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import kotlinx.collections.immutable.ImmutableList
data class EditDefaultNotificationSettingState(
val isOneToOne: Boolean,
val mode: RoomNotificationMode?,
val roomsWithUserDefinedMode: List<RoomSummary.Filled>,
val roomsWithUserDefinedMode: ImmutableList<RoomSummary.Filled>,
val changeNotificationSettingAction: Async<Unit>,
val eventSink: (EditDefaultNotificationSettingStateEvents) -> Unit,
)

View file

@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import kotlinx.collections.immutable.persistentListOf
open class EditDefaultNotificationSettingStateProvider: PreviewParameterProvider<EditDefaultNotificationSettingState> {
override val values: Sequence<EditDefaultNotificationSettingState>
@ -39,7 +40,7 @@ private fun anEditDefaultNotificationSettingsState(
) = EditDefaultNotificationSettingState(
isOneToOne = isOneToOne,
mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
roomsWithUserDefinedMode = listOf(aRoomSummary()),
roomsWithUserDefinedMode = persistentListOf(aRoomSummary()),
changeNotificationSettingAction = changeNotificationSettingAction,
eventSink = {}
)

View file

@ -90,7 +90,7 @@ fun aRoomMember(
isIgnored = isIgnored,
)
fun aRoomMemberList() = listOf(
fun aRoomMemberList() = persistentListOf(
anAlice(),
aBob(),
aRoomMember(UserId("@carol:server.org"), "Carol"),

View file

@ -49,6 +49,7 @@ import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@ -129,7 +130,7 @@ class RoomDetailsPresenterTests {
isEncrypted = true,
isDirect = true,
).apply {
val roomMembers = listOf(myRoomMember, otherRoomMember)
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
}
val presenter = createRoomDetailsPresenter(room)
@ -220,7 +221,7 @@ class RoomDetailsPresenterTests {
isEncrypted = true,
isDirect = true,
).apply {
val roomMembers = listOf(myRoomMember, otherRoomMember)
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true))
@ -253,7 +254,7 @@ class RoomDetailsPresenterTests {
isDirect = true,
topic = null,
).apply {
val roomMembers = listOf(myRoomMember, otherRoomMember)
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true))

View file

@ -39,6 +39,7 @@ import io.element.android.libraries.usersearch.test.FakeUserRepository
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@ -167,7 +168,7 @@ internal class RoomInviteMembersPresenterTest {
matrixRoom = FakeMatrixRoom().apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
listOf(
persistentListOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
)
@ -227,7 +228,7 @@ internal class RoomInviteMembersPresenterTest {
roomMemberListDataSource = createDataSource(FakeMatrixRoom().apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
listOf(
persistentListOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
)

View file

@ -39,6 +39,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@ -56,7 +57,7 @@ class RoomMemberDetailsPresenterTests {
val room = aMatrixRoom().apply {
givenUserDisplayNameResult(Result.success("A custom name"))
givenUserAvatarUrlResult(Result.success("A custom avatar"))
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
@ -83,7 +84,7 @@ class RoomMemberDetailsPresenterTests {
val room = aMatrixRoom().apply {
givenUserDisplayNameResult(Result.failure(Throwable()))
givenUserAvatarUrlResult(Result.failure(Throwable()))
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
@ -106,7 +107,7 @@ class RoomMemberDetailsPresenterTests {
val room = aMatrixRoom().apply {
givenUserDisplayNameResult(Result.success(null))
givenUserAvatarUrlResult(Result.success(null))
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(roomMember)))
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,

View file

@ -23,7 +23,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
@Immutable
data class RoomListRoomSummary constructor(
data class RoomListRoomSummary(
val id: String,
val roomId: RoomId,
val name: String = "",

View file

@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import io.element.android.libraries.matrix.api.verification.VerificationFlowState
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@ -132,7 +133,7 @@ class VerifySelfSessionPresenterTests {
presenter.present()
}.test {
requestVerificationAndAwaitVerifyingState(service)
service.givenVerificationFlowState(VerificationFlowState.ReceivedVerificationData(emptyList()))
service.givenVerificationFlowState(VerificationFlowState.ReceivedVerificationData(persistentListOf()))
ensureAllEventsConsumed()
}
}