Iterate on removing space child rooms.
This commit is contained in:
parent
df3fe6d6d6
commit
f50165807d
3 changed files with 54 additions and 10 deletions
|
|
@ -112,6 +112,23 @@ class SpacePresenter(
|
|||
var isManageMode by remember { mutableStateOf(false) }
|
||||
var selectedRoomIds by remember { mutableStateOf<Set<RoomId>>(emptySet()) }
|
||||
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) {
|
||||
// Remove joined children from the join actions
|
||||
|
|
@ -171,10 +188,19 @@ class SpacePresenter(
|
|||
localCoroutineScope.launch {
|
||||
removeRoomsAction = AsyncAction.Loading
|
||||
val spaceId = spaceRoomList.roomId
|
||||
val results = selectedRoomIds.map { roomId ->
|
||||
async { spaceService.removeChildFromSpace(spaceId, roomId) }
|
||||
val roomsToRemove = selectedRoomIds.toSet()
|
||||
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) {
|
||||
removeRoomsAction = AsyncAction.Failure(Exception("Failed to remove some rooms"))
|
||||
} else {
|
||||
|
|
@ -191,7 +217,7 @@ class SpacePresenter(
|
|||
}
|
||||
return SpaceState(
|
||||
currentSpace = currentSpace.getOrNull(),
|
||||
children = children,
|
||||
children = filteredChildren,
|
||||
seenSpaceInvites = seenSpaceInvites,
|
||||
hideInvitesAvatar = hideInvitesAvatar,
|
||||
hasMoreToLoad = hasMoreToLoad,
|
||||
|
|
|
|||
|
|
@ -34,11 +34,12 @@ data class SpaceState(
|
|||
val eventSink: (SpaceEvents) -> Unit
|
||||
) {
|
||||
fun isJoining(spaceId: RoomId): Boolean = joinActions[spaceId] == AsyncAction.Loading
|
||||
fun isSelected(spaceId: RoomId): Boolean = selectedRoomIds.contains(spaceId)
|
||||
val hasAnyFailure: Boolean = joinActions.values.any {
|
||||
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 isRemoveButtonEnabled: Boolean = selectedRoomIds.isNotEmpty()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package io.element.android.features.space.impl.root
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.clickable
|
||||
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.libraries.architecture.AsyncAction
|
||||
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.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.AsyncIndicatorHost
|
||||
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.AvatarType
|
||||
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.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.DropdownMenu
|
||||
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.Icon
|
||||
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.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
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.spaces.SpaceRoom
|
||||
|
|
@ -90,6 +91,15 @@ fun SpaceView(
|
|||
modifier: Modifier = Modifier,
|
||||
acceptDeclineInviteView: @Composable () -> Unit,
|
||||
) {
|
||||
|
||||
BackHandler {
|
||||
if (state.isManageMode) {
|
||||
state.eventSink(SpaceEvents.ExitManageMode)
|
||||
} else {
|
||||
onBackClick()
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = {
|
||||
|
|
@ -230,7 +240,7 @@ private fun SpaceViewContent(
|
|||
) { index, spaceRoom ->
|
||||
val isInvitation = spaceRoom.state == CurrentUserMembership.INVITED
|
||||
val isCurrentlyJoining = state.isJoining(spaceRoom.roomId)
|
||||
val isSelected = spaceRoom.roomId in state.selectedRoomIds
|
||||
val isSelected = state.isSelected(spaceRoom.roomId)
|
||||
SpaceRoomItemView(
|
||||
spaceRoom = spaceRoom,
|
||||
showUnreadIndicator = isInvitation && spaceRoom.roomId !in state.seenSpaceInvites,
|
||||
|
|
@ -530,6 +540,13 @@ private fun RemoveRoomsConfirmationDialog(
|
|||
onSubmitClick = onConfirm,
|
||||
onDismiss = onDismiss,
|
||||
destructiveSubmit = true,
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Error(),
|
||||
tint = ElementTheme.colors.textCriticalPrimary,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue