88package io.element.android.features.space.impl.leave
99
1010import androidx.compose.runtime.Composable
11+ import androidx.compose.runtime.LaunchedEffect
1112import androidx.compose.runtime.MutableState
1213import androidx.compose.runtime.getValue
14+ import androidx.compose.runtime.mutableIntStateOf
1315import androidx.compose.runtime.mutableStateOf
14- import androidx.compose.runtime.produceState
1516import androidx.compose.runtime.remember
1617import androidx.compose.runtime.rememberCoroutineScope
1718import androidx.compose.runtime.setValue
@@ -26,10 +27,9 @@ import io.element.android.libraries.architecture.runUpdatingState
2627import io.element.android.libraries.matrix.api.core.RoomId
2728import io.element.android.libraries.matrix.api.spaces.LeaveSpaceHandle
2829import io.element.android.libraries.matrix.api.spaces.LeaveSpaceRoom
29- import kotlinx.collections.immutable.ImmutableSet
30+ import kotlinx.collections.immutable.ImmutableList
3031import kotlinx.collections.immutable.persistentSetOf
3132import kotlinx.collections.immutable.toImmutableList
32- import kotlinx.collections.immutable.toPersistentSet
3333import kotlinx.coroutines.CoroutineScope
3434import kotlinx.coroutines.launch
3535
@@ -42,72 +42,85 @@ class LeaveSpacePresenter(
4242 fun create (leaveSpaceHandle : LeaveSpaceHandle ): LeaveSpacePresenter
4343 }
4444
45+ data class LeaveSpaceRooms (
46+ val current : LeaveSpaceRoom ? ,
47+ val others : List <LeaveSpaceRoom >,
48+ )
49+
4550 @Composable
4651 override fun present (): LeaveSpaceState {
4752 val coroutineScope = rememberCoroutineScope()
48- var currentSpace : LeaveSpaceRoom ? by remember { mutableStateOf( null ) }
53+ var retryCount by remember { mutableIntStateOf( 0 ) }
4954 val leaveSpaceAction = remember {
5055 mutableStateOf<AsyncAction <Unit >>(AsyncAction .Uninitialized )
5156 }
52- val selectedRoomIds = remember {
53- mutableStateOf<ImmutableSet <RoomId >>(persistentSetOf())
57+ var selectedRoomIds by remember {
58+ mutableStateOf<Collection <RoomId >>(setOf ())
59+ }
60+ var leaveSpaceRooms by remember {
61+ mutableStateOf<AsyncData <LeaveSpaceRooms >>(AsyncData .Loading ())
5462 }
55- val leaveSpaceRooms by produceState( AsyncData . Loading () ) {
63+ LaunchedEffect (retryCount ) {
5664 val rooms = leaveSpaceHandle.rooms()
5765 val (currentRoom, otherRooms) = rooms.getOrNull()
5866 .orEmpty()
5967 .partition { it.spaceRoom.roomId == leaveSpaceHandle.id }
60- currentSpace = currentRoom.firstOrNull()
6168 // By default select all rooms that can be left
62- selectedRoomIds.value = otherRooms
69+ selectedRoomIds = otherRooms
6370 .filter { it.isLastAdmin.not () }
6471 .map { it.spaceRoom.roomId }
65- .toPersistentSet()
66- value = rooms.fold(
67- onSuccess = { AsyncData .Success (otherRooms) },
72+ leaveSpaceRooms = rooms.fold(
73+ onSuccess = {
74+ AsyncData .Success (
75+ LeaveSpaceRooms (
76+ current = currentRoom.firstOrNull(),
77+ others = otherRooms.toImmutableList(),
78+ )
79+ )
80+ },
6881 onFailure = { AsyncData .Failure (it) }
6982 )
7083 }
71- val selectableSpaceRooms by produceState(
72- initialValue = AsyncData .Loading (),
73- key1 = leaveSpaceRooms,
74- key2 = selectedRoomIds.value,
75- ) {
76- value = leaveSpaceRooms.map { list ->
77- list.orEmpty().map { room ->
84+ var selectableSpaceRooms by remember {
85+ mutableStateOf<AsyncData <ImmutableList <SelectableSpaceRoom >>>(AsyncData .Loading ())
86+ }
87+ LaunchedEffect (selectedRoomIds, leaveSpaceRooms) {
88+ selectableSpaceRooms = leaveSpaceRooms.map {
89+ it?.others.orEmpty().map { room ->
7890 SelectableSpaceRoom (
7991 spaceRoom = room.spaceRoom,
8092 isLastAdmin = room.isLastAdmin,
81- isSelected = selectedRoomIds.value. contains(room.spaceRoom.roomId),
93+ isSelected = selectedRoomIds.contains(room.spaceRoom.roomId),
8294 )
8395 }.toImmutableList()
8496 }
8597 }
8698
8799 fun handleEvents (event : LeaveSpaceEvents ) {
88100 when (event) {
101+ LeaveSpaceEvents .Retry -> {
102+ leaveSpaceRooms = AsyncData .Loading ()
103+ retryCount + = 1
104+ }
89105 LeaveSpaceEvents .DeselectAllRooms -> {
90- selectedRoomIds.value = persistentSetOf()
106+ selectedRoomIds = persistentSetOf()
91107 }
92108 LeaveSpaceEvents .SelectAllRooms -> {
93- selectedRoomIds.value = selectableSpaceRooms.dataOrNull()
109+ selectedRoomIds = selectableSpaceRooms.dataOrNull()
94110 .orEmpty()
95111 .filter { it.isLastAdmin.not () }
96112 .map { it.spaceRoom.roomId }
97- .toPersistentSet()
98113 }
99114 is LeaveSpaceEvents .ToggleRoomSelection -> {
100- val currentSet = selectedRoomIds.value
101- selectedRoomIds.value = if (currentSet.contains(event.roomId)) {
102- currentSet - event.roomId
115+ selectedRoomIds = if (selectedRoomIds.contains(event.roomId)) {
116+ selectedRoomIds - event.roomId
103117 } else {
104- currentSet + event.roomId
118+ selectedRoomIds + event.roomId
105119 }
106- .toPersistentSet()
107120 }
108121 LeaveSpaceEvents .LeaveSpace -> coroutineScope.leaveSpace(
109122 leaveSpaceAction = leaveSpaceAction,
110- selectedRoomIds = selectedRoomIds.value ,
123+ selectedRoomIds = selectedRoomIds,
111124 )
112125 LeaveSpaceEvents .CloseError -> {
113126 leaveSpaceAction.value = AsyncAction .Uninitialized
@@ -116,8 +129,8 @@ class LeaveSpacePresenter(
116129 }
117130
118131 return LeaveSpaceState (
119- spaceName = currentSpace ?.spaceRoom?.name,
120- isLastAdmin = currentSpace ?.isLastAdmin == true ,
132+ spaceName = leaveSpaceRooms.dataOrNull()?.current ?.spaceRoom?.name,
133+ isLastAdmin = leaveSpaceRooms.dataOrNull()?.current ?.isLastAdmin == true ,
121134 selectableSpaceRooms = selectableSpaceRooms,
122135 leaveSpaceAction = leaveSpaceAction.value,
123136 eventSink = ::handleEvents,
@@ -126,7 +139,7 @@ class LeaveSpacePresenter(
126139
127140 private fun CoroutineScope.leaveSpace (
128141 leaveSpaceAction : MutableState <AsyncAction <Unit >>,
129- selectedRoomIds : Set <RoomId >,
142+ selectedRoomIds : Collection <RoomId >,
130143 ) = launch {
131144 runUpdatingState(leaveSpaceAction) {
132145 leaveSpaceHandle.leave(selectedRoomIds.toList())
0 commit comments