Iterate on removing space child rooms.
This commit is contained in:
parent
7b8e11c8cb
commit
bed35807d2
3 changed files with 54 additions and 10 deletions
|
|
@ -112,6 +112,23 @@ class SpacePresenter(
|
||||||
var isManageMode by remember { mutableStateOf(false) }
|
var isManageMode by remember { mutableStateOf(false) }
|
||||||
var selectedRoomIds by remember { mutableStateOf<Set<RoomId>>(emptySet()) }
|
var selectedRoomIds by remember { mutableStateOf<Set<RoomId>>(emptySet()) }
|
||||||
var removeRoomsAction by remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
var removeRoomsAction by remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||||
|
var removedRoomIds by remember { mutableStateOf<Set<RoomId>>(emptySet()) }
|
||||||
|
|
||||||
|
val filteredChildren by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
children
|
||||||
|
.filterNot { it.roomId in removedRoomIds }
|
||||||
|
.let { list ->
|
||||||
|
if (isManageMode) {
|
||||||
|
// In manage mode, only show rooms (not spaces)
|
||||||
|
list.filter { !it.isSpace }
|
||||||
|
} else {
|
||||||
|
list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toImmutableList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(children) {
|
LaunchedEffect(children) {
|
||||||
// Remove joined children from the join actions
|
// Remove joined children from the join actions
|
||||||
|
|
@ -171,10 +188,19 @@ class SpacePresenter(
|
||||||
localCoroutineScope.launch {
|
localCoroutineScope.launch {
|
||||||
removeRoomsAction = AsyncAction.Loading
|
removeRoomsAction = AsyncAction.Loading
|
||||||
val spaceId = spaceRoomList.roomId
|
val spaceId = spaceRoomList.roomId
|
||||||
val results = selectedRoomIds.map { roomId ->
|
val roomsToRemove = selectedRoomIds.toSet()
|
||||||
async { spaceService.removeChildFromSpace(spaceId, roomId) }
|
val successfullyRemoved = mutableSetOf<RoomId>()
|
||||||
|
val results = roomsToRemove.map { roomId ->
|
||||||
|
async {
|
||||||
|
spaceService.removeChildFromSpace(spaceId, roomId)
|
||||||
|
.onSuccess { successfullyRemoved.add(roomId) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val hasError = results.awaitAll().any { it.isFailure }
|
results.awaitAll()
|
||||||
|
if (successfullyRemoved.isNotEmpty()) {
|
||||||
|
removedRoomIds = removedRoomIds + successfullyRemoved
|
||||||
|
}
|
||||||
|
val hasError = successfullyRemoved.size < roomsToRemove.size
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
removeRoomsAction = AsyncAction.Failure(Exception("Failed to remove some rooms"))
|
removeRoomsAction = AsyncAction.Failure(Exception("Failed to remove some rooms"))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -191,7 +217,7 @@ class SpacePresenter(
|
||||||
}
|
}
|
||||||
return SpaceState(
|
return SpaceState(
|
||||||
currentSpace = currentSpace.getOrNull(),
|
currentSpace = currentSpace.getOrNull(),
|
||||||
children = children,
|
children = filteredChildren,
|
||||||
seenSpaceInvites = seenSpaceInvites,
|
seenSpaceInvites = seenSpaceInvites,
|
||||||
hideInvitesAvatar = hideInvitesAvatar,
|
hideInvitesAvatar = hideInvitesAvatar,
|
||||||
hasMoreToLoad = hasMoreToLoad,
|
hasMoreToLoad = hasMoreToLoad,
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,12 @@ data class SpaceState(
|
||||||
val eventSink: (SpaceEvents) -> Unit
|
val eventSink: (SpaceEvents) -> Unit
|
||||||
) {
|
) {
|
||||||
fun isJoining(spaceId: RoomId): Boolean = joinActions[spaceId] == AsyncAction.Loading
|
fun isJoining(spaceId: RoomId): Boolean = joinActions[spaceId] == AsyncAction.Loading
|
||||||
|
fun isSelected(spaceId: RoomId): Boolean = selectedRoomIds.contains(spaceId)
|
||||||
val hasAnyFailure: Boolean = joinActions.values.any {
|
val hasAnyFailure: Boolean = joinActions.values.any {
|
||||||
it is AsyncAction.Failure
|
it is AsyncAction.Failure
|
||||||
}
|
}
|
||||||
|
|
||||||
val showManageRoomsAction: Boolean = canManageRooms && children.isNotEmpty()
|
val showManageRoomsAction: Boolean = canManageRooms && children.any { spaceRoom -> !spaceRoom.isSpace }
|
||||||
val selectedCount: Int = selectedRoomIds.size
|
val selectedCount: Int = selectedRoomIds.size
|
||||||
val isRemoveButtonEnabled: Boolean = selectedRoomIds.isNotEmpty()
|
val isRemoveButtonEnabled: Boolean = selectedRoomIds.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package io.element.android.features.space.impl.root
|
package io.element.android.features.space.impl.root
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
|
@ -42,10 +43,9 @@ import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.designsystem.atomic.molecules.InviteButtonsRowMolecule
|
import io.element.android.libraries.designsystem.atomic.molecules.InviteButtonsRowMolecule
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
|
||||||
import io.element.android.libraries.designsystem.components.ClickableLinkText
|
import io.element.android.libraries.designsystem.components.ClickableLinkText
|
||||||
import io.element.android.libraries.designsystem.components.SimpleModalBottomSheet
|
import io.element.android.libraries.designsystem.components.SimpleModalBottomSheet
|
||||||
|
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncIndicator
|
import io.element.android.libraries.designsystem.components.async.AsyncIndicator
|
||||||
import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost
|
import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost
|
||||||
import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState
|
import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState
|
||||||
|
|
@ -54,18 +54,19 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarType
|
import io.element.android.libraries.designsystem.components.avatar.AvatarType
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
|
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||||
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 io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||||
import io.element.android.libraries.designsystem.theme.components.DropdownMenu
|
import io.element.android.libraries.designsystem.theme.components.DropdownMenu
|
||||||
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
|
import io.element.android.libraries.designsystem.theme.components.DropdownMenuItem
|
||||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
|
||||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||||
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.IconButton
|
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
|
||||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
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.Text
|
||||||
|
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
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.spaces.SpaceRoom
|
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
||||||
|
|
@ -90,6 +91,15 @@ fun SpaceView(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
acceptDeclineInviteView: @Composable () -> Unit,
|
acceptDeclineInviteView: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
BackHandler {
|
||||||
|
if (state.isManageMode) {
|
||||||
|
state.eventSink(SpaceEvents.ExitManageMode)
|
||||||
|
} else {
|
||||||
|
onBackClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
topBar = {
|
topBar = {
|
||||||
|
|
@ -230,7 +240,7 @@ private fun SpaceViewContent(
|
||||||
) { index, spaceRoom ->
|
) { index, spaceRoom ->
|
||||||
val isInvitation = spaceRoom.state == CurrentUserMembership.INVITED
|
val isInvitation = spaceRoom.state == CurrentUserMembership.INVITED
|
||||||
val isCurrentlyJoining = state.isJoining(spaceRoom.roomId)
|
val isCurrentlyJoining = state.isJoining(spaceRoom.roomId)
|
||||||
val isSelected = spaceRoom.roomId in state.selectedRoomIds
|
val isSelected = state.isSelected(spaceRoom.roomId)
|
||||||
SpaceRoomItemView(
|
SpaceRoomItemView(
|
||||||
spaceRoom = spaceRoom,
|
spaceRoom = spaceRoom,
|
||||||
showUnreadIndicator = isInvitation && spaceRoom.roomId !in state.seenSpaceInvites,
|
showUnreadIndicator = isInvitation && spaceRoom.roomId !in state.seenSpaceInvites,
|
||||||
|
|
@ -530,6 +540,13 @@ private fun RemoveRoomsConfirmationDialog(
|
||||||
onSubmitClick = onConfirm,
|
onSubmitClick = onConfirm,
|
||||||
onDismiss = onDismiss,
|
onDismiss = onDismiss,
|
||||||
destructiveSubmit = true,
|
destructiveSubmit = true,
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = CompoundIcons.Error(),
|
||||||
|
tint = ElementTheme.colors.textCriticalPrimary,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue