favorite : simplify and branch live data again
This commit is contained in:
parent
e00311a739
commit
133064823b
13 changed files with 41 additions and 333 deletions
|
|
@ -1,27 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id("io.element.android-library")
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "io.element.android.features.roomactions.api"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(projects.libraries.matrix.api)
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +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.features.roomactions.api
|
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the favorite status of a room.
|
|
||||||
* Use either the room id or the room instance with the desired favorite status.
|
|
||||||
*/
|
|
||||||
interface SetRoomIsFavoriteAction {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The result of the action?
|
|
||||||
*/
|
|
||||||
sealed interface Result {
|
|
||||||
data object Success : Result
|
|
||||||
data object RoomNotFound : Result
|
|
||||||
data class Exception(val inner: java.lang.Exception) : Result
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the favorite status of a room by its id, it'll try to load the room from the session.
|
|
||||||
*/
|
|
||||||
suspend operator fun invoke(roomId: RoomId, isFavorite: Boolean): Result
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the favorite status of a room using the provided instance.
|
|
||||||
*/
|
|
||||||
suspend operator fun invoke(room: MatrixRoom, isFavorite: Boolean): Result
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
|
|
||||||
@Suppress("DSL_SCOPE_VIOLATION")
|
|
||||||
plugins {
|
|
||||||
id("io.element.android-compose-library")
|
|
||||||
alias(libs.plugins.anvil)
|
|
||||||
alias(libs.plugins.ksp)
|
|
||||||
id("kotlin-parcelize")
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "io.element.android.features.roomactions.impl"
|
|
||||||
}
|
|
||||||
|
|
||||||
anvil {
|
|
||||||
generateDaggerFactories.set(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(projects.anvilannotations)
|
|
||||||
anvil(projects.anvilcodegen)
|
|
||||||
api(projects.features.roomactions.api)
|
|
||||||
implementation(projects.libraries.core)
|
|
||||||
implementation(projects.libraries.architecture)
|
|
||||||
implementation(projects.libraries.matrix.api)
|
|
||||||
|
|
||||||
testImplementation(libs.test.junit)
|
|
||||||
testImplementation(libs.coroutines.test)
|
|
||||||
testImplementation(libs.molecule.runtime)
|
|
||||||
testImplementation(libs.test.truth)
|
|
||||||
testImplementation(libs.test.turbine)
|
|
||||||
testImplementation(projects.libraries.matrix.test)
|
|
||||||
|
|
||||||
ksp(libs.showkase.processor)
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +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.features.roomactions.impl
|
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
|
||||||
import io.element.android.features.roomactions.api.SetRoomIsFavoriteAction
|
|
||||||
import io.element.android.libraries.di.SessionScope
|
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
|
||||||
import javax.inject.Inject
|
|
||||||
import kotlin.coroutines.cancellation.CancellationException
|
|
||||||
|
|
||||||
@ContributesBinding(SessionScope::class)
|
|
||||||
class DefaultSetRoomIsFavoriteAction @Inject constructor(private val client: MatrixClient) : SetRoomIsFavoriteAction {
|
|
||||||
|
|
||||||
override suspend operator fun invoke(roomId: RoomId, isFavorite: Boolean): SetRoomIsFavoriteAction.Result {
|
|
||||||
return client.getRoom(roomId)?.use { room ->
|
|
||||||
invoke(room, isFavorite)
|
|
||||||
} ?: SetRoomIsFavoriteAction.Result.RoomNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun invoke(room: MatrixRoom, isFavorite: Boolean): SetRoomIsFavoriteAction.Result {
|
|
||||||
return room.setIsFavorite(isFavorite).fold(
|
|
||||||
onSuccess = {
|
|
||||||
SetRoomIsFavoriteAction.Result.Success
|
|
||||||
},
|
|
||||||
onFailure = { throwable ->
|
|
||||||
if (throwable is Exception && throwable !is CancellationException) {
|
|
||||||
SetRoomIsFavoriteAction.Result.Exception(throwable)
|
|
||||||
} else {
|
|
||||||
throw throwable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +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.features.roomactions.impl
|
|
||||||
|
|
||||||
import io.element.android.features.roomactions.api.SetRoomIsFavoriteAction
|
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class DefaultSetRoomIsFavoriteActionTests {
|
|
||||||
private val room = FakeMatrixRoom()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given a room id and a client without rooms, when action is invoked, then it returns Result_RoomNotFound`() = runTest {
|
|
||||||
val action = DefaultSetRoomIsFavoriteAction(FakeMatrixClient())
|
|
||||||
val result = action(room.roomId, true)
|
|
||||||
assert(result is SetRoomIsFavoriteAction.Result.RoomNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given a room, when action is invoked, then it returns Result_Success`() = runTest {
|
|
||||||
val action = DefaultSetRoomIsFavoriteAction(FakeMatrixClient())
|
|
||||||
val result = action(room, true)
|
|
||||||
assert(result is SetRoomIsFavoriteAction.Result.Success)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given a room id and a client with a room, when action is invoked, then it returns Result_Success`() = runTest {
|
|
||||||
val client = FakeMatrixClient().apply {
|
|
||||||
givenGetRoomResult(room.roomId, room)
|
|
||||||
}
|
|
||||||
val action = DefaultSetRoomIsFavoriteAction(client)
|
|
||||||
val result = action(room.roomId, true)
|
|
||||||
assert(result is SetRoomIsFavoriteAction.Result.Success)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `given a room, when action is invoked and fail, then it returns Result_Exception`() = runTest {
|
|
||||||
val action = DefaultSetRoomIsFavoriteAction(FakeMatrixClient())
|
|
||||||
room.givenSetIsFavoriteResult(Result.failure(Exception()))
|
|
||||||
val result = action(room, true)
|
|
||||||
assert(result is SetRoomIsFavoriteAction.Result.Exception)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
plugins {
|
|
||||||
id("io.element.android-library")
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "io.element.android.features.roomactions.test"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(projects.features.roomactions.api)
|
|
||||||
implementation(projects.libraries.matrix.api)
|
|
||||||
implementation(libs.coroutines.core)
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +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.features.roomactions.test
|
|
||||||
|
|
||||||
import io.element.android.features.roomactions.api.SetRoomIsFavoriteAction
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
|
||||||
|
|
||||||
class FakeSetRoomIsFavoriteAction : SetRoomIsFavoriteAction {
|
|
||||||
private var counter = 0
|
|
||||||
|
|
||||||
fun assertCalled(number: Int) {
|
|
||||||
assert(counter == number) { "Expected $number calls, got $counter" }
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun invoke(roomId: RoomId, isFavorite: Boolean): SetRoomIsFavoriteAction.Result {
|
|
||||||
counter++
|
|
||||||
return SetRoomIsFavoriteAction.Result.Success
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun invoke(room: MatrixRoom, isFavorite: Boolean): SetRoomIsFavoriteAction.Result {
|
|
||||||
counter++
|
|
||||||
return SetRoomIsFavoriteAction.Result.Success
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -54,7 +54,6 @@ dependencies {
|
||||||
implementation(projects.features.createroom.api)
|
implementation(projects.features.createroom.api)
|
||||||
implementation(projects.services.analytics.api)
|
implementation(projects.services.analytics.api)
|
||||||
implementation(projects.features.poll.api)
|
implementation(projects.features.poll.api)
|
||||||
implementation(projects.features.roomactions.api)
|
|
||||||
|
|
||||||
testImplementation(libs.test.junit)
|
testImplementation(libs.test.junit)
|
||||||
testImplementation(libs.coroutines.test)
|
testImplementation(libs.coroutines.test)
|
||||||
|
|
@ -71,7 +70,6 @@ dependencies {
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
testImplementation(projects.features.leaveroom.test)
|
testImplementation(projects.features.leaveroom.test)
|
||||||
testImplementation(projects.features.createroom.test)
|
testImplementation(projects.features.createroom.test)
|
||||||
testImplementation(projects.features.roomactions.test)
|
|
||||||
|
|
||||||
ksp(libs.showkase.processor)
|
ksp(libs.showkase.processor)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
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.roomactions.api.SetRoomIsFavoriteAction
|
|
||||||
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
|
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.bool.orFalse
|
import io.element.android.libraries.core.bool.orFalse
|
||||||
|
|
@ -62,19 +61,19 @@ class RoomDetailsPresenter @Inject constructor(
|
||||||
private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory,
|
private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory,
|
||||||
private val leaveRoomPresenter: LeaveRoomPresenter,
|
private val leaveRoomPresenter: LeaveRoomPresenter,
|
||||||
private val dispatchers: CoroutineDispatchers,
|
private val dispatchers: CoroutineDispatchers,
|
||||||
private val setRoomIsFavorite: SetRoomIsFavoriteAction,
|
|
||||||
) : Presenter<RoomDetailsState> {
|
) : Presenter<RoomDetailsState> {
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): RoomDetailsState {
|
override fun present(): RoomDetailsState {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val leaveRoomState = leaveRoomPresenter.present()
|
val leaveRoomState = leaveRoomPresenter.present()
|
||||||
val canShowNotificationSettings = remember { mutableStateOf(false) }
|
val canShowNotificationSettings = remember { mutableStateOf(false) }
|
||||||
val roomInfo = room.roomInfoFlow.collectAsState(initial = null).value
|
val roomInfo by room.roomInfoFlow.collectAsState(initial = null)
|
||||||
|
|
||||||
val roomAvatar by remember { derivedStateOf { roomInfo?.avatarUrl ?: room.avatarUrl } }
|
val roomAvatar by remember { derivedStateOf { roomInfo?.avatarUrl ?: room.avatarUrl } }
|
||||||
|
|
||||||
val roomName by remember { derivedStateOf { (roomInfo?.name ?: room.name ?: room.displayName).trim() } }
|
val roomName by remember { derivedStateOf { (roomInfo?.name ?: room.name ?: room.displayName).trim() } }
|
||||||
val roomTopic by remember { derivedStateOf { roomInfo?.topic ?: room.topic } }
|
val roomTopic by remember { derivedStateOf { roomInfo?.topic ?: room.topic } }
|
||||||
|
val isFavorite by remember { derivedStateOf { roomInfo?.isFavorite.orFalse() } }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
canShowNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings)
|
canShowNotificationSettings.value = featureFlagService.isFeatureEnabled(FeatureFlags.NotificationSettings)
|
||||||
|
|
@ -99,9 +98,6 @@ class RoomDetailsPresenter @Inject constructor(
|
||||||
val dmMember by room.getDirectRoomMember(membersState)
|
val dmMember by room.getDirectRoomMember(membersState)
|
||||||
val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember)
|
val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember)
|
||||||
val roomType by getRoomType(dmMember)
|
val roomType by getRoomType(dmMember)
|
||||||
val isFavorite by remember {
|
|
||||||
derivedStateOf { roomInfo?.isFavorite.orFalse() }
|
|
||||||
}
|
|
||||||
|
|
||||||
val topicState = remember(canEditTopic, roomTopic, roomType) {
|
val topicState = remember(canEditTopic, roomTopic, roomType) {
|
||||||
val topic = roomTopic
|
val topic = roomTopic
|
||||||
|
|
@ -131,7 +127,7 @@ class RoomDetailsPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
is RoomDetailsEvent.SetIsFavorite -> {
|
is RoomDetailsEvent.SetIsFavorite -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
setRoomIsFavorite(room, event.isFavorite)
|
room.setIsFavorite(event.isFavorite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ dependencies {
|
||||||
implementation(projects.features.networkmonitor.api)
|
implementation(projects.features.networkmonitor.api)
|
||||||
implementation(projects.features.leaveroom.api)
|
implementation(projects.features.leaveroom.api)
|
||||||
implementation(projects.services.analytics.api)
|
implementation(projects.services.analytics.api)
|
||||||
implementation(projects.features.roomactions.api)
|
|
||||||
api(projects.features.roomlist.api)
|
api(projects.features.roomlist.api)
|
||||||
ksp(libs.showkase.processor)
|
ksp(libs.showkase.processor)
|
||||||
|
|
||||||
|
|
@ -80,5 +79,4 @@ dependencies {
|
||||||
testImplementation(projects.features.networkmonitor.test)
|
testImplementation(projects.features.networkmonitor.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
testImplementation(projects.features.leaveroom.test)
|
testImplementation(projects.features.leaveroom.test)
|
||||||
testImplementation(projects.features.roomactions.test)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
||||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||||
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
||||||
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.InviteStateDataSource
|
||||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
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
|
||||||
|
|
@ -54,8 +53,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.flow.collect
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.onCompletion
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val EXTENDED_RANGE_SIZE = 40
|
private const val EXTENDED_RANGE_SIZE = 40
|
||||||
|
|
@ -201,6 +204,15 @@ 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 ->
|
||||||
|
room.roomInfoFlow
|
||||||
|
.onEach { roomInfo ->
|
||||||
|
contextMenuState.value = initialState.copy(
|
||||||
|
isFavorite = roomInfo.isFavorite,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateVisibleRange(range: IntRange) {
|
private fun updateVisibleRange(range: IntRange) {
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ class RoomListContextMenuTest {
|
||||||
@Test
|
@Test
|
||||||
fun `clicking on Favourites generates expected Event`() {
|
fun `clicking on Favourites generates expected Event`() {
|
||||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||||
val contextMenu = aContextMenuShown(isDm = false, isFavorite = AsyncData.Success(false))
|
val contextMenu = aContextMenuShown(isDm = false, isFavorite = false)
|
||||||
val callback = EnsureNeverCalledWithParam<RoomId>()
|
val callback = EnsureNeverCalledWithParam<RoomId>()
|
||||||
rule.setContent {
|
rule.setContent {
|
||||||
RoomListContextMenu(
|
RoomListContextMenu(
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,6 @@ import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
|
||||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||||
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
||||||
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
||||||
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.FakeInviteDataSource
|
||||||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
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.RoomListDataSource
|
||||||
|
|
@ -35,7 +33,6 @@ import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryF
|
||||||
import io.element.android.features.roomlist.impl.migration.InMemoryMigrationScreenStore
|
import io.element.android.features.roomlist.impl.migration.InMemoryMigrationScreenStore
|
||||||
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
|
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
|
||||||
import io.element.android.features.roomlist.impl.model.createRoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.createRoomListRoomSummary
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
|
||||||
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
||||||
import io.element.android.libraries.dateformatter.test.A_FORMATTED_DATE
|
import io.element.android.libraries.dateformatter.test.A_FORMATTED_DATE
|
||||||
import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter
|
import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter
|
||||||
|
|
@ -363,10 +360,11 @@ class RoomListPresenterTests {
|
||||||
roomId = summary.roomId,
|
roomId = summary.roomId,
|
||||||
roomName = summary.name,
|
roomName = summary.name,
|
||||||
isDm = false,
|
isDm = false,
|
||||||
isFavorite = AsyncData.Success(false),
|
isFavorite = false,
|
||||||
markAsUnreadFeatureFlagEnabled = true,
|
markAsUnreadFeatureFlagEnabled = true,
|
||||||
hasNewContent = false,
|
hasNewContent = false,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
room.setIsFavorite(isFavorite = true)
|
room.setIsFavorite(isFavorite = true)
|
||||||
|
|
@ -377,10 +375,11 @@ class RoomListPresenterTests {
|
||||||
roomId = summary.roomId,
|
roomId = summary.roomId,
|
||||||
roomName = summary.name,
|
roomName = summary.name,
|
||||||
isDm = false,
|
isDm = false,
|
||||||
isFavorite = AsyncData.Success(true),
|
isFavorite = true,
|
||||||
markAsUnreadFeatureFlagEnabled = true,
|
markAsUnreadFeatureFlagEnabled = true,
|
||||||
hasNewContent = false,
|
hasNewContent = false,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
|
|
@ -405,14 +404,16 @@ class RoomListPresenterTests {
|
||||||
|
|
||||||
val shownState = awaitItem()
|
val shownState = awaitItem()
|
||||||
assertThat(shownState.contextMenu)
|
assertThat(shownState.contextMenu)
|
||||||
.isEqualTo(RoomListState.ContextMenu.Shown(
|
.isEqualTo(
|
||||||
roomId = summary.roomId,
|
RoomListState.ContextMenu.Shown(
|
||||||
roomName = summary.name,
|
roomId = summary.roomId,
|
||||||
isDm = false,
|
roomName = summary.name,
|
||||||
isFavorite = AsyncData.Success(false),
|
isDm = false,
|
||||||
markAsUnreadFeatureFlagEnabled = true,
|
isFavorite = false,
|
||||||
hasNewContent = false,
|
markAsUnreadFeatureFlagEnabled = true,
|
||||||
))
|
hasNewContent = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
shownState.eventSink(RoomListEvents.HideContextMenu)
|
shownState.eventSink(RoomListEvents.HideContextMenu)
|
||||||
|
|
||||||
|
|
@ -469,14 +470,19 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
|
fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
|
||||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||||
val setRoomIsFavoriteAction = FakeSetRoomIsFavoriteAction()
|
val room = FakeMatrixRoom()
|
||||||
val presenter = createRoomListPresenter(setRoomIsFavoriteAction = setRoomIsFavoriteAction, coroutineScope = scope)
|
val client = FakeMatrixClient().apply {
|
||||||
|
givenGetRoomResult(A_ROOM_ID, room)
|
||||||
|
}
|
||||||
|
val presenter = createRoomListPresenter(client = client, coroutineScope = scope)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, true))
|
initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, true))
|
||||||
setRoomIsFavoriteAction.assertCalled(1)
|
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true))
|
||||||
|
initialState.eventSink(RoomListEvents.SetRoomIsFavorite(A_ROOM_ID, false))
|
||||||
|
assertThat(room.setIsFavoriteCalls).isEqualTo(listOf(true, false))
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
|
|
@ -560,7 +566,6 @@ class RoomListPresenterTests {
|
||||||
encryptionService: EncryptionService = FakeEncryptionService(),
|
encryptionService: EncryptionService = FakeEncryptionService(),
|
||||||
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
|
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
|
||||||
coroutineScope: CoroutineScope,
|
coroutineScope: CoroutineScope,
|
||||||
setRoomIsFavoriteAction: SetRoomIsFavoriteAction = FakeSetRoomIsFavoriteAction(),
|
|
||||||
migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter(
|
migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter(
|
||||||
matrixClient = client,
|
matrixClient = client,
|
||||||
migrationScreenStore = InMemoryMigrationScreenStore(),
|
migrationScreenStore = InMemoryMigrationScreenStore(),
|
||||||
|
|
@ -589,7 +594,6 @@ class RoomListPresenterTests {
|
||||||
encryptionService = encryptionService,
|
encryptionService = encryptionService,
|
||||||
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
|
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
|
||||||
),
|
),
|
||||||
setRoomIsFavorite = setRoomIsFavoriteAction,
|
|
||||||
migrationScreenPresenter = migrationScreenPresenter,
|
migrationScreenPresenter = migrationScreenPresenter,
|
||||||
sessionPreferencesStore = sessionPreferencesStore,
|
sessionPreferencesStore = sessionPreferencesStore,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue