Favorite : rework and add tests
This commit is contained in:
parent
b15597509d
commit
d9017a098c
21 changed files with 454 additions and 144 deletions
|
|
@ -60,7 +60,7 @@ fun RoomListContextMenu(
|
|||
eventSink(RoomListEvents.LeaveRoom(contextMenu.roomId))
|
||||
},
|
||||
onFavoriteChanged = { isFavorite ->
|
||||
eventSink(RoomListEvents.MarkRoomAsFavorite(contextMenu.roomId, isFavorite))
|
||||
eventSink(RoomListEvents.SetRoomIsFavorite(contextMenu.roomId, isFavorite))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ sealed interface RoomListEvents {
|
|||
data class ShowContextMenu(val roomListRoomSummary: RoomListRoomSummary) : RoomListEvents
|
||||
data object HideContextMenu : RoomListEvents
|
||||
data class LeaveRoom(val roomId: RoomId) : RoomListEvents
|
||||
data class MarkRoomAsFavorite(val roomId: RoomId, val isFavorite: Boolean) : RoomListEvents
|
||||
data class SetRoomIsFavorite(val roomId: RoomId, val isFavorite: Boolean) : RoomListEvents
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
|||
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||
import io.element.android.features.roomactions.api.SetRoomIsFavoriteAction
|
||||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
|
|
@ -45,17 +46,14 @@ import io.element.android.libraries.indicator.api.IndicatorService
|
|||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.api.room.tags.RoomNotableTags
|
||||
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.verification.SessionVerificationService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val EXTENDED_RANGE_SIZE = 40
|
||||
|
|
@ -71,6 +69,7 @@ class RoomListPresenter @Inject constructor(
|
|||
private val encryptionService: EncryptionService,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
private val indicatorService: IndicatorService,
|
||||
private val setRoomIsFavorite: SetRoomIsFavoriteAction,
|
||||
) : Presenter<RoomListState> {
|
||||
@Composable
|
||||
override fun present(): RoomListState {
|
||||
|
|
@ -134,7 +133,7 @@ class RoomListPresenter @Inject constructor(
|
|||
contextMenu.value = RoomListState.ContextMenu.Hidden
|
||||
}
|
||||
is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId))
|
||||
is RoomListEvents.MarkRoomAsFavorite -> coroutineScope.markRoomAsFavorite(event)
|
||||
is RoomListEvents.SetRoomIsFavorite -> coroutineScope.setRoomIsFavorite(event)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,28 +169,23 @@ class RoomListPresenter @Inject constructor(
|
|||
isFavorite = AsyncData.Loading(),
|
||||
)
|
||||
contextMenuState.value = initialState
|
||||
val room = client.getRoom(event.roomListRoomSummary.roomId)
|
||||
if (room != null) {
|
||||
room.notableTagsFlow
|
||||
.distinctUntilChanged()
|
||||
.onEach { tags ->
|
||||
val newState = initialState.copy(isFavorite = AsyncData.Success(tags.isFavorite))
|
||||
contextMenuState.value = newState
|
||||
}
|
||||
.launchIn(this)
|
||||
} else {
|
||||
contextMenuState.value = initialState.copy(isFavorite = AsyncData.Failure(IllegalStateException("Room not found")))
|
||||
client.getRoom(event.roomListRoomSummary.roomId).use { room ->
|
||||
if (room != null) {
|
||||
room.notableTagsFlow
|
||||
.distinctUntilChanged()
|
||||
.onEach { tags ->
|
||||
val newState = initialState.copy(isFavorite = AsyncData.Success(tags.isFavorite))
|
||||
contextMenuState.value = newState
|
||||
}
|
||||
.collect()
|
||||
} else {
|
||||
contextMenuState.value = initialState.copy(isFavorite = AsyncData.Failure(IllegalStateException("Room not found")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.markRoomAsFavorite(event: RoomListEvents.MarkRoomAsFavorite) = launch {
|
||||
val room = client.getRoom(event.roomId)
|
||||
if (room != null) {
|
||||
val notableTags = RoomNotableTags(isFavorite = event.isFavorite);
|
||||
room.updateNotableTags(notableTags)
|
||||
}else {
|
||||
Timber.w("Room ${event.roomId} not found, can't mark as favorite");
|
||||
}
|
||||
private fun CoroutineScope.setRoomIsFavorite(event: RoomListEvents.SetRoomIsFavorite) = launch {
|
||||
setRoomIsFavorite(event.roomId, event.isFavorite)
|
||||
}
|
||||
|
||||
private fun updateVisibleRange(range: IntRange) {
|
||||
|
|
@ -204,5 +198,3 @@ class RoomListPresenter @Inject constructor(
|
|||
client.roomListService.updateAllRoomsVisibleRange(extendedRange)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,14 @@ import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
|||
import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
|
||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
||||
import io.element.android.features.roomactions.api.SetRoomIsFavoriteAction
|
||||
import io.element.android.features.roomactions.test.FakeSetRoomIsFavoriteAction
|
||||
import io.element.android.features.roomlist.impl.datasource.FakeInviteDataSource
|
||||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
||||
import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory
|
||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
||||
import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
|
|
@ -44,6 +47,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
|||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.api.room.tags.RoomNotableTags
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
|
|
@ -55,6 +59,7 @@ import io.element.android.libraries.matrix.test.A_USER_NAME
|
|||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
|
||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||
|
|
@ -309,19 +314,29 @@ class RoomListPresenterTests {
|
|||
@Test
|
||||
fun `present - show context menu`() = runTest {
|
||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||
val presenter = createRoomListPresenter(coroutineScope = scope)
|
||||
val room = FakeMatrixRoom()
|
||||
val client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(A_ROOM_ID, room)
|
||||
}
|
||||
val presenter = createRoomListPresenter(client = client, coroutineScope = scope)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
skipItems(1)
|
||||
|
||||
val initialState = awaitItem()
|
||||
val summary = aRoomListRoomSummary
|
||||
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
|
||||
|
||||
val shownState = awaitItem()
|
||||
assertThat(shownState.contextMenu)
|
||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false))
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.contextMenu)
|
||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false, AsyncData.Success(false)))
|
||||
}
|
||||
|
||||
room.updateNotableTags(RoomNotableTags(isFavorite = true))
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.contextMenu)
|
||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false, AsyncData.Success(true)))
|
||||
}
|
||||
scope.cancel()
|
||||
}
|
||||
}
|
||||
|
|
@ -329,7 +344,11 @@ class RoomListPresenterTests {
|
|||
@Test
|
||||
fun `present - hide context menu`() = runTest {
|
||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||
val presenter = createRoomListPresenter(coroutineScope = scope)
|
||||
val room = FakeMatrixRoom()
|
||||
val client = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(A_ROOM_ID, room)
|
||||
}
|
||||
val presenter = createRoomListPresenter(client = client, coroutineScope = scope)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
|
@ -341,7 +360,7 @@ class RoomListPresenterTests {
|
|||
|
||||
val shownState = awaitItem()
|
||||
assertThat(shownState.contextMenu)
|
||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false))
|
||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false, AsyncData.Success(false)))
|
||||
shownState.eventSink(RoomListEvents.HideContextMenu)
|
||||
|
||||
val hiddenState = awaitItem()
|
||||
|
|
@ -394,6 +413,22 @@ class RoomListPresenterTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
|
||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||
val setRoomIsFavoriteAction = FakeSetRoomIsFavoriteAction()
|
||||
val presenter = createRoomListPresenter(setRoomIsFavoriteAction = setRoomIsFavoriteAction, coroutineScope = scope)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, true))
|
||||
setRoomIsFavoriteAction.assertCalled(1)
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
scope.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private fun TestScope.createRoomListPresenter(
|
||||
client: MatrixClient = FakeMatrixClient(),
|
||||
sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(),
|
||||
|
|
@ -407,6 +442,7 @@ class RoomListPresenterTests {
|
|||
roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(),
|
||||
encryptionService: EncryptionService = FakeEncryptionService(),
|
||||
coroutineScope: CoroutineScope,
|
||||
setRoomIsFavoriteAction: SetRoomIsFavoriteAction = FakeSetRoomIsFavoriteAction(),
|
||||
) = RoomListPresenter(
|
||||
client = client,
|
||||
sessionVerificationService = sessionVerificationService,
|
||||
|
|
@ -431,6 +467,7 @@ class RoomListPresenterTests {
|
|||
encryptionService = encryptionService,
|
||||
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
|
||||
),
|
||||
setRoomIsFavorite = setRoomIsFavoriteAction,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue