refactor (start chat) : use invite people module in room details screen
This commit is contained in:
parent
98343e0531
commit
c41994ad13
20 changed files with 207 additions and 543 deletions
|
|
@ -27,23 +27,30 @@ import io.element.android.libraries.architecture.runCatchingUpdatingState
|
|||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.di.annotations.AppCoroutineScope
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
import io.element.android.libraries.matrix.api.room.filterMembers
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.libraries.usersearch.api.UserRepository
|
||||
import io.element.android.services.apperror.api.AppErrorStateService
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class DefaultInvitePeoplePresenter @AssistedInject constructor(
|
||||
@Assisted private val room: JoinedRoom,
|
||||
private val userRepository: UserRepository,
|
||||
private val coroutineDispatchers: CoroutineDispatchers,
|
||||
@AppCoroutineScope private val coroutineScope: CoroutineScope,
|
||||
private val appErrorStateService: AppErrorStateService,
|
||||
) : InvitePeoplePresenter {
|
||||
|
||||
@AssistedFactory
|
||||
|
|
@ -97,12 +104,30 @@ class DefaultInvitePeoplePresenter @AssistedInject constructor(
|
|||
searchResults.toggleUser(it.user)
|
||||
}
|
||||
is InvitePeopleEvents.SendInvites -> {
|
||||
coroutineScope.sendInvites(selectedUsers.value)
|
||||
}
|
||||
is InvitePeopleEvents.CloseSearch -> {
|
||||
searchActive = false
|
||||
searchQuery = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.sendInvites(selectedUsers: List<MatrixUser>) = launch {
|
||||
val anyInviteFailed = selectedUsers
|
||||
.map { room.inviteUserById(it.userId) }
|
||||
.any { it.isFailure }
|
||||
|
||||
if (anyInviteFailed) {
|
||||
appErrorStateService.showError(
|
||||
titleRes = CommonStrings.common_unable_to_invite_title,
|
||||
bodyRes = CommonStrings.common_unable_to_invite_message,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("toggleUserInSelectedUsers")
|
||||
private fun MutableState<ImmutableList<MatrixUser>>.toggleUser(user: MatrixUser) {
|
||||
value = if (value.contains(user)) {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ class DefaultInvitePeopleRenderer @Inject constructor() : InvitePeopleRenderer {
|
|||
if (state is DefaultInvitePeopleState) {
|
||||
InvitePeopleView(
|
||||
state = state,
|
||||
onBackClick = {},
|
||||
onSubmitClick = {},
|
||||
modifier = modifier
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
|
|||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class DefaultInvitePeopleState(
|
||||
val canInvite: Boolean,
|
||||
override val canInvite: Boolean,
|
||||
val searchQuery: String,
|
||||
val showSearchLoader: Boolean,
|
||||
val searchResults: SearchBarResultState<ImmutableList<InvitableUser>>,
|
||||
val selectedUsers: ImmutableList<MatrixUser>,
|
||||
val isSearchActive: Boolean,
|
||||
override val isSearchActive: Boolean,
|
||||
override val eventSink: (InvitePeopleEvents) -> Unit
|
||||
): InvitePeopleState
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
package io.element.android.features.invitepeople.impl
|
||||
|
||||
import androidx.activity.OnBackPressedDispatcher
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
|
|
@ -21,6 +21,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bumble.appyx.core.plugin.BackPressHandler
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncLoading
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
|
|
@ -28,7 +29,6 @@ import io.element.android.libraries.designsystem.components.button.BackButton
|
|||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBar
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
|
@ -46,87 +46,46 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
@Composable
|
||||
fun InvitePeopleView(
|
||||
state: DefaultInvitePeopleState,
|
||||
onBackClick: () -> Unit,
|
||||
onSubmitClick: (List<MatrixUser>) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
RoomInviteMembersTopBar(
|
||||
onBackClick = {
|
||||
if (state.isSearchActive) {
|
||||
state.eventSink(DefaultInvitePeopleEvents.OnSearchActiveChanged(false))
|
||||
} else {
|
||||
onBackClick()
|
||||
}
|
||||
},
|
||||
onSubmitClick = { onSubmitClick(state.selectedUsers) },
|
||||
canSend = state.canInvite,
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
RoomInviteMembersSearchBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
query = state.searchQuery,
|
||||
showLoader = state.showSearchLoader,
|
||||
selectedUsers = state.selectedUsers,
|
||||
state = state.searchResults,
|
||||
active = state.isSearchActive,
|
||||
onActiveChange = {
|
||||
state.eventSink(
|
||||
DefaultInvitePeopleEvents.OnSearchActiveChanged(
|
||||
it
|
||||
)
|
||||
)
|
||||
},
|
||||
onTextChange = { state.eventSink(DefaultInvitePeopleEvents.UpdateSearchQuery(it)) },
|
||||
onToggleUser = { state.eventSink(DefaultInvitePeopleEvents.ToggleUser(it)) },
|
||||
)
|
||||
|
||||
if (!state.isSearchActive) {
|
||||
SelectedUsersRowList(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
selectedUsers = state.selectedUsers,
|
||||
autoScroll = true,
|
||||
onUserRemove = { state.eventSink(DefaultInvitePeopleEvents.ToggleUser(it)) },
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
Column(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
InvitePeopleSearchBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
query = state.searchQuery,
|
||||
showLoader = state.showSearchLoader,
|
||||
selectedUsers = state.selectedUsers,
|
||||
state = state.searchResults,
|
||||
active = state.isSearchActive,
|
||||
onActiveChange = {
|
||||
state.eventSink(
|
||||
DefaultInvitePeopleEvents.OnSearchActiveChanged(
|
||||
it
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
onTextChange = { state.eventSink(DefaultInvitePeopleEvents.UpdateSearchQuery(it)) },
|
||||
onToggleUser = { state.eventSink(DefaultInvitePeopleEvents.ToggleUser(it)) },
|
||||
)
|
||||
|
||||
if (!state.isSearchActive) {
|
||||
SelectedUsersRowList(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
selectedUsers = state.selectedUsers,
|
||||
autoScroll = true,
|
||||
onUserRemove = { state.eventSink(DefaultInvitePeopleEvents.ToggleUser(it)) },
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun RoomInviteMembersTopBar(
|
||||
canSend: Boolean,
|
||||
onBackClick: () -> Unit,
|
||||
onSubmitClick: () -> Unit,
|
||||
) {
|
||||
TopAppBar(
|
||||
titleStr = "Invite people",
|
||||
navigationIcon = { BackButton(onClick = onBackClick) },
|
||||
actions = {
|
||||
TextButton(
|
||||
text = stringResource(CommonStrings.action_invite),
|
||||
onClick = onSubmitClick,
|
||||
enabled = canSend,
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun RoomInviteMembersSearchBar(
|
||||
private fun InvitePeopleSearchBar(
|
||||
query: String,
|
||||
state: SearchBarResultState<ImmutableList<InvitableUser>>,
|
||||
showLoader: Boolean,
|
||||
|
|
@ -219,9 +178,5 @@ private fun RoomInviteMembersSearchBar(
|
|||
@Composable
|
||||
internal fun RoomInviteMembersViewPreview(@PreviewParameter(DefaultInvitePeopleStateProvider::class) state: DefaultInvitePeopleState) =
|
||||
ElementPreview {
|
||||
InvitePeopleView(
|
||||
state = state,
|
||||
onBackClick = {},
|
||||
onSubmitClick = {},
|
||||
)
|
||||
InvitePeopleView(state = state)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue