favorite : apply pr review remarks

This commit is contained in:
ganfra 2024-02-15 13:22:07 +01:00
parent 81d1111ecc
commit fdba1b2dc6
6 changed files with 23 additions and 44 deletions

View file

@ -20,5 +20,5 @@ sealed interface RoomDetailsEvent {
data object LeaveRoom : RoomDetailsEvent data object LeaveRoom : RoomDetailsEvent
data object MuteNotification : RoomDetailsEvent data object MuteNotification : RoomDetailsEvent
data object UnmuteNotification : RoomDetailsEvent data object UnmuteNotification : RoomDetailsEvent
data class SetIsFavorite(val isFavorite: Boolean) : RoomDetailsEvent data class SetFavorite(val isFavorite: Boolean) : RoomDetailsEvent
} }

View file

@ -124,7 +124,7 @@ class RoomDetailsPresenter @Inject constructor(
client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.isOneToOne) client.notificationSettingsService().unmuteRoom(room.roomId, room.isEncrypted, room.isOneToOne)
} }
} }
is RoomDetailsEvent.SetIsFavorite -> { is RoomDetailsEvent.SetFavorite -> {
scope.launch { scope.launch {
room.setIsFavorite(event.isFavorite) room.setIsFavorite(event.isFavorite)
} }

View file

@ -167,7 +167,7 @@ fun RoomDetailsView(
FavoriteSection( FavoriteSection(
isFavorite = state.isFavorite, isFavorite = state.isFavorite,
onFavoriteChanges = { onFavoriteChanges = {
state.eventSink(RoomDetailsEvent.SetIsFavorite(it)) state.eventSink(RoomDetailsEvent.SetFavorite(it))
} }
) )

View file

@ -438,9 +438,9 @@ class RoomDetailsPresenterTests {
val presenter = createRoomDetailsPresenter(room = room) val presenter = createRoomDetailsPresenter(room = room)
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RoomDetailsEvent.SetIsFavorite(true)) initialState.eventSink(RoomDetailsEvent.SetFavorite(true))
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true)) assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true))
initialState.eventSink(RoomDetailsEvent.SetIsFavorite(false)) initialState.eventSink(RoomDetailsEvent.SetFavorite(false))
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false)) assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false))
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
} }

View file

@ -28,6 +28,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkMonitor
@ -38,8 +39,6 @@ import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.coroutine.cancel
import io.element.android.libraries.architecture.coroutine.rememberJob
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
@ -53,9 +52,12 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.api.user.getCurrentUser import io.element.android.libraries.matrix.api.user.getCurrentUser
import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -120,7 +122,6 @@ class RoomListPresenter @Inject constructor(
var displaySearchResults by rememberSaveable { mutableStateOf(false) } var displaySearchResults by rememberSaveable { mutableStateOf(false) }
val contextMenu = remember { mutableStateOf<RoomListState.ContextMenu>(RoomListState.ContextMenu.Hidden) } val contextMenu = remember { mutableStateOf<RoomListState.ContextMenu>(RoomListState.ContextMenu.Hidden) }
val showContextMenuJob = rememberJob()
fun handleEvents(event: RoomListEvents) { fun handleEvents(event: RoomListEvents) {
when (event) { when (event) {
@ -135,10 +136,9 @@ class RoomListPresenter @Inject constructor(
displaySearchResults = !displaySearchResults displaySearchResults = !displaySearchResults
} }
is RoomListEvents.ShowContextMenu -> { is RoomListEvents.ShowContextMenu -> {
showContextMenuJob.value = coroutineScope.showContextMenu(event, contextMenu) coroutineScope.showContextMenu(event, contextMenu)
} }
is RoomListEvents.HideContextMenu -> { is RoomListEvents.HideContextMenu -> {
showContextMenuJob.cancel()
contextMenu.value = RoomListState.ContextMenu.Hidden contextMenu.value = RoomListState.ContextMenu.Hidden
} }
is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId)) is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId))
@ -192,6 +192,7 @@ class RoomListPresenter @Inject constructor(
matrixUser.value = client.getCurrentUser() matrixUser.value = client.getCurrentUser()
} }
@OptIn(ExperimentalCoroutinesApi::class)
private fun CoroutineScope.showContextMenu(event: RoomListEvents.ShowContextMenu, contextMenuState: MutableState<RoomListState.ContextMenu>) = launch { private fun CoroutineScope.showContextMenu(event: RoomListEvents.ShowContextMenu, contextMenuState: MutableState<RoomListState.ContextMenu>) = launch {
val initialState = RoomListState.ContextMenu.Shown( val initialState = RoomListState.ContextMenu.Shown(
roomId = event.roomListRoomSummary.roomId, roomId = event.roomListRoomSummary.roomId,
@ -202,13 +203,25 @@ class RoomListPresenter @Inject constructor(
hasNewContent = event.roomListRoomSummary.hasNewContent hasNewContent = event.roomListRoomSummary.hasNewContent
) )
contextMenuState.value = initialState contextMenuState.value = initialState
client.getRoom(event.roomListRoomSummary.roomId)?.use { room -> client.getRoom(event.roomListRoomSummary.roomId)?.use { room ->
val isContextMenuShownFlow = snapshotFlow {
contextMenuState.value is RoomListState.ContextMenu.Shown
}
room.roomInfoFlow room.roomInfoFlow
.onEach { roomInfo -> .onEach { roomInfo ->
contextMenuState.value = initialState.copy( contextMenuState.value = initialState.copy(
isFavorite = roomInfo.isFavorite, isFavorite = roomInfo.isFavorite,
) )
} }
.flatMapLatest {
isContextMenuShownFlow
}
.takeWhile { isContextMenuShown ->
isContextMenuShown
}
.collect() .collect()
} }
} }

View file

@ -1,34 +0,0 @@
/*
* Copyright (c) 2024 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.architecture.coroutine
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import kotlinx.coroutines.Job
import kotlin.coroutines.cancellation.CancellationException
@Composable
fun rememberJob(): MutableState<Job?> = remember {
mutableStateOf(null)
}
fun MutableState<Job?>.cancel(cause: CancellationException? = null) {
value?.cancel(cause)
value = null
}