@@ -37,6 +37,7 @@ import io.element.android.libraries.architecture.NodeInputs
37
37
import io.element.android.libraries.architecture.createNode
38
38
import io.element.android.libraries.architecture.inputs
39
39
import io.element.android.libraries.core.bool.orFalse
40
+ import io.element.android.libraries.core.coroutine.withPreviousValue
40
41
import io.element.android.libraries.di.SessionScope
41
42
import io.element.android.libraries.matrix.api.MatrixClient
42
43
import io.element.android.libraries.matrix.api.core.RoomAlias
@@ -47,11 +48,14 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
47
48
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
48
49
import io.element.android.libraries.matrix.api.sync.SyncService
49
50
import io.element.android.libraries.matrix.ui.room.LoadingRoomState
51
+ import kotlinx.coroutines.flow.SharingStarted
50
52
import kotlinx.coroutines.flow.combine
51
53
import kotlinx.coroutines.flow.distinctUntilChanged
54
+ import kotlinx.coroutines.flow.filter
52
55
import kotlinx.coroutines.flow.first
53
56
import kotlinx.coroutines.flow.launchIn
54
57
import kotlinx.coroutines.flow.map
58
+ import kotlinx.coroutines.flow.shareIn
55
59
import kotlinx.coroutines.launch
56
60
import kotlinx.parcelize.Parcelize
57
61
import timber.log.Timber
@@ -124,8 +128,19 @@ class RoomFlowNode @AssistedInject constructor(
124
128
private fun subscribeToRoomInfoFlow (roomId : RoomId , serverNames : List <String >) {
125
129
val roomInfoFlow = client.getRoomInfoFlow(roomId)
126
130
val isSpaceFlow = roomInfoFlow.map { it.getOrNull()?.isSpace.orFalse() }.distinctUntilChanged()
127
- val currentMembershipFlow = roomInfoFlow.map { it.getOrNull()?.currentUserMembership }.distinctUntilChanged()
128
- combine(currentMembershipFlow, isSpaceFlow) { membership, isSpace ->
131
+
132
+ // This observes the local membership changes for the room
133
+ val membershipUpdateFlow = membershipObserver.updates
134
+ .filter { it.roomId == roomId }
135
+ .distinctUntilChanged()
136
+ // We add a replay so we can check the last local membership update
137
+ .shareIn(lifecycleScope, started = SharingStarted .Eagerly , replay = 1 )
138
+
139
+ val currentMembershipFlow = roomInfoFlow
140
+ .map { it.getOrNull()?.currentUserMembership }
141
+ .distinctUntilChanged()
142
+ .withPreviousValue()
143
+ combine(currentMembershipFlow, isSpaceFlow) { (previousMembership, membership), isSpace ->
129
144
Timber .d(" Room membership: $membership " )
130
145
when (membership) {
131
146
CurrentUserMembership .JOINED -> {
@@ -146,26 +161,24 @@ class RoomFlowNode @AssistedInject constructor(
146
161
}
147
162
}
148
163
else -> {
149
- // Was invited or the room is not known, display the join room screen
150
- backstack.newRoot(
151
- NavTarget .JoinRoom (
152
- roomId = roomId,
153
- serverNames = serverNames,
154
- trigger = inputs.trigger.getOrNull() ? : JoinedRoom .Trigger .Invite ,
164
+ if (membership == CurrentUserMembership .LEFT && previousMembership == CurrentUserMembership .JOINED ) {
165
+ // The user left the room in this device, remove the room from the backstack
166
+ if (! membershipUpdateFlow.first().isUserInRoom) {
167
+ navigateUp()
168
+ }
169
+ } else {
170
+ // Was invited or the room is not known, display the join room screen
171
+ backstack.newRoot(
172
+ NavTarget .JoinRoom (
173
+ roomId = roomId,
174
+ serverNames = serverNames,
175
+ trigger = inputs.trigger.getOrNull() ? : JoinedRoom .Trigger .Invite ,
176
+ )
155
177
)
156
- )
178
+ }
157
179
}
158
180
}
159
181
}.launchIn(lifecycleScope)
160
-
161
- // If the user leaves the room from this client, close the room flow.
162
- lifecycleScope.launch {
163
- membershipObserver.updates
164
- .first { it.roomId == roomId && ! it.isUserInRoom }
165
- .run {
166
- navigateUp()
167
- }
168
- }
169
182
}
170
183
171
184
override fun resolve (navTarget : NavTarget , buildContext : BuildContext ): Node {
0 commit comments