Browse Source
* Add leave room functionality to the Room Details screen * Add snackbar message throught `SnackbarDistpacher`test/jme/compound-poc
Jorge Martin Espinosa
1 year ago
committed by
GitHub
32 changed files with 564 additions and 71 deletions
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.appnav |
||||
|
||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher |
||||
import io.element.android.libraries.designsystem.utils.SnackbarMessage |
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver |
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService |
||||
import io.element.android.libraries.matrix.api.verification.VerificationFlowState |
||||
import io.element.android.libraries.ui.strings.R |
||||
import kotlinx.coroutines.CoroutineScope |
||||
import kotlinx.coroutines.Dispatchers |
||||
import kotlinx.coroutines.Job |
||||
import kotlinx.coroutines.flow.drop |
||||
import kotlinx.coroutines.flow.launchIn |
||||
import kotlinx.coroutines.flow.map |
||||
import kotlinx.coroutines.flow.onEach |
||||
import kotlinx.coroutines.launch |
||||
import javax.inject.Inject |
||||
import kotlin.coroutines.coroutineContext |
||||
|
||||
class LoggedInEventProcessor @Inject constructor( |
||||
private val snackbarDispatcher: SnackbarDispatcher, |
||||
roomMembershipObserver: RoomMembershipObserver, |
||||
sessionVerificationService: SessionVerificationService, |
||||
) { |
||||
|
||||
private var observingJob: Job? = null |
||||
|
||||
private val displayLeftRoomMessage = roomMembershipObserver.updates |
||||
.map { !it.isUserInRoom } |
||||
|
||||
private val displayVerificationSuccessfulMessage = sessionVerificationService.verificationFlowState |
||||
.map { it == VerificationFlowState.Finished } |
||||
|
||||
fun observeEvents(coroutineScope: CoroutineScope) { |
||||
observingJob = coroutineScope.launch { |
||||
displayLeftRoomMessage.onEach { |
||||
displayMessage(R.string.common_current_user_left_room) |
||||
}.launchIn(this) |
||||
|
||||
displayVerificationSuccessfulMessage |
||||
.drop(1) |
||||
.onEach { |
||||
displayMessage(R.string.common_verification_complete) |
||||
}.launchIn(this) |
||||
} |
||||
} |
||||
|
||||
fun stopObserving() { |
||||
observingJob?.cancel() |
||||
observingJob = null |
||||
} |
||||
|
||||
private suspend fun displayMessage(message: Int) { |
||||
snackbarDispatcher.post(SnackbarMessage(message)) |
||||
} |
||||
} |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
Add leave room functionality to the Room Details screen. |
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.designsystem.utils |
||||
|
||||
import androidx.annotation.StringRes |
||||
import androidx.compose.material3.SnackbarDuration |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.LaunchedEffect |
||||
import androidx.compose.runtime.collectAsState |
||||
import androidx.compose.runtime.getValue |
||||
import kotlinx.coroutines.Dispatchers |
||||
import kotlinx.coroutines.flow.Flow |
||||
import kotlinx.coroutines.flow.MutableStateFlow |
||||
import kotlinx.coroutines.flow.update |
||||
import kotlinx.coroutines.launch |
||||
import kotlinx.coroutines.sync.Mutex |
||||
import kotlinx.coroutines.sync.withLock |
||||
|
||||
class SnackbarDispatcher { |
||||
private val mutex = Mutex() |
||||
|
||||
private val snackbarState = MutableStateFlow<SnackbarMessage?>(null) |
||||
val snackbarMessage: Flow<SnackbarMessage?> = snackbarState |
||||
|
||||
suspend fun post(message: SnackbarMessage) { |
||||
mutex.withLock { |
||||
snackbarState.update { message } |
||||
} |
||||
} |
||||
|
||||
suspend fun clear() { |
||||
mutex.withLock { |
||||
snackbarState.update { null } |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Composable |
||||
fun handleSnackbarMessage( |
||||
snackbarDispatcher: SnackbarDispatcher |
||||
): SnackbarMessage? { |
||||
val snackbarMessage by snackbarDispatcher.snackbarMessage.collectAsState(initial = null) |
||||
LaunchedEffect(snackbarMessage) { |
||||
if (snackbarMessage != null) { |
||||
launch(Dispatchers.Main) { |
||||
snackbarDispatcher.clear() |
||||
} |
||||
} |
||||
} |
||||
return snackbarMessage |
||||
} |
||||
|
||||
data class SnackbarMessage( |
||||
@StringRes val messageResId: Int, |
||||
val duration: SnackbarDuration = SnackbarDuration.Short, |
||||
@StringRes val actionResId: Int? = null, |
||||
val action: () -> Unit = {}, |
||||
) |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright (c) 2023 New Vector Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package io.element.android.libraries.matrix.api.room |
||||
|
||||
import io.element.android.libraries.matrix.api.core.RoomId |
||||
import io.element.android.libraries.matrix.api.core.SessionId |
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange |
||||
import kotlinx.coroutines.flow.MutableSharedFlow |
||||
import kotlinx.coroutines.flow.asSharedFlow |
||||
|
||||
class RoomMembershipObserver( |
||||
private val sessionId: SessionId, |
||||
) { |
||||
data class RoomMembershipUpdate( |
||||
val roomId: RoomId, |
||||
val isUserInRoom: Boolean, |
||||
val change: MembershipChange, |
||||
) |
||||
|
||||
private val _updates = MutableSharedFlow<RoomMembershipUpdate>(replay = 1) |
||||
val updates = _updates.asSharedFlow() |
||||
|
||||
fun notifyUserLeftRoom(roomId: RoomId) { |
||||
_updates.tryEmit(RoomMembershipUpdate(roomId, false, MembershipChange.LEFT)) |
||||
} |
||||
} |
Loading…
Reference in new issue