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 @@ |
|||||||
|
/* |
||||||
|
* 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 @@ |
|||||||
|
Add leave room functionality to the Room Details screen. |
@ -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 @@ |
|||||||
|
/* |
||||||
|
* 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