Display a notice if Matrix ID isn't resolved (#461)
Display a notice if Matrix ID isn't resolved If we can't get the profile of a user after an mxid was searched for, show a warning under their ID to say the invite probably won't be delivered. Closes #424
This commit is contained in:
parent
0f27ad5a84
commit
36d372e1eb
89 changed files with 503 additions and 216 deletions
|
|
@ -22,40 +22,49 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.matrix.ui.components.CheckableMatrixUserRow
|
||||
import io.element.android.libraries.matrix.ui.components.CheckableUnresolvedUserRow
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
|
||||
@Composable
|
||||
fun SearchMultipleUsersResultItem(
|
||||
matrixUser: MatrixUser,
|
||||
searchResult: UserSearchResult,
|
||||
isUserSelected: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onCheckedChange: (Boolean) -> Unit = {},
|
||||
) {
|
||||
CheckableMatrixUserRow(
|
||||
checked = isUserSelected,
|
||||
modifier = modifier,
|
||||
matrixUser = matrixUser,
|
||||
avatarSize = AvatarSize.Custom(36.dp),
|
||||
onCheckedChange = onCheckedChange,
|
||||
)
|
||||
if (searchResult.isUnresolved) {
|
||||
CheckableUnresolvedUserRow(
|
||||
checked = isUserSelected,
|
||||
modifier = modifier,
|
||||
avatarData = searchResult.matrixUser.getAvatarData(AvatarSize.Custom(36.dp)),
|
||||
id = searchResult.matrixUser.userId.value,
|
||||
onCheckedChange = onCheckedChange,
|
||||
)
|
||||
} else {
|
||||
CheckableMatrixUserRow(
|
||||
checked = isUserSelected,
|
||||
modifier = modifier,
|
||||
matrixUser = searchResult.matrixUser,
|
||||
avatarSize = AvatarSize.Custom(36.dp),
|
||||
onCheckedChange = onCheckedChange,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SearchMultipleUsersResultItemLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SearchMultipleUsersResultItemDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
internal fun SearchMultipleUsersResultItemPreview() = ElementThemedPreview { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
SearchMultipleUsersResultItem(matrixUser = aMatrixUser(), isUserSelected = true)
|
||||
SearchMultipleUsersResultItem(matrixUser = aMatrixUser(), isUserSelected = false)
|
||||
SearchMultipleUsersResultItem(searchResult = UserSearchResult(aMatrixUser(), isUnresolved = false), isUserSelected = false)
|
||||
SearchMultipleUsersResultItem(searchResult = UserSearchResult(aMatrixUser(), isUnresolved = false), isUserSelected = true)
|
||||
SearchMultipleUsersResultItem(searchResult = UserSearchResult(aMatrixUser(), isUnresolved = true), isUserSelected = false)
|
||||
SearchMultipleUsersResultItem(searchResult = UserSearchResult(aMatrixUser(), isUnresolved = true), isUserSelected = true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,39 +17,48 @@
|
|||
package io.element.android.features.createroom.impl.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.matrix.ui.components.MatrixUserRow
|
||||
import io.element.android.libraries.matrix.ui.components.UnresolvedUserRow
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
|
||||
@Composable
|
||||
fun SearchSingleUserResultItem(
|
||||
matrixUser: MatrixUser,
|
||||
searchResult: UserSearchResult,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit = {},
|
||||
) {
|
||||
MatrixUserRow(
|
||||
modifier = modifier.clickable(onClick = onClick),
|
||||
matrixUser = matrixUser,
|
||||
avatarSize = AvatarSize.Custom(36.dp),
|
||||
)
|
||||
if (searchResult.isUnresolved) {
|
||||
UnresolvedUserRow(
|
||||
modifier = modifier.clickable(onClick = onClick),
|
||||
avatarData = searchResult.matrixUser.getAvatarData(AvatarSize.Custom(36.dp)),
|
||||
id = searchResult.matrixUser.userId.value,
|
||||
)
|
||||
} else {
|
||||
MatrixUserRow(
|
||||
modifier = modifier.clickable(onClick = onClick),
|
||||
matrixUser = searchResult.matrixUser,
|
||||
avatarSize = AvatarSize.Custom(36.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SearchSingleUserResultItemLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun SearchSingleUserResultItemDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
internal fun SearchSingleUserResultItemPreview() = ElementThemedPreview{ ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
SearchSingleUserResultItem(matrixUser = aMatrixUser())
|
||||
Column {
|
||||
SearchSingleUserResultItem(searchResult = UserSearchResult(aMatrixUser(), isUnresolved = false))
|
||||
SearchSingleUserResultItem(searchResult = UserSearchResult(aMatrixUser(), isUnresolved = true))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,12 +29,13 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul
|
|||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.SelectedUsersList
|
||||
import io.element.android.libraries.ui.strings.R
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun SearchUserBar(
|
||||
query: String,
|
||||
state: SearchBarResultState<ImmutableList<MatrixUser>>,
|
||||
state: SearchBarResultState<ImmutableList<UserSearchResult>>,
|
||||
selectedUsers: ImmutableList<MatrixUser>,
|
||||
active: Boolean,
|
||||
isMultiSelectionEnabled: Boolean,
|
||||
|
|
@ -68,26 +69,26 @@ fun SearchUserBar(
|
|||
resultHandler = { users ->
|
||||
LazyColumn {
|
||||
if (isMultiSelectionEnabled) {
|
||||
items(users) { matrixUser ->
|
||||
items(users) { searchResult ->
|
||||
SearchMultipleUsersResultItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
matrixUser = matrixUser,
|
||||
isUserSelected = selectedUsers.find { it.userId == matrixUser.userId } != null,
|
||||
searchResult = searchResult,
|
||||
isUserSelected = selectedUsers.find { it.userId == searchResult.matrixUser.userId } != null,
|
||||
onCheckedChange = { checked ->
|
||||
if (checked) {
|
||||
onUserSelected(matrixUser)
|
||||
onUserSelected(searchResult.matrixUser)
|
||||
} else {
|
||||
onUserDeselected(matrixUser)
|
||||
onUserDeselected(searchResult.matrixUser)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
items(users) { matrixUser ->
|
||||
items(users) { searchResult ->
|
||||
SearchSingleUserResultItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
matrixUser = matrixUser,
|
||||
onClick = { onUserSelected(matrixUser) }
|
||||
searchResult = searchResult,
|
||||
onClick = { onUserSelected(searchResult.matrixUser) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import dagger.assisted.AssistedFactory
|
|||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.usersearch.api.UserRepository
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ class DefaultUserListPresenter @AssistedInject constructor(
|
|||
var isSearchActive by rememberSaveable { mutableStateOf(false) }
|
||||
val selectedUsers by userListDataStore.selectedUsers().collectAsState(emptyList())
|
||||
var searchQuery by rememberSaveable { mutableStateOf("") }
|
||||
var searchResults: SearchBarResultState<ImmutableList<MatrixUser>> by remember {
|
||||
var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember {
|
||||
mutableStateOf(SearchBarResultState.NotSearching())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,12 @@ package io.element.android.features.createroom.impl.userlist
|
|||
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class UserListState(
|
||||
val searchQuery: String,
|
||||
val searchResults: SearchBarResultState<ImmutableList<MatrixUser>>,
|
||||
val searchResults: SearchBarResultState<ImmutableList<UserSearchResult>>,
|
||||
val selectedUsers: ImmutableList<MatrixUser>,
|
||||
val isSearchActive: Boolean,
|
||||
val selectionMode: SelectionMode,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package io.element.android.features.createroom.impl.userlist
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
|
|
@ -38,14 +39,14 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
|
|||
isSearchActive = true,
|
||||
searchQuery = "@someone:matrix.org",
|
||||
selectedUsers = aListOfSelectedUsers(),
|
||||
searchResults = SearchBarResultState.Results(aMatrixUserList().toImmutableList()),
|
||||
searchResults = SearchBarResultState.Results(aMatrixUserList().map { UserSearchResult(it) }.toImmutableList()),
|
||||
),
|
||||
aUserListState().copy(
|
||||
isSearchActive = true,
|
||||
searchQuery = "@someone:matrix.org",
|
||||
selectionMode = SelectionMode.Multiple,
|
||||
selectedUsers = aListOfSelectedUsers(),
|
||||
searchResults = SearchBarResultState.Results(aMatrixUserList().toImmutableList()),
|
||||
searchResults = SearchBarResultState.Results(aMatrixUserList().map { UserSearchResult(it) }.toImmutableList()),
|
||||
),
|
||||
aUserListState().copy(
|
||||
isSearchActive = true,
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
<string name="screen_create_room_add_people_title">"Añadir personas"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Se ha producido un error al intentar iniciar un chat"</string>
|
||||
<string name="screen_create_room_title">"Crear una sala"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
<string name="screen_create_room_add_people_title">"Aggiungi persone"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"Si è verificato un errore durante il tentativo di avviare una chat"</string>
|
||||
<string name="screen_create_room_title">"Crea una stanza"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -14,4 +14,4 @@
|
|||
<string name="screen_create_room_topic_placeholder">"Despre ce este această cameră?"</string>
|
||||
<string name="screen_start_chat_error_starting_chat">"A apărut o eroare la încercarea începerii conversației"</string>
|
||||
<string name="screen_create_room_title">"Creați o cameră"</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
|
@ -130,18 +131,18 @@ class DefaultUserListPresenterTests {
|
|||
skipItems(2)
|
||||
|
||||
// When the user repository emits a result, it's copied to the state
|
||||
userRepository.emitResult(listOf(aMatrixUser()))
|
||||
userRepository.emitResult(listOf(UserSearchResult(aMatrixUser())))
|
||||
assertThat(awaitItem().searchResults).isEqualTo(
|
||||
SearchBarResultState.Results(
|
||||
persistentListOf(aMatrixUser())
|
||||
persistentListOf(UserSearchResult(aMatrixUser()))
|
||||
)
|
||||
)
|
||||
|
||||
// When the user repository emits another result, it replaces the previous value
|
||||
userRepository.emitResult(aMatrixUserList())
|
||||
userRepository.emitResult(aMatrixUserList().map { UserSearchResult(it) })
|
||||
assertThat(awaitItem().searchResults).isEqualTo(
|
||||
SearchBarResultState.Results(
|
||||
aMatrixUserList()
|
||||
aMatrixUserList().map { UserSearchResult(it) }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomView
|
||||
import io.element.android.features.roomdetails.impl.blockuser.BlockUserDialogs
|
||||
import io.element.android.features.roomdetails.impl.blockuser.BlockUserSection
|
||||
import io.element.android.features.leaveroom.api.LeaveRoomView
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberHeaderSection
|
||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberMainActionsSection
|
||||
import io.element.android.libraries.architecture.isLoading
|
||||
|
|
@ -67,6 +67,7 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold
|
|||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
|
|
@ -185,7 +186,7 @@ internal fun RoomHeaderSection(
|
|||
|
||||
@Composable
|
||||
internal fun TopicSection(roomTopic: String, modifier: Modifier = Modifier) {
|
||||
PreferenceCategory(title = stringResource(R.string.screen_room_details_topic_title), modifier = modifier) {
|
||||
PreferenceCategory(title = stringResource(StringR.string.common_topic), modifier = modifier) {
|
||||
Text(
|
||||
roomTopic,
|
||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp),
|
||||
|
|
|
|||
|
|
@ -126,15 +126,16 @@ class RoomInviteMembersPresenter @Inject constructor(
|
|||
userRepository.search(searchQuery).collect {
|
||||
searchResults.value = when {
|
||||
it.isEmpty() -> SearchBarResultState.NoResults()
|
||||
else -> SearchBarResultState.Results(it.map { user ->
|
||||
val existingMembership = joinedMembers.firstOrNull { j -> j.userId == user.userId }?.membership
|
||||
else -> SearchBarResultState.Results(it.map { result ->
|
||||
val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership
|
||||
val isJoined = existingMembership == RoomMembershipState.JOIN
|
||||
val isInvited = existingMembership == RoomMembershipState.INVITE
|
||||
InvitableUser(
|
||||
matrixUser = user,
|
||||
isSelected = selectedUsers.value.contains(user) || isJoined || isInvited,
|
||||
matrixUser = result.matrixUser,
|
||||
isSelected = selectedUsers.value.contains(result.matrixUser) || isJoined || isInvited,
|
||||
isAlreadyJoined = isJoined,
|
||||
isAlreadyInvited = isInvited,
|
||||
isUnresolved = result.isUnresolved,
|
||||
)
|
||||
}.toImmutableList())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,4 +35,5 @@ data class InvitableUser(
|
|||
val isSelected: Boolean = false,
|
||||
val isAlreadyJoined: Boolean = false,
|
||||
val isAlreadyInvited: Boolean = false,
|
||||
val isUnresolved: Boolean = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -48,5 +48,19 @@ internal class RoomInviteMembersStateProvider : PreviewParameterProvider<RoomInv
|
|||
)
|
||||
)
|
||||
),
|
||||
RoomInviteMembersState(
|
||||
isSearchActive = true,
|
||||
canInvite = true,
|
||||
searchQuery = "@alice:server.org",
|
||||
selectedUsers = persistentListOf(
|
||||
aMatrixUser("@carol:server.org", "Carol")
|
||||
),
|
||||
searchResults = SearchBarResultState.Results(
|
||||
persistentListOf(
|
||||
InvitableUser(aMatrixUser("@alice:server.org"), isUnresolved = true),
|
||||
InvitableUser(aMatrixUser("@bob:server.org", "Bob")),
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul
|
|||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.CheckableUnresolvedUserRow
|
||||
import io.element.android.libraries.matrix.ui.components.CheckableUserRow
|
||||
import io.element.android.libraries.matrix.ui.components.SelectedUsersList
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
|
|
@ -180,22 +181,32 @@ private fun RoomInviteMembersSearchBar(
|
|||
|
||||
LazyColumn {
|
||||
items(results) { invitableUser ->
|
||||
CheckableUserRow(
|
||||
checked = invitableUser.isSelected,
|
||||
enabled = !invitableUser.isAlreadyInvited && !invitableUser.isAlreadyJoined,
|
||||
avatarData = invitableUser.matrixUser.getAvatarData(AvatarSize.MEDIUM),
|
||||
name = invitableUser.matrixUser.getBestName(),
|
||||
subtext = when {
|
||||
// If they're already invited or joined we show that information
|
||||
invitableUser.isAlreadyJoined -> stringResource(R.string.screen_room_details_already_a_member)
|
||||
invitableUser.isAlreadyInvited -> stringResource(R.string.screen_room_details_already_invited)
|
||||
// Otherwise show the ID, unless that's already used for their name
|
||||
invitableUser.matrixUser.displayName.isNullOrEmpty().not() -> invitableUser.matrixUser.userId.value
|
||||
else -> null
|
||||
},
|
||||
onCheckedChange = { onUserToggled(invitableUser.matrixUser) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
if (invitableUser.isUnresolved && !invitableUser.isAlreadyInvited && !invitableUser.isAlreadyJoined) {
|
||||
CheckableUnresolvedUserRow(
|
||||
checked = invitableUser.isSelected,
|
||||
avatarData = invitableUser.matrixUser.getAvatarData(AvatarSize.MEDIUM),
|
||||
id = invitableUser.matrixUser.userId.value,
|
||||
onCheckedChange = { onUserToggled(invitableUser.matrixUser) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
} else {
|
||||
CheckableUserRow(
|
||||
checked = invitableUser.isSelected,
|
||||
enabled = !invitableUser.isAlreadyInvited && !invitableUser.isAlreadyJoined,
|
||||
avatarData = invitableUser.matrixUser.getAvatarData(AvatarSize.MEDIUM),
|
||||
name = invitableUser.matrixUser.getBestName(),
|
||||
subtext = when {
|
||||
// If they're already invited or joined we show that information
|
||||
invitableUser.isAlreadyJoined -> stringResource(R.string.screen_room_details_already_a_member)
|
||||
invitableUser.isAlreadyInvited -> stringResource(R.string.screen_room_details_already_invited)
|
||||
// Otherwise show the ID, unless that's already used for their name
|
||||
invitableUser.matrixUser.displayName.isNullOrEmpty().not() -> invitableUser.matrixUser.userId.value
|
||||
else -> null
|
||||
},
|
||||
onCheckedChange = { onUserToggled(invitableUser.matrixUser) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul
|
|||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
|
||||
import io.element.android.libraries.usersearch.api.UserSearchResult
|
||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -130,7 +132,7 @@ internal class RoomInviteMembersPresenterTest {
|
|||
skipItems(1)
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitResult(aMatrixUserList())
|
||||
repository.emitResult(aMatrixUserList().map { UserSearchResult(it) })
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItem()
|
||||
|
|
@ -175,7 +177,7 @@ internal class RoomInviteMembersPresenterTest {
|
|||
skipItems(1)
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitResult(aMatrixUserList())
|
||||
repository.emitResult(aMatrixUserList().map { UserSearchResult(it) })
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItem()
|
||||
|
|
@ -202,6 +204,53 @@ internal class RoomInviteMembersPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - performs search and handles unresolved results`() = runTest {
|
||||
val userList = aMatrixUserList()
|
||||
val joinedUser = userList[0]
|
||||
val invitedUser = userList[1]
|
||||
|
||||
val repository = FakeUserRepository()
|
||||
val presenter = RoomInviteMembersPresenter(
|
||||
userRepository = repository,
|
||||
roomMemberListDataSource = createDataSource(FakeMatrixRoom().apply {
|
||||
givenRoomMembersState(MatrixRoomMembersState.Ready(listOf(
|
||||
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
|
||||
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
|
||||
)))
|
||||
}),
|
||||
coroutineDispatchers = testCoroutineDispatchers()
|
||||
)
|
||||
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(RoomInviteMembersEvents.UpdateSearchQuery("some query"))
|
||||
skipItems(1)
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
|
||||
val unresolvedUser = UserSearchResult(aMatrixUser(id = A_USER_ID.value), isUnresolved = true)
|
||||
repository.emitResult(listOf(unresolvedUser) + aMatrixUserList().map { UserSearchResult(it) })
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItem()
|
||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||
|
||||
val users = resultState.searchResults.users()
|
||||
|
||||
val userWhoShouldBeUnresolved = users.first()
|
||||
assertThat(userWhoShouldBeUnresolved.isUnresolved).isTrue()
|
||||
|
||||
// All other users are neither joined nor invited
|
||||
val otherUsers = users.minus(userWhoShouldBeUnresolved)
|
||||
assertThat(otherUsers.none { it.isUnresolved }).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - toggle users updates selected user state`() = runTest {
|
||||
val repository = FakeUserRepository()
|
||||
|
|
@ -254,7 +303,7 @@ internal class RoomInviteMembersPresenterTest {
|
|||
skipItems(1)
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitResult(aMatrixUserList() + selectedUser)
|
||||
repository.emitResult((aMatrixUserList() + selectedUser).map { UserSearchResult(it) })
|
||||
skipItems(2)
|
||||
|
||||
val resultState = awaitItem()
|
||||
|
|
@ -296,7 +345,7 @@ internal class RoomInviteMembersPresenterTest {
|
|||
skipItems(1)
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitResult(aMatrixUserList() + selectedUser)
|
||||
repository.emitResult((aMatrixUserList() + selectedUser).map { UserSearchResult(it) })
|
||||
skipItems(2)
|
||||
|
||||
// And then a user is toggled
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue