RoomList invites : update and remove tests
This commit is contained in:
parent
8f583d78ac
commit
b09269333d
24 changed files with 144 additions and 584 deletions
|
|
@ -50,7 +50,6 @@ dependencies {
|
||||||
testImplementation(libs.test.turbine)
|
testImplementation(libs.test.turbine)
|
||||||
testImplementation(projects.libraries.matrix.test)
|
testImplementation(projects.libraries.matrix.test)
|
||||||
testImplementation(projects.libraries.push.test)
|
testImplementation(projects.libraries.push.test)
|
||||||
testImplementation(projects.features.invite.test)
|
|
||||||
testImplementation(projects.services.analytics.test)
|
testImplementation(projects.services.analytics.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,265 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.features.invite.impl.invitelist
|
|
||||||
|
|
||||||
import app.cash.molecule.RecompositionMode
|
|
||||||
import app.cash.molecule.moleculeFlow
|
|
||||||
import app.cash.turbine.TurbineTestContext
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
|
||||||
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
|
||||||
import io.element.android.features.invite.api.response.anAcceptDeclineInviteState
|
|
||||||
import io.element.android.features.invite.test.FakeSeenInvitesStore
|
|
||||||
import io.element.android.libraries.architecture.Presenter
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
|
||||||
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.RoomMembershipState
|
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
|
||||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_NAME
|
|
||||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
|
||||||
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.room.aRoomMember
|
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
|
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class InviteListPresenterTests {
|
|
||||||
@get:Rule
|
|
||||||
val warmUpRule = WarmUpRule()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - starts empty, adds invites when received`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
val presenter = createInviteListPresenter(
|
|
||||||
FakeMatrixClient(roomListService = roomListService)
|
|
||||||
)
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val initialState = awaitItem()
|
|
||||||
assertThat(initialState.inviteList).isEmpty()
|
|
||||||
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummary()))
|
|
||||||
|
|
||||||
val withInviteState = awaitItem()
|
|
||||||
assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - uses user ID and avatar for direct invites`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService().withDirectChatInvitation()
|
|
||||||
val presenter = createInviteListPresenter(
|
|
||||||
FakeMatrixClient(roomListService = roomListService)
|
|
||||||
)
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val withInviteState = awaitInitialItem()
|
|
||||||
assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomAlias).isEqualTo(A_USER_ID.value)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomName).isEqualTo(A_ROOM_NAME)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomAvatarData).isEqualTo(
|
|
||||||
AvatarData(
|
|
||||||
id = A_USER_ID.value,
|
|
||||||
name = A_USER_NAME,
|
|
||||||
url = AN_AVATAR_URL,
|
|
||||||
size = AvatarSize.RoomInviteItem,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
assertThat(withInviteState.inviteList[0].sender).isNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - includes sender details for room invites`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService().withRoomInvitation()
|
|
||||||
val presenter = createInviteListPresenter(
|
|
||||||
FakeMatrixClient(roomListService = roomListService)
|
|
||||||
)
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val withInviteState = awaitInitialItem()
|
|
||||||
assertThat(withInviteState.inviteList.size).isEqualTo(1)
|
|
||||||
assertThat(withInviteState.inviteList[0].sender?.displayName).isEqualTo(A_USER_NAME)
|
|
||||||
assertThat(withInviteState.inviteList[0].sender?.userId).isEqualTo(A_USER_ID)
|
|
||||||
assertThat(withInviteState.inviteList[0].sender?.avatarData).isEqualTo(
|
|
||||||
AvatarData(
|
|
||||||
id = A_USER_ID.value,
|
|
||||||
name = A_USER_NAME,
|
|
||||||
url = AN_AVATAR_URL,
|
|
||||||
size = AvatarSize.InviteSender,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - stores seen invites when received`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
val store = FakeSeenInvitesStore()
|
|
||||||
val presenter = createInviteListPresenter(
|
|
||||||
FakeMatrixClient(
|
|
||||||
roomListService = roomListService,
|
|
||||||
),
|
|
||||||
store,
|
|
||||||
)
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
awaitItem()
|
|
||||||
|
|
||||||
// When one invite is received, that ID is saved
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummary()))
|
|
||||||
|
|
||||||
awaitItem()
|
|
||||||
assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID))
|
|
||||||
|
|
||||||
// When a second is added, both are saved
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
|
|
||||||
|
|
||||||
awaitItem()
|
|
||||||
assertThat(store.getProvidedRoomIds()).isEqualTo(setOf(A_ROOM_ID, A_ROOM_ID_2))
|
|
||||||
|
|
||||||
// When they're both dismissed, an empty set is saved
|
|
||||||
roomListService.postInviteRooms(listOf())
|
|
||||||
|
|
||||||
awaitItem()
|
|
||||||
assertThat(store.getProvidedRoomIds()).isEmpty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - marks invite as new if they're unseen`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
val store = FakeSeenInvitesStore()
|
|
||||||
store.publishRoomIds(setOf(A_ROOM_ID))
|
|
||||||
val presenter = createInviteListPresenter(
|
|
||||||
FakeMatrixClient(
|
|
||||||
roomListService = roomListService,
|
|
||||||
),
|
|
||||||
store,
|
|
||||||
)
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
awaitItem()
|
|
||||||
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummary(), aRoomSummary(A_ROOM_ID_2)))
|
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
val withInviteState = awaitItem()
|
|
||||||
assertThat(withInviteState.inviteList.size).isEqualTo(2)
|
|
||||||
assertThat(withInviteState.inviteList[0].roomId).isEqualTo(A_ROOM_ID)
|
|
||||||
assertThat(withInviteState.inviteList[0].isNew).isFalse()
|
|
||||||
assertThat(withInviteState.inviteList[1].roomId).isEqualTo(A_ROOM_ID_2)
|
|
||||||
assertThat(withInviteState.inviteList[1].isNew).isTrue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun FakeRoomListService.withRoomInvitation(): FakeRoomListService {
|
|
||||||
postInviteRooms(
|
|
||||||
listOf(
|
|
||||||
RoomSummary.Filled(
|
|
||||||
aRoomSummaryDetails(
|
|
||||||
roomId = A_ROOM_ID,
|
|
||||||
name = A_ROOM_NAME,
|
|
||||||
avatarUrl = null,
|
|
||||||
isDirect = false,
|
|
||||||
lastMessage = null,
|
|
||||||
inviter = aRoomMember(
|
|
||||||
userId = A_USER_ID,
|
|
||||||
displayName = A_USER_NAME,
|
|
||||||
avatarUrl = AN_AVATAR_URL,
|
|
||||||
membership = RoomMembershipState.JOIN,
|
|
||||||
isNameAmbiguous = false,
|
|
||||||
powerLevel = 0,
|
|
||||||
normalizedPowerLevel = 0,
|
|
||||||
isIgnored = false,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun FakeRoomListService.withDirectChatInvitation(): FakeRoomListService {
|
|
||||||
postInviteRooms(
|
|
||||||
listOf(
|
|
||||||
RoomSummary.Filled(
|
|
||||||
aRoomSummaryDetails(
|
|
||||||
roomId = A_ROOM_ID,
|
|
||||||
name = A_ROOM_NAME,
|
|
||||||
avatarUrl = null,
|
|
||||||
isDirect = true,
|
|
||||||
lastMessage = null,
|
|
||||||
inviter = aRoomMember(
|
|
||||||
userId = A_USER_ID,
|
|
||||||
displayName = A_USER_NAME,
|
|
||||||
avatarUrl = AN_AVATAR_URL,
|
|
||||||
membership = RoomMembershipState.JOIN,
|
|
||||||
isNameAmbiguous = false,
|
|
||||||
powerLevel = 0,
|
|
||||||
normalizedPowerLevel = 0,
|
|
||||||
isIgnored = false,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun aRoomSummary(id: RoomId = A_ROOM_ID) = RoomSummary.Filled(
|
|
||||||
aRoomSummaryDetails(
|
|
||||||
roomId = id,
|
|
||||||
name = A_ROOM_NAME,
|
|
||||||
avatarUrl = null,
|
|
||||||
isDirect = false,
|
|
||||||
lastMessage = null,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
private suspend fun TurbineTestContext<InviteListState>.awaitInitialItem(): InviteListState {
|
|
||||||
skipItems(1)
|
|
||||||
return awaitItem()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createInviteListPresenter(
|
|
||||||
client: MatrixClient,
|
|
||||||
seenInvitesStore: SeenInvitesStore = FakeSeenInvitesStore(),
|
|
||||||
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() },
|
|
||||||
) = InviteListPresenter(
|
|
||||||
client,
|
|
||||||
seenInvitesStore,
|
|
||||||
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022 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.invite.test"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(libs.coroutines.core)
|
|
||||||
implementation(projects.libraries.matrix.api)
|
|
||||||
api(projects.features.invite.api)
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.features.invite.test
|
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
|
|
||||||
class FakeSeenInvitesStore : SeenInvitesStore {
|
|
||||||
private val existing = MutableStateFlow(emptySet<RoomId>())
|
|
||||||
private var provided: Set<RoomId>? = null
|
|
||||||
|
|
||||||
fun publishRoomIds(invites: Set<RoomId>) {
|
|
||||||
existing.value = invites
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getProvidedRoomIds() = provided
|
|
||||||
|
|
||||||
override fun seenRoomIds(): Flow<Set<RoomId>> = existing
|
|
||||||
|
|
||||||
override suspend fun markAsSeen(roomIds: Set<RoomId>) {
|
|
||||||
provided = roomIds.toSet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -49,7 +49,6 @@ dependencies {
|
||||||
testImplementation(libs.test.truth)
|
testImplementation(libs.test.truth)
|
||||||
testImplementation(libs.test.turbine)
|
testImplementation(libs.test.turbine)
|
||||||
testImplementation(projects.libraries.matrix.test)
|
testImplementation(projects.libraries.matrix.test)
|
||||||
testImplementation(projects.features.invite.test)
|
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
|
|
||||||
ksp(libs.showkase.processor)
|
ksp(libs.showkase.processor)
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ dependencies {
|
||||||
testImplementation(projects.libraries.indicator.impl)
|
testImplementation(projects.libraries.indicator.impl)
|
||||||
testImplementation(projects.libraries.permissions.noop)
|
testImplementation(projects.libraries.permissions.noop)
|
||||||
testImplementation(projects.libraries.preferences.test)
|
testImplementation(projects.libraries.preferences.test)
|
||||||
testImplementation(projects.features.invite.test)
|
|
||||||
testImplementation(projects.services.analytics.test)
|
testImplementation(projects.services.analytics.test)
|
||||||
testImplementation(projects.features.networkmonitor.test)
|
testImplementation(projects.features.networkmonitor.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.takeWhile
|
import kotlinx.coroutines.flow.takeWhile
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.jetbrains.annotations.VisibleForTesting
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val EXTENDED_RANGE_SIZE = 40
|
private const val EXTENDED_RANGE_SIZE = 40
|
||||||
|
|
@ -292,10 +293,11 @@ class RoomListPresenter @Inject constructor(
|
||||||
val extendedRange = IntRange(extendedRangeStart, extendedRangeEnd)
|
val extendedRange = IntRange(extendedRangeStart, extendedRangeEnd)
|
||||||
client.roomListService.updateAllRoomsVisibleRange(extendedRange)
|
client.roomListService.updateAllRoomsVisibleRange(extendedRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RoomListRoomSummary.toInviteData() = InviteData(
|
|
||||||
roomId = roomId,
|
|
||||||
roomName = name,
|
|
||||||
isDirect = isDirect,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
internal fun RoomListRoomSummary.toInviteData() = InviteData(
|
||||||
|
roomId = roomId,
|
||||||
|
roomName = name,
|
||||||
|
isDirect = isDirect,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ import io.element.android.features.leaveroom.api.LeaveRoomState
|
||||||
import io.element.android.features.leaveroom.api.aLeaveRoomState
|
import io.element.android.features.leaveroom.api.aLeaveRoomState
|
||||||
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
|
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
|
||||||
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
|
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
|
||||||
import io.element.android.features.roomlist.impl.model.DisplayType
|
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
|
||||||
|
import io.element.android.features.roomlist.impl.model.InviteSender
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||||
import io.element.android.features.roomlist.impl.model.aRoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.aRoomListRoomSummary
|
||||||
import io.element.android.features.roomlist.impl.search.RoomListSearchState
|
import io.element.android.features.roomlist.impl.search.RoomListSearchState
|
||||||
|
|
@ -83,6 +84,17 @@ internal fun aRoomListState(
|
||||||
|
|
||||||
internal fun aRoomListRoomSummaryList(): ImmutableList<RoomListRoomSummary> {
|
internal fun aRoomListRoomSummaryList(): ImmutableList<RoomListRoomSummary> {
|
||||||
return persistentListOf(
|
return persistentListOf(
|
||||||
|
aRoomListRoomSummary(
|
||||||
|
name = "Room Invited",
|
||||||
|
avatarData = AvatarData("!roomId", "Room with Alice and Bob", size = AvatarSize.RoomListItem),
|
||||||
|
id = "!roomId:domain",
|
||||||
|
inviteSender = InviteSender(
|
||||||
|
userId = UserId("@bob:domain"),
|
||||||
|
displayName = "Bob",
|
||||||
|
avatarData = AvatarData("@bob:domain", "Bob", size = AvatarSize.InviteSender),
|
||||||
|
),
|
||||||
|
displayType = RoomSummaryDisplayType.INVITE,
|
||||||
|
),
|
||||||
aRoomListRoomSummary(
|
aRoomListRoomSummary(
|
||||||
name = "Room",
|
name = "Room",
|
||||||
numberOfUnreadMessages = 1,
|
numberOfUnreadMessages = 1,
|
||||||
|
|
@ -101,11 +113,11 @@ internal fun aRoomListRoomSummaryList(): ImmutableList<RoomListRoomSummary> {
|
||||||
),
|
),
|
||||||
aRoomListRoomSummary(
|
aRoomListRoomSummary(
|
||||||
id = "!roomId3:domain",
|
id = "!roomId3:domain",
|
||||||
displayType = DisplayType.PLACEHOLDER,
|
displayType = RoomSummaryDisplayType.PLACEHOLDER,
|
||||||
),
|
),
|
||||||
aRoomListRoomSummary(
|
aRoomListRoomSummary(
|
||||||
id = "!roomId4:domain",
|
id = "!roomId4:domain",
|
||||||
displayType = DisplayType.PLACEHOLDER,
|
displayType = RoomSummaryDisplayType.PLACEHOLDER,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ private fun RoomListScaffold(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun RoomListRoomSummary.contentType() = type.ordinal
|
internal fun RoomListRoomSummary.contentType() = displayType.ordinal
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||||
import io.element.android.features.roomlist.impl.RoomListEvents
|
import io.element.android.features.roomlist.impl.RoomListEvents
|
||||||
import io.element.android.features.roomlist.impl.model.DisplayType
|
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
|
||||||
import io.element.android.features.roomlist.impl.model.InviteSender
|
import io.element.android.features.roomlist.impl.model.InviteSender
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
|
||||||
|
|
@ -78,11 +78,11 @@ internal fun RoomSummaryRow(
|
||||||
eventSink: (RoomListEvents) -> Unit,
|
eventSink: (RoomListEvents) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
when (room.type) {
|
when (room.displayType) {
|
||||||
DisplayType.PLACEHOLDER -> {
|
RoomSummaryDisplayType.PLACEHOLDER -> {
|
||||||
RoomSummaryPlaceholderRow(modifier = modifier)
|
RoomSummaryPlaceholderRow(modifier = modifier)
|
||||||
}
|
}
|
||||||
DisplayType.INVITE -> {
|
RoomSummaryDisplayType.INVITE -> {
|
||||||
RoomSummaryScaffoldRow(
|
RoomSummaryScaffoldRow(
|
||||||
room = room,
|
room = room,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
@ -107,7 +107,7 @@ internal fun RoomSummaryRow(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DisplayType.ROOM -> {
|
RoomSummaryDisplayType.ROOM -> {
|
||||||
RoomSummaryScaffoldRow(
|
RoomSummaryScaffoldRow(
|
||||||
room = room,
|
room = room,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ package io.element.android.features.roomlist.impl.datasource
|
||||||
|
|
||||||
import io.element.android.features.roomlist.impl.model.InviteSender
|
import io.element.android.features.roomlist.impl.model.InviteSender
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||||
import io.element.android.features.roomlist.impl.model.DisplayType
|
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
|
||||||
import io.element.android.libraries.core.extensions.orEmpty
|
import io.element.android.libraries.core.extensions.orEmpty
|
||||||
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormatter
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
|
|
@ -38,7 +38,7 @@ class RoomListRoomSummaryFactory @Inject constructor(
|
||||||
return RoomListRoomSummary(
|
return RoomListRoomSummary(
|
||||||
id = id,
|
id = id,
|
||||||
roomId = RoomId(id),
|
roomId = RoomId(id),
|
||||||
type = DisplayType.PLACEHOLDER,
|
displayType = RoomSummaryDisplayType.PLACEHOLDER,
|
||||||
name = "Short name",
|
name = "Short name",
|
||||||
timestamp = "hh:mm",
|
timestamp = "hh:mm",
|
||||||
lastMessage = "Last message for placeholder",
|
lastMessage = "Last message for placeholder",
|
||||||
|
|
@ -95,10 +95,10 @@ class RoomListRoomSummaryFactory @Inject constructor(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
canonicalAlias = roomSummary.details.canonicalAlias,
|
canonicalAlias = roomSummary.details.canonicalAlias,
|
||||||
type = if (roomSummary.details.currentUserMembership == CurrentUserMembership.INVITED) {
|
displayType = if (roomSummary.details.currentUserMembership == CurrentUserMembership.INVITED) {
|
||||||
DisplayType.INVITE
|
RoomSummaryDisplayType.INVITE
|
||||||
} else {
|
} else {
|
||||||
DisplayType.ROOM
|
RoomSummaryDisplayType.ROOM
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||||
@Immutable
|
@Immutable
|
||||||
data class RoomListRoomSummary(
|
data class RoomListRoomSummary(
|
||||||
val id: String,
|
val id: String,
|
||||||
val type: DisplayType,
|
val displayType: RoomSummaryDisplayType,
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val name: String,
|
val name: String,
|
||||||
val canonicalAlias: String?,
|
val canonicalAlias: String?,
|
||||||
|
|
@ -45,11 +45,11 @@ data class RoomListRoomSummary(
|
||||||
val isHighlighted = userDefinedNotificationMode != RoomNotificationMode.MUTE &&
|
val isHighlighted = userDefinedNotificationMode != RoomNotificationMode.MUTE &&
|
||||||
(numberOfUnreadNotifications > 0 || numberOfUnreadMentions > 0) ||
|
(numberOfUnreadNotifications > 0 || numberOfUnreadMentions > 0) ||
|
||||||
isMarkedUnread ||
|
isMarkedUnread ||
|
||||||
type == DisplayType.INVITE
|
displayType == RoomSummaryDisplayType.INVITE
|
||||||
|
|
||||||
val hasNewContent = numberOfUnreadMessages > 0 ||
|
val hasNewContent = numberOfUnreadMessages > 0 ||
|
||||||
numberOfUnreadMentions > 0 ||
|
numberOfUnreadMentions > 0 ||
|
||||||
numberOfUnreadNotifications > 0 ||
|
numberOfUnreadNotifications > 0 ||
|
||||||
isMarkedUnread ||
|
isMarkedUnread ||
|
||||||
type == DisplayType.INVITE
|
displayType == RoomSummaryDisplayType.INVITE
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSu
|
||||||
override val values: Sequence<RoomListRoomSummary>
|
override val values: Sequence<RoomListRoomSummary>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
listOf(
|
listOf(
|
||||||
aRoomListRoomSummary(displayType = DisplayType.PLACEHOLDER),
|
aRoomListRoomSummary(displayType = RoomSummaryDisplayType.PLACEHOLDER),
|
||||||
aRoomListRoomSummary(),
|
aRoomListRoomSummary(),
|
||||||
aRoomListRoomSummary(lastMessage = null),
|
aRoomListRoomSummary(lastMessage = null),
|
||||||
aRoomListRoomSummary(
|
aRoomListRoomSummary(
|
||||||
|
|
@ -83,7 +83,7 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSu
|
||||||
}.flatten(),
|
}.flatten(),
|
||||||
listOf(
|
listOf(
|
||||||
aRoomListRoomSummary(
|
aRoomListRoomSummary(
|
||||||
displayType = DisplayType.INVITE,
|
displayType = RoomSummaryDisplayType.INVITE,
|
||||||
inviteSender = InviteSender(
|
inviteSender = InviteSender(
|
||||||
userId = UserId("@alice:matrix.org"),
|
userId = UserId("@alice:matrix.org"),
|
||||||
displayName = "Alice",
|
displayName = "Alice",
|
||||||
|
|
@ -93,7 +93,7 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSu
|
||||||
),
|
),
|
||||||
aRoomListRoomSummary(
|
aRoomListRoomSummary(
|
||||||
name = "Bob",
|
name = "Bob",
|
||||||
displayType = DisplayType.INVITE,
|
displayType = RoomSummaryDisplayType.INVITE,
|
||||||
inviteSender = InviteSender(
|
inviteSender = InviteSender(
|
||||||
userId = UserId("@bob:matrix.org"),
|
userId = UserId("@bob:matrix.org"),
|
||||||
displayName = "Bob",
|
displayName = "Bob",
|
||||||
|
|
@ -120,7 +120,7 @@ internal fun aRoomListRoomSummary(
|
||||||
isDirect: Boolean = false,
|
isDirect: Boolean = false,
|
||||||
isFavorite: Boolean = false,
|
isFavorite: Boolean = false,
|
||||||
inviteSender: InviteSender? = null,
|
inviteSender: InviteSender? = null,
|
||||||
displayType: DisplayType = DisplayType.ROOM,
|
displayType: RoomSummaryDisplayType = RoomSummaryDisplayType.ROOM,
|
||||||
canonicalAlias: String? = null,
|
canonicalAlias: String? = null,
|
||||||
) = RoomListRoomSummary(
|
) = RoomListRoomSummary(
|
||||||
id = id,
|
id = id,
|
||||||
|
|
@ -138,6 +138,6 @@ internal fun aRoomListRoomSummary(
|
||||||
isDirect = isDirect,
|
isDirect = isDirect,
|
||||||
isFavorite = isFavorite,
|
isFavorite = isFavorite,
|
||||||
inviteSender = inviteSender,
|
inviteSender = inviteSender,
|
||||||
type = displayType,
|
displayType = displayType,
|
||||||
canonicalAlias = canonicalAlias,
|
canonicalAlias = canonicalAlias,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ package io.element.android.features.roomlist.impl.model
|
||||||
/**
|
/**
|
||||||
* Represents the type of display for a room list item.
|
* Represents the type of display for a room list item.
|
||||||
*/
|
*/
|
||||||
enum class DisplayType {
|
enum class RoomSummaryDisplayType {
|
||||||
PLACEHOLDER,
|
PLACEHOLDER,
|
||||||
ROOM,
|
ROOM,
|
||||||
INVITE
|
INVITE
|
||||||
|
|
@ -21,13 +21,15 @@ import app.cash.molecule.moleculeFlow
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import im.vector.app.features.analytics.plan.Interaction
|
import im.vector.app.features.analytics.plan.Interaction
|
||||||
|
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
|
||||||
|
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
||||||
|
import io.element.android.features.invite.api.response.anAcceptDeclineInviteState
|
||||||
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.leaveroom.fake.FakeLeaveRoomPresenter
|
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.roomlist.impl.datasource.FakeInviteDataSource
|
|
||||||
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.datasource.RoomListRoomSummaryFactory
|
import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory
|
||||||
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
|
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
|
||||||
|
|
@ -51,6 +53,7 @@ import io.element.android.libraries.indicator.impl.DefaultIndicatorService
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
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.BackupState
|
||||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||||
|
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
||||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||||
|
|
@ -76,15 +79,20 @@ import io.element.android.tests.testutils.EventsRecorder
|
||||||
import io.element.android.tests.testutils.MutablePresenter
|
import io.element.android.tests.testutils.MutablePresenter
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||||
|
import io.element.android.tests.testutils.lambda.assert
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
|
import io.element.android.tests.testutils.lambda.value
|
||||||
|
import io.element.android.tests.testutils.test
|
||||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.test.TestScope
|
import kotlinx.coroutines.test.TestScope
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.util.Optional
|
||||||
|
|
||||||
class RoomListPresenterTests {
|
class RoomListPresenterTests {
|
||||||
@get:Rule
|
@get:Rule
|
||||||
|
|
@ -302,38 +310,6 @@ class RoomListPresenterTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `present - sets invite state`() = runTest {
|
|
||||||
val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites)
|
|
||||||
val inviteStateDataSource = FakeInviteDataSource(inviteStateFlow)
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
|
||||||
val presenter = createRoomListPresenter(
|
|
||||||
inviteStateDataSource = inviteStateDataSource,
|
|
||||||
coroutineScope = scope,
|
|
||||||
client = FakeMatrixClient(roomListService = roomListService),
|
|
||||||
)
|
|
||||||
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
presenter.present()
|
|
||||||
}.test {
|
|
||||||
val firstItem = consumeItemsUntilPredicate {
|
|
||||||
it.contentState is RoomListContentState.Rooms
|
|
||||||
}.last()
|
|
||||||
assertThat(firstItem.contentAsRooms().invitesState).isEqualTo(InvitesState.NoInvites)
|
|
||||||
|
|
||||||
inviteStateFlow.value = InvitesState.SeenInvites
|
|
||||||
assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.SeenInvites)
|
|
||||||
|
|
||||||
inviteStateFlow.value = InvitesState.NewInvites
|
|
||||||
assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.NewInvites)
|
|
||||||
|
|
||||||
inviteStateFlow.value = InvitesState.NoInvites
|
|
||||||
assertThat(awaitItem().contentAsRooms().invitesState).isEqualTo(InvitesState.NoInvites)
|
|
||||||
scope.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - show context menu`() = runTest {
|
fun `present - show context menu`() = runTest {
|
||||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||||
|
|
@ -608,11 +584,53 @@ class RoomListPresenterTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - when a room is invited then accept and decline events are sent to acceptDeclinePresenter`() = runTest {
|
||||||
|
val eventSinkRecorder = lambdaRecorder { _: AcceptDeclineInviteEvents -> }
|
||||||
|
val acceptDeclinePresenter = Presenter {
|
||||||
|
anAcceptDeclineInviteState(eventSink = eventSinkRecorder)
|
||||||
|
}
|
||||||
|
val roomListService = FakeRoomListService()
|
||||||
|
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||||
|
val matrixClient = FakeMatrixClient(
|
||||||
|
roomListService = roomListService,
|
||||||
|
)
|
||||||
|
val roomSummary = aRoomSummaryFilled(
|
||||||
|
currentUserMembership = CurrentUserMembership.INVITED
|
||||||
|
)
|
||||||
|
roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1))
|
||||||
|
roomListService.postAllRooms(listOf(roomSummary))
|
||||||
|
val presenter = createRoomListPresenter(
|
||||||
|
coroutineScope = scope,
|
||||||
|
client = matrixClient,
|
||||||
|
acceptDeclineInvitePresenter = acceptDeclinePresenter
|
||||||
|
)
|
||||||
|
presenter.test {
|
||||||
|
val state = consumeItemsUntilPredicate {
|
||||||
|
it.contentState is RoomListContentState.Rooms
|
||||||
|
}.last()
|
||||||
|
|
||||||
|
val roomListRoomSummary = state.contentAsRooms().summaries.first {
|
||||||
|
it.id == roomSummary.identifier()
|
||||||
|
}
|
||||||
|
state.eventSink(RoomListEvents.AcceptInvite(roomListRoomSummary))
|
||||||
|
state.eventSink(RoomListEvents.DeclineInvite(roomListRoomSummary))
|
||||||
|
|
||||||
|
val inviteData = roomListRoomSummary.toInviteData()
|
||||||
|
|
||||||
|
assert(eventSinkRecorder)
|
||||||
|
.isCalledExactly(2)
|
||||||
|
.withSequence(
|
||||||
|
listOf(value(AcceptDeclineInviteEvents.AcceptInvite(inviteData))),
|
||||||
|
listOf(value(AcceptDeclineInviteEvents.DeclineInvite(inviteData))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun TestScope.createRoomListPresenter(
|
private fun TestScope.createRoomListPresenter(
|
||||||
client: MatrixClient = FakeMatrixClient(),
|
client: MatrixClient = FakeMatrixClient(),
|
||||||
networkMonitor: NetworkMonitor = FakeNetworkMonitor(),
|
networkMonitor: NetworkMonitor = FakeNetworkMonitor(),
|
||||||
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
|
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
|
||||||
inviteStateDataSource: InviteStateDataSource = FakeInviteDataSource(),
|
|
||||||
leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(),
|
leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(),
|
||||||
lastMessageTimestampFormatter: LastMessageTimestampFormatter = FakeLastMessageTimestampFormatter().apply {
|
lastMessageTimestampFormatter: LastMessageTimestampFormatter = FakeLastMessageTimestampFormatter().apply {
|
||||||
givenFormat(A_FORMATTED_DATE)
|
givenFormat(A_FORMATTED_DATE)
|
||||||
|
|
@ -625,11 +643,11 @@ class RoomListPresenterTests {
|
||||||
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||||
filtersPresenter: Presenter<RoomListFiltersState> = Presenter { aRoomListFiltersState() },
|
filtersPresenter: Presenter<RoomListFiltersState> = Presenter { aRoomListFiltersState() },
|
||||||
searchPresenter: Presenter<RoomListSearchState> = Presenter { aRoomListSearchState() },
|
searchPresenter: Presenter<RoomListSearchState> = Presenter { aRoomListSearchState() },
|
||||||
|
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() },
|
||||||
) = RoomListPresenter(
|
) = RoomListPresenter(
|
||||||
client = client,
|
client = client,
|
||||||
networkMonitor = networkMonitor,
|
networkMonitor = networkMonitor,
|
||||||
snackbarDispatcher = snackbarDispatcher,
|
snackbarDispatcher = snackbarDispatcher,
|
||||||
inviteStateDataSource = inviteStateDataSource,
|
|
||||||
leaveRoomPresenter = leaveRoomPresenter,
|
leaveRoomPresenter = leaveRoomPresenter,
|
||||||
roomListDataSource = RoomListDataSource(
|
roomListDataSource = RoomListDataSource(
|
||||||
roomListService = client.roomListService,
|
roomListService = client.roomListService,
|
||||||
|
|
@ -651,5 +669,6 @@ class RoomListPresenterTests {
|
||||||
sessionPreferencesStore = sessionPreferencesStore,
|
sessionPreferencesStore = sessionPreferencesStore,
|
||||||
filtersPresenter = filtersPresenter,
|
filtersPresenter = filtersPresenter,
|
||||||
analyticsService = analyticsService,
|
analyticsService = analyticsService,
|
||||||
|
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import androidx.compose.ui.test.performClick
|
||||||
import androidx.compose.ui.test.performTouchInput
|
import androidx.compose.ui.test.performTouchInput
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.element.android.features.roomlist.impl.components.RoomListMenuAction
|
import io.element.android.features.roomlist.impl.components.RoomListMenuAction
|
||||||
|
import io.element.android.features.roomlist.impl.model.RoomSummaryDisplayType
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
import io.element.android.tests.testutils.EnsureNeverCalled
|
import io.element.android.tests.testutils.EnsureNeverCalled
|
||||||
|
|
@ -93,7 +94,9 @@ class RoomListViewTest {
|
||||||
val state = aRoomListState(
|
val state = aRoomListState(
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
)
|
)
|
||||||
val room0 = state.contentAsRooms().summaries.first()
|
val room0 = state.contentAsRooms().summaries.first{
|
||||||
|
it.displayType == RoomSummaryDisplayType.ROOM
|
||||||
|
}
|
||||||
ensureCalledOnceWithParam(room0.roomId) { callback ->
|
ensureCalledOnceWithParam(room0.roomId) { callback ->
|
||||||
rule.setRoomListView(
|
rule.setRoomListView(
|
||||||
state = state,
|
state = state,
|
||||||
|
|
@ -109,7 +112,9 @@ class RoomListViewTest {
|
||||||
val state = aRoomListState(
|
val state = aRoomListState(
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
)
|
)
|
||||||
val room0 = state.contentAsRooms().summaries.first()
|
val room0 = state.contentAsRooms().summaries.first{
|
||||||
|
it.displayType == RoomSummaryDisplayType.ROOM
|
||||||
|
}
|
||||||
rule.setRoomListView(
|
rule.setRoomListView(
|
||||||
state = state,
|
state = state,
|
||||||
)
|
)
|
||||||
|
|
@ -136,19 +141,20 @@ class RoomListViewTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking on invites invokes the expected callback`() {
|
fun `clicking on accept and decline invite emits the expected Events`() {
|
||||||
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
val eventsRecorder = EventsRecorder<RoomListEvents>()
|
||||||
val state = aRoomListState(
|
val state = aRoomListState(
|
||||||
contentState = aRoomsContentState(invitesState = InvitesState.NewInvites),
|
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
)
|
)
|
||||||
ensureCalledOnce { callback ->
|
val invitedRoom = state.contentAsRooms().summaries.first {
|
||||||
rule.setRoomListView(
|
it.displayType == RoomSummaryDisplayType.INVITE
|
||||||
state = state,
|
|
||||||
onInvitesClicked = callback,
|
|
||||||
)
|
|
||||||
rule.clickOn(CommonStrings.action_invites_list)
|
|
||||||
}
|
}
|
||||||
|
rule.setRoomListView(state = state)
|
||||||
|
rule.clickOn(CommonStrings.action_accept)
|
||||||
|
rule.clickOn(CommonStrings.action_decline)
|
||||||
|
eventsRecorder.assertList(
|
||||||
|
listOf(RoomListEvents.AcceptInvite(invitedRoom),RoomListEvents.DeclineInvite(invitedRoom)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,7 +164,6 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
|
||||||
onSettingsClicked: () -> Unit = EnsureNeverCalled(),
|
onSettingsClicked: () -> Unit = EnsureNeverCalled(),
|
||||||
onConfirmRecoveryKeyClicked: () -> Unit = EnsureNeverCalled(),
|
onConfirmRecoveryKeyClicked: () -> Unit = EnsureNeverCalled(),
|
||||||
onCreateRoomClicked: () -> Unit = EnsureNeverCalled(),
|
onCreateRoomClicked: () -> Unit = EnsureNeverCalled(),
|
||||||
onInvitesClicked: () -> Unit = EnsureNeverCalled(),
|
|
||||||
onRoomSettingsClicked: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
onRoomSettingsClicked: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
|
||||||
onMenuActionClicked: (RoomListMenuAction) -> Unit = EnsureNeverCalledWithParam(),
|
onMenuActionClicked: (RoomListMenuAction) -> Unit = EnsureNeverCalledWithParam(),
|
||||||
onRoomDirectorySearchClicked: () -> Unit = EnsureNeverCalled(),
|
onRoomDirectorySearchClicked: () -> Unit = EnsureNeverCalled(),
|
||||||
|
|
@ -170,10 +175,10 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
|
||||||
onSettingsClicked = onSettingsClicked,
|
onSettingsClicked = onSettingsClicked,
|
||||||
onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked,
|
onConfirmRecoveryKeyClicked = onConfirmRecoveryKeyClicked,
|
||||||
onCreateRoomClicked = onCreateRoomClicked,
|
onCreateRoomClicked = onCreateRoomClicked,
|
||||||
onInvitesClicked = onInvitesClicked,
|
|
||||||
onRoomSettingsClicked = onRoomSettingsClicked,
|
onRoomSettingsClicked = onRoomSettingsClicked,
|
||||||
onMenuActionClicked = onMenuActionClicked,
|
onMenuActionClicked = onMenuActionClicked,
|
||||||
onRoomDirectorySearchClicked = onRoomDirectorySearchClicked,
|
onRoomDirectorySearchClicked = onRoomDirectorySearchClicked,
|
||||||
|
acceptDeclineInviteView = { },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,134 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.features.roomlist.impl.datasource
|
|
||||||
|
|
||||||
import app.cash.molecule.RecompositionMode
|
|
||||||
import app.cash.molecule.moleculeFlow
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
|
||||||
import io.element.android.features.invite.test.FakeSeenInvitesStore
|
|
||||||
import io.element.android.features.roomlist.impl.InvitesState
|
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
|
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
|
||||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
|
||||||
import kotlinx.coroutines.test.runTest
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
internal class DefaultInviteStateDataSourceTest {
|
|
||||||
@Test
|
|
||||||
fun `emits NoInvites state if invites list is empty`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
val client = FakeMatrixClient(roomListService = roomListService)
|
|
||||||
val seenStore = FakeSeenInvitesStore()
|
|
||||||
val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers())
|
|
||||||
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
dataSource.inviteState()
|
|
||||||
}.test {
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `emits NewInvites state if unseen invite exists`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
|
|
||||||
val client = FakeMatrixClient(roomListService = roomListService)
|
|
||||||
val seenStore = FakeSeenInvitesStore()
|
|
||||||
val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers())
|
|
||||||
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
dataSource.inviteState()
|
|
||||||
}.test {
|
|
||||||
skipItems(2)
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `emits NewInvites state if multiple invites exist and at least one is unseen`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
|
|
||||||
val client = FakeMatrixClient(roomListService = roomListService)
|
|
||||||
val seenStore = FakeSeenInvitesStore()
|
|
||||||
seenStore.publishRoomIds(setOf(A_ROOM_ID))
|
|
||||||
val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers(useUnconfinedTestDispatcher = true))
|
|
||||||
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
dataSource.inviteState()
|
|
||||||
}.test {
|
|
||||||
skipItems(1)
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `emits SeenInvites state if invite exists in seen store`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
|
|
||||||
val client = FakeMatrixClient(roomListService = roomListService)
|
|
||||||
val seenStore = FakeSeenInvitesStore()
|
|
||||||
seenStore.publishRoomIds(setOf(A_ROOM_ID))
|
|
||||||
val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers(useUnconfinedTestDispatcher = true))
|
|
||||||
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
dataSource.inviteState()
|
|
||||||
}.test {
|
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `emits new state in response to upstream events`() = runTest {
|
|
||||||
val roomListService = FakeRoomListService()
|
|
||||||
val client = FakeMatrixClient(roomListService = roomListService)
|
|
||||||
val seenStore = FakeSeenInvitesStore()
|
|
||||||
val dataSource = DefaultInviteStateDataSource(client, seenStore, testCoroutineDispatchers())
|
|
||||||
|
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
|
||||||
dataSource.inviteState()
|
|
||||||
}.test {
|
|
||||||
// Initially there are no invites
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
|
|
||||||
|
|
||||||
// When a single invite is received, state should be NewInvites
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID)))
|
|
||||||
skipItems(1)
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
|
|
||||||
|
|
||||||
// If that invite is marked as seen, then the state becomes SeenInvites
|
|
||||||
seenStore.publishRoomIds(setOf(A_ROOM_ID))
|
|
||||||
skipItems(1)
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.SeenInvites)
|
|
||||||
|
|
||||||
// Another new invite resets it to NewInvites
|
|
||||||
roomListService.postInviteRooms(listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(roomId = A_ROOM_ID_2)))
|
|
||||||
skipItems(1)
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NewInvites)
|
|
||||||
|
|
||||||
// All of the invites going away reverts to NoInvites
|
|
||||||
roomListService.postInviteRooms(emptyList())
|
|
||||||
skipItems(1)
|
|
||||||
assertThat(awaitItem()).isEqualTo(InvitesState.NoInvites)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.features.roomlist.impl.datasource
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import io.element.android.features.roomlist.impl.InvitesState
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
|
|
||||||
class FakeInviteDataSource(
|
|
||||||
private val flow: Flow<InvitesState> = flowOf()
|
|
||||||
) : InviteStateDataSource {
|
|
||||||
@Composable
|
|
||||||
override fun inviteState(): InvitesState {
|
|
||||||
val state = flow.collectAsState(initial = InvitesState.NoInvites)
|
|
||||||
return state.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -45,6 +45,7 @@ class RoomListFiltersPresenterTests {
|
||||||
filterSelectionState(RoomListFilter.People, false),
|
filterSelectionState(RoomListFilter.People, false),
|
||||||
filterSelectionState(RoomListFilter.Rooms, false),
|
filterSelectionState(RoomListFilter.Rooms, false),
|
||||||
filterSelectionState(RoomListFilter.Favourites, false),
|
filterSelectionState(RoomListFilter.Favourites, false),
|
||||||
|
filterSelectionState(RoomListFilter.Invites, false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
|
|
@ -84,6 +85,7 @@ class RoomListFiltersPresenterTests {
|
||||||
filterSelectionState(RoomListFilter.People, false),
|
filterSelectionState(RoomListFilter.People, false),
|
||||||
filterSelectionState(RoomListFilter.Rooms, false),
|
filterSelectionState(RoomListFilter.Rooms, false),
|
||||||
filterSelectionState(RoomListFilter.Favourites, false),
|
filterSelectionState(RoomListFilter.Favourites, false),
|
||||||
|
filterSelectionState(RoomListFilter.Invites, false),
|
||||||
).inOrder()
|
).inOrder()
|
||||||
assertThat(state.selectedFilters()).isEmpty()
|
assertThat(state.selectedFilters()).isEmpty()
|
||||||
val roomListCurrentFilter = roomListService.allRooms.currentFilter.value as MatrixRoomListFilter.All
|
val roomListCurrentFilter = roomListService.allRooms.currentFilter.value as MatrixRoomListFilter.All
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,15 @@ class RoomListRoomSummaryTest {
|
||||||
assertThat(sut.isHighlighted).isTrue()
|
assertThat(sut.isHighlighted).isTrue()
|
||||||
assertThat(sut.hasNewContent).isTrue()
|
assertThat(sut.hasNewContent).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when display type is invite then isHighlighted and hasNewContent are true`() {
|
||||||
|
val sut = createRoomListRoomSummary(
|
||||||
|
displayType = RoomSummaryDisplayType.INVITE,
|
||||||
|
)
|
||||||
|
assertThat(sut.isHighlighted).isTrue()
|
||||||
|
assertThat(sut.hasNewContent).isTrue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun createRoomListRoomSummary(
|
internal fun createRoomListRoomSummary(
|
||||||
|
|
@ -81,6 +90,7 @@ internal fun createRoomListRoomSummary(
|
||||||
isMarkedUnread: Boolean = false,
|
isMarkedUnread: Boolean = false,
|
||||||
userDefinedNotificationMode: RoomNotificationMode? = null,
|
userDefinedNotificationMode: RoomNotificationMode? = null,
|
||||||
isFavorite: Boolean = false,
|
isFavorite: Boolean = false,
|
||||||
|
displayType: RoomSummaryDisplayType = RoomSummaryDisplayType.ROOM,
|
||||||
) = RoomListRoomSummary(
|
) = RoomListRoomSummary(
|
||||||
id = A_ROOM_ID.value,
|
id = A_ROOM_ID.value,
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
|
|
@ -92,9 +102,11 @@ internal fun createRoomListRoomSummary(
|
||||||
timestamp = A_FORMATTED_DATE,
|
timestamp = A_FORMATTED_DATE,
|
||||||
lastMessage = "",
|
lastMessage = "",
|
||||||
avatarData = AvatarData(id = A_ROOM_ID.value, name = A_ROOM_NAME, size = AvatarSize.RoomListItem),
|
avatarData = AvatarData(id = A_ROOM_ID.value, name = A_ROOM_NAME, size = AvatarSize.RoomListItem),
|
||||||
isPlaceholder = false,
|
displayType = displayType,
|
||||||
userDefinedNotificationMode = userDefinedNotificationMode,
|
userDefinedNotificationMode = userDefinedNotificationMode,
|
||||||
hasRoomCall = false,
|
hasRoomCall = false,
|
||||||
isDirect = false,
|
isDirect = false,
|
||||||
isFavorite = isFavorite,
|
isFavorite = isFavorite,
|
||||||
|
canonicalAlias = null,
|
||||||
|
inviteSender = null,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ fun aRoomSummaryFilled(
|
||||||
numUnreadMentions: Int = 0,
|
numUnreadMentions: Int = 0,
|
||||||
numUnreadMessages: Int = 0,
|
numUnreadMessages: Int = 0,
|
||||||
notificationMode: RoomNotificationMode? = null,
|
notificationMode: RoomNotificationMode? = null,
|
||||||
|
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
|
||||||
) = RoomSummary.Filled(
|
) = RoomSummary.Filled(
|
||||||
aRoomSummaryDetails(
|
aRoomSummaryDetails(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
|
|
@ -51,6 +52,7 @@ fun aRoomSummaryFilled(
|
||||||
numUnreadMentions = numUnreadMentions,
|
numUnreadMentions = numUnreadMentions,
|
||||||
numUnreadMessages = numUnreadMessages,
|
numUnreadMessages = numUnreadMessages,
|
||||||
notificationMode = notificationMode,
|
notificationMode = notificationMode,
|
||||||
|
currentUserMembership = currentUserMembership,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,4 @@ import io.element.android.libraries.push.impl.intent.IntentProvider
|
||||||
|
|
||||||
class FakeIntentProvider : IntentProvider {
|
class FakeIntentProvider : IntentProvider {
|
||||||
override fun getViewRoomIntent(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?) = Intent()
|
override fun getViewRoomIntent(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?) = Intent()
|
||||||
|
|
||||||
override fun getInviteListIntent(sessionId: SessionId) = Intent()
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,4 +65,5 @@ dependencies {
|
||||||
implementation(projects.libraries.featureflag.impl)
|
implementation(projects.libraries.featureflag.impl)
|
||||||
implementation(projects.services.analytics.noop)
|
implementation(projects.services.analytics.noop)
|
||||||
implementation(libs.coroutines.core)
|
implementation(libs.coroutines.core)
|
||||||
|
implementation(projects.libraries.push.test)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ import android.content.Context
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import io.element.android.features.invite.impl.response.AcceptDeclineInvitePresenter
|
||||||
|
import io.element.android.features.invite.impl.response.AcceptDeclineInviteView
|
||||||
import io.element.android.features.leaveroom.impl.LeaveRoomPresenterImpl
|
import io.element.android.features.leaveroom.impl.LeaveRoomPresenterImpl
|
||||||
import io.element.android.features.networkmonitor.impl.NetworkMonitorImpl
|
import io.element.android.features.networkmonitor.impl.NetworkMonitorImpl
|
||||||
import io.element.android.features.roomlist.impl.RoomListPresenter
|
import io.element.android.features.roomlist.impl.RoomListPresenter
|
||||||
|
|
@ -48,6 +50,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
import io.element.android.libraries.preferences.impl.store.DefaultSessionPreferencesStore
|
import io.element.android.libraries.preferences.impl.store.DefaultSessionPreferencesStore
|
||||||
|
import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager
|
||||||
import io.element.android.services.analytics.noop.NoopAnalyticsService
|
import io.element.android.services.analytics.noop.NoopAnalyticsService
|
||||||
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -94,7 +97,6 @@ class RoomListScreen(
|
||||||
client = matrixClient,
|
client = matrixClient,
|
||||||
networkMonitor = NetworkMonitorImpl(context, Singleton.appScope),
|
networkMonitor = NetworkMonitorImpl(context, Singleton.appScope),
|
||||||
snackbarDispatcher = SnackbarDispatcher(),
|
snackbarDispatcher = SnackbarDispatcher(),
|
||||||
inviteStateDataSource = DefaultInviteStateDataSource(matrixClient, DefaultSeenInvitesStore(context), coroutineDispatchers),
|
|
||||||
leaveRoomPresenter = LeaveRoomPresenterImpl(matrixClient, RoomMembershipObserver(), coroutineDispatchers),
|
leaveRoomPresenter = LeaveRoomPresenterImpl(matrixClient, RoomMembershipObserver(), coroutineDispatchers),
|
||||||
roomListDataSource = RoomListDataSource(
|
roomListDataSource = RoomListDataSource(
|
||||||
roomListService = matrixClient.roomListService,
|
roomListService = matrixClient.roomListService,
|
||||||
|
|
@ -130,6 +132,11 @@ class RoomListScreen(
|
||||||
featureFlagService = featureFlagService,
|
featureFlagService = featureFlagService,
|
||||||
filterSelectionStrategy = DefaultFilterSelectionStrategy(),
|
filterSelectionStrategy = DefaultFilterSelectionStrategy(),
|
||||||
),
|
),
|
||||||
|
acceptDeclineInvitePresenter = AcceptDeclineInvitePresenter(
|
||||||
|
client = matrixClient,
|
||||||
|
analyticsService = NoopAnalyticsService(),
|
||||||
|
notificationDrawerManager = FakeNotificationDrawerManager(),
|
||||||
|
),
|
||||||
analyticsService = NoopAnalyticsService(),
|
analyticsService = NoopAnalyticsService(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -152,11 +159,13 @@ class RoomListScreen(
|
||||||
onSettingsClicked = {},
|
onSettingsClicked = {},
|
||||||
onConfirmRecoveryKeyClicked = {},
|
onConfirmRecoveryKeyClicked = {},
|
||||||
onCreateRoomClicked = {},
|
onCreateRoomClicked = {},
|
||||||
onInvitesClicked = {},
|
|
||||||
onRoomSettingsClicked = {},
|
onRoomSettingsClicked = {},
|
||||||
onMenuActionClicked = {},
|
onMenuActionClicked = {},
|
||||||
onRoomDirectorySearchClicked = {},
|
onRoomDirectorySearchClicked = {},
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
acceptDeclineInviteView = {
|
||||||
|
AcceptDeclineInviteView(state = state.acceptDeclineInviteState, onInviteAccepted = {}, onInviteDeclined = {})
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue