diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 01c3dc12d1..d12c6ca901 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -58,7 +58,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.SnackbarMessage -import io.element.android.libraries.designsystem.utils.handleSnackbarMessage +import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MessageEventType @@ -110,7 +110,7 @@ class MessagesPresenter @AssistedInject constructor( val networkConnectionStatus by networkMonitor.connectivity.collectAsState(initial = networkMonitor.currentConnectivityStatus) - val snackbarMessage = handleSnackbarMessage(snackbarDispatcher) + val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() LaunchedEffect(syncUpdateFlow) { roomAvatar.value = diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt index 88bf7c91c2..5ef1bdcd47 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt @@ -35,7 +35,7 @@ import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.SnackbarMessage -import io.element.android.libraries.designsystem.utils.handleSnackbarMessage +import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaFile import kotlinx.coroutines.CoroutineScope @@ -66,7 +66,7 @@ class MediaViewerPresenter @AssistedInject constructor( val localMedia: MutableState> = remember { mutableStateOf(Async.Uninitialized) } - val snackbarMessage = handleSnackbarMessage(snackbarDispatcher) + val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() localMediaActions.Configure() DisposableEffect(loadMediaTrigger) { coroutineScope.downloadMedia(mediaFile, localMedia) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index 9448ff4b1b..12791b8083 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -38,7 +38,7 @@ import io.element.android.libraries.core.extensions.orEmpty import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.handleSnackbarMessage +import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId @@ -135,7 +135,7 @@ class RoomListPresenter @Inject constructor( filteredRoomSummaries.value = updateFilteredRoomSummaries(mappedRoomSummaries.value, filter) } - val snackbarMessage = handleSnackbarMessage(snackbarDispatcher) + val snackbarMessage by snackbarDispatcher.collectSnackbarMessageAsState() return RoomListState( matrixUser = matrixUser.value, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt index 1de46c78e0..ba9f2d3121 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt @@ -21,6 +21,7 @@ import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.remember @@ -28,27 +29,31 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.res.stringResource import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +/** + * A global dispatcher of [SnackbarMessage] to be displayed in [Snackbar] via a [SnackbarHostState]. + */ class SnackbarDispatcher { private val mutex = Mutex() - private val snackbarState = MutableStateFlow(null) - val snackbarMessage: Flow = snackbarState + private val _snackbarMessage = MutableStateFlow(null) + val snackbarMessage: Flow = _snackbarMessage.asStateFlow() suspend fun post(message: SnackbarMessage) { mutex.withLock { - snackbarState.update { message } + _snackbarMessage.update { message } } } suspend fun clear() { mutex.withLock { - snackbarState.update { null } + _snackbarMessage.update { null } } } } @@ -59,10 +64,8 @@ val LocalSnackbarDispatcher = compositionLocalOf { } @Composable -fun handleSnackbarMessage( - snackbarDispatcher: SnackbarDispatcher -): SnackbarMessage? { - return snackbarDispatcher.snackbarMessage.collectAsState(initial = null).value +fun SnackbarDispatcher.collectSnackbarMessageAsState(): State { + return snackbarMessage.collectAsState(initial = null) } @Composable