Merge develop into feature/fga/permalink_timeline

This commit is contained in:
ganfra 2024-04-18 15:40:17 +02:00
commit 6808edda86
398 changed files with 2667 additions and 2461 deletions

View file

@ -17,7 +17,9 @@
package io.element.android.libraries.matrix.api
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
@ -30,6 +32,7 @@ import io.element.android.libraries.matrix.api.pusher.PushersService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.sync.SyncService
@ -98,4 +101,6 @@ interface MatrixClient : Closeable {
suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result<Unit>
suspend fun getRecentlyVisitedRooms(): Result<List<RoomId>>
suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result<RoomId>
suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias): Result<RoomPreview>
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.api.core
import io.element.android.libraries.androidutils.metadata.isInDebug
import java.io.Serializable
@JvmInline
value class RoomAlias(val value: String) : Serializable {
init {
if (isInDebug && !MatrixPatterns.isRoomAlias(value)) {
error("`$value` is not a valid room alias.\n Example room alias: `#room_alias:domain`.")
}
}
override fun toString(): String = value
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.api.core
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
sealed interface RoomIdOrAlias : Parcelable {
@Parcelize
@JvmInline
value class Id(val roomId: RoomId) : RoomIdOrAlias
@Parcelize
@JvmInline
value class Alias(val roomAlias: RoomAlias) : RoomIdOrAlias
val identifier: String
get() = when (this) {
is Id -> roomId.value
is Alias -> roomAlias.value
}
}
fun RoomId.toRoomIdOrAlias() = RoomIdOrAlias.Id(this)
fun RoomAlias.toRoomIdOrAlias() = RoomIdOrAlias.Alias(this)

View file

@ -20,8 +20,10 @@ import android.net.Uri
import androidx.compose.runtime.Immutable
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
/**
* This sealed class represents all the permalink cases.
@ -29,36 +31,11 @@ import kotlinx.collections.immutable.ImmutableList
*/
@Immutable
sealed interface PermalinkData {
sealed interface RoomLink : PermalinkData {
val viaParameters: ImmutableList<String>
}
data class RoomIdLink(
val roomId: RoomId,
override val viaParameters: ImmutableList<String>
) : RoomLink
data class RoomAliasLink(
val roomAlias: String,
override val viaParameters: ImmutableList<String>
) : RoomLink
sealed interface EventLink : PermalinkData {
val eventId: EventId
val viaParameters: ImmutableList<String>
}
data class EventIdLink(
val roomId: RoomId,
override val eventId: EventId,
override val viaParameters: ImmutableList<String>
) : EventLink
data class EventIdAliasLink(
val roomAlias: String,
override val eventId: EventId,
override val viaParameters: ImmutableList<String>
) : EventLink
data class RoomLink(
val roomIdOrAlias: RoomIdOrAlias,
val eventId: EventId? = null,
val viaParameters: ImmutableList<String> = persistentListOf()
) : PermalinkData
/*
* &room_name=Team2

View file

@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.api.room
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.TransactionId
@ -45,8 +46,8 @@ interface MatrixRoom : Closeable {
val roomId: RoomId
val name: String?
val displayName: String
val alias: String?
val alternativeAliases: List<String>
val alias: RoomAlias?
val alternativeAliases: List<RoomAlias>
val topic: String?
val avatarUrl: String?
val isEncrypted: Boolean

View file

@ -17,6 +17,8 @@
package io.element.android.libraries.matrix.api.room
import androidx.compose.runtime.Immutable
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import kotlinx.collections.immutable.ImmutableList
@ -24,7 +26,7 @@ import kotlinx.collections.immutable.ImmutableMap
@Immutable
data class MatrixRoomInfo(
val id: String,
val id: RoomId,
val name: String?,
val topic: String?,
val avatarUrl: String?,
@ -33,7 +35,7 @@ data class MatrixRoomInfo(
val isSpace: Boolean,
val isTombstoned: Boolean,
val isFavorite: Boolean,
val canonicalAlias: String?,
val canonicalAlias: RoomAlias?,
val alternativeAliases: ImmutableList<String>,
val currentUserMembership: CurrentUserMembership,
val latestEvent: EventTimelineItem?,

View file

@ -23,5 +23,5 @@ sealed interface Mention {
data class User(val userId: UserId) : Mention
data object AtRoom : Mention
data class Room(val roomId: RoomId) : Mention
data class RoomAlias(val roomAlias: String?) : Mention
data class RoomAlias(val roomAlias: RoomAlias?) : Mention
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.api.room.alias
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.room.MatrixRoom
/**
* Return true if the given roomIdOrAlias is the same room as this room.
*/
fun MatrixRoom.matches(roomIdOrAlias: RoomIdOrAlias): Boolean {
return when (roomIdOrAlias) {
is RoomIdOrAlias.Id -> {
roomIdOrAlias.roomId == roomId
}
is RoomIdOrAlias.Alias -> {
roomIdOrAlias.roomAlias == alias || roomIdOrAlias.roomAlias in alternativeAliases
}
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.matrix.api.room.preview
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
data class RoomPreview(
/** The room id for this room. */
val roomId: RoomId,
/** The canonical alias for the room. */
val canonicalAlias: RoomAlias?,
/** The room's name, if set. */
val name: String?,
/** The room's topic, if set. */
val topic: String?,
/** The MXC URI to the room's avatar, if set. */
val avatarUrl: String?,
/** The number of joined members. */
val numberOfJoinedMembers: Long,
/** The room type (space, custom) or nothing, if it's a regular room. */
val roomType: String?,
/** Is the history world-readable for this room? */
val isHistoryWorldReadable: Boolean,
/** Is the room joined by the current user? */
val isJoined: Boolean,
/** Is the current user invited to this room? */
val isInvited: Boolean,
/** is the join rule public for this room? */
val isPublic: Boolean,
/** Can we knock (or restricted-knock) to this room? */
val canKnock: Boolean,
)

View file

@ -16,13 +16,14 @@
package io.element.android.libraries.matrix.api.roomdirectory
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
data class RoomDescription(
val roomId: RoomId,
val name: String?,
val topic: String?,
val alias: String?,
val alias: RoomAlias?,
val avatarUrl: String?,
val joinRule: JoinRule,
val isWorldReadable: Boolean,

View file

@ -57,6 +57,11 @@ sealed interface RoomListFilter {
*/
data object Favorite : RoomListFilter
/**
* A filter that matches rooms with Invited membership.
*/
data object Invite : RoomListFilter
/**
* A filter that matches either Group or People rooms.
*/

View file

@ -16,7 +16,9 @@
package io.element.android.libraries.matrix.api.roomlist
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.message.RoomMessage
@ -36,7 +38,7 @@ sealed interface RoomSummary {
data class RoomSummaryDetails(
val roomId: RoomId,
val name: String,
val canonicalAlias: String?,
val canonicalAlias: RoomAlias?,
val isDirect: Boolean,
val avatarUrl: String?,
val lastMessage: RoomMessage?,
@ -49,6 +51,7 @@ data class RoomSummaryDetails(
val hasRoomCall: Boolean,
val isDm: Boolean,
val isFavorite: Boolean,
val currentUserMembership: CurrentUserMembership,
) {
val lastMessageTimestamp = lastMessage?.originServerTs
}

View file

@ -23,7 +23,9 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.coroutine.childScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
import io.element.android.libraries.matrix.api.createroom.RoomPreset
@ -37,6 +39,7 @@ import io.element.android.libraries.matrix.api.pusher.PushersService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.awaitLoaded
@ -460,6 +463,24 @@ class RustMatrixClient(
}
}
@Suppress("TooGenericExceptionThrown")
override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result<RoomId> = withContext(sessionDispatcher) {
runCatching {
// TODO Waiting for SDK to be released
throw Exception("Not implemented")
// client.resolveRoomAlias(roomAlias.value).let(::RoomId)
}
}
@Suppress("TooGenericExceptionThrown")
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias): Result<RoomPreview> = withContext(sessionDispatcher) {
runCatching {
// TODO Waiting for SDK to be released
throw Exception("Not implemented")
// client.getRoomPreview(roomIdOrAlias.identifier).let(RoomPreviewMapper::map)
}
}
override fun syncService(): SyncService = rustSyncService
override fun sessionVerificationService(): SessionVerificationService = verificationService

View file

@ -71,6 +71,7 @@ class RustMatrixClientFactory @Inject constructor(
val syncService = client.syncService()
.withUtdHook(utdTracker)
.withUnifiedInvitesInRoomList(true)
.finish()
RustMatrixClient(

View file

@ -20,8 +20,10 @@ import android.net.Uri
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.MatrixToConverter
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
@ -59,24 +61,24 @@ class DefaultPermalinkParser @Inject constructor(
} else {
val viaParameters = result.via.toImmutableList()
when (val id = result.id) {
is MatrixId.Room -> PermalinkData.RoomIdLink(
roomId = RoomId(id.id),
viaParameters = viaParameters,
)
is MatrixId.User -> PermalinkData.UserLink(
userId = UserId(id.id),
)
is MatrixId.RoomAlias -> PermalinkData.RoomAliasLink(
roomAlias = id.alias,
is MatrixId.Room -> PermalinkData.RoomLink(
roomIdOrAlias = RoomId(id.id).toRoomIdOrAlias(),
viaParameters = viaParameters,
)
is MatrixId.EventOnRoomId -> PermalinkData.EventIdLink(
roomId = RoomId(id.roomId),
is MatrixId.RoomAlias -> PermalinkData.RoomLink(
roomIdOrAlias = RoomAlias(id.alias).toRoomIdOrAlias(),
viaParameters = viaParameters,
)
is MatrixId.EventOnRoomId -> PermalinkData.RoomLink(
roomIdOrAlias = RoomId(id.roomId).toRoomIdOrAlias(),
eventId = EventId(id.eventId),
viaParameters = viaParameters,
)
is MatrixId.EventOnRoomAlias -> PermalinkData.EventIdAliasLink(
roomAlias = id.alias,
is MatrixId.EventOnRoomAlias -> PermalinkData.RoomLink(
roomIdOrAlias = RoomAlias(id.alias).toRoomIdOrAlias(),
eventId = EventId(id.eventId),
viaParameters = viaParameters,
)

View file

@ -16,6 +16,8 @@
package io.element.android.libraries.matrix.impl.room
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
@ -35,7 +37,7 @@ class MatrixRoomInfoMapper(
) {
fun map(rustRoomInfo: RustRoomInfo): MatrixRoomInfo = rustRoomInfo.use {
return MatrixRoomInfo(
id = it.id,
id = RoomId(it.id),
name = it.name,
topic = it.topic,
avatarUrl = it.avatarUrl,
@ -44,7 +46,7 @@ class MatrixRoomInfoMapper(
isSpace = it.isSpace,
isTombstoned = it.isTombstoned,
isFavorite = it.isFavourite,
canonicalAlias = it.canonicalAlias,
canonicalAlias = it.canonicalAlias?.let(::RoomAlias),
alternativeAliases = it.alternativeAliases.toImmutableList(),
currentUserMembership = it.membership.map(),
latestEvent = it.latestEvent?.use(timelineItemMapper::map),

View file

@ -20,6 +20,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.coroutine.childScope
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.TransactionId
@ -205,11 +206,11 @@ class RustMatrixRoom(
override val isEncrypted: Boolean
get() = runCatching { innerRoom.isEncrypted() }.getOrDefault(false)
override val alias: String?
get() = runCatching { innerRoom.canonicalAlias() }.getOrDefault(null)
override val alias: RoomAlias?
get() = runCatching { innerRoom.canonicalAlias()?.let(::RoomAlias) }.getOrDefault(null)
override val alternativeAliases: List<String>
get() = runCatching { innerRoom.alternativeAliases() }.getOrDefault(emptyList())
override val alternativeAliases: List<RoomAlias>
get() = runCatching { innerRoom.alternativeAliases().map { RoomAlias(it) } }.getOrDefault(emptyList())
override val isPublic: Boolean
get() = runCatching { innerRoom.isPublic() }.getOrDefault(false)

View file

@ -25,16 +25,16 @@ import org.matrix.rustcomponents.sdk.RoomMember as RustRoomMember
object RoomMemberMapper {
fun map(roomMember: RustRoomMember): RoomMember = RoomMember(
UserId(roomMember.userId),
roomMember.displayName,
roomMember.avatarUrl,
mapMembership(roomMember.membership),
roomMember.isNameAmbiguous,
roomMember.powerLevel,
roomMember.normalizedPowerLevel,
roomMember.isIgnored,
mapRole(roomMember.suggestedRoleForPowerLevel),
)
userId = UserId(roomMember.userId),
displayName = roomMember.displayName,
avatarUrl = roomMember.avatarUrl,
membership = mapMembership(roomMember.membership),
isNameAmbiguous = roomMember.isNameAmbiguous,
powerLevel = roomMember.powerLevel,
normalizedPowerLevel = roomMember.normalizedPowerLevel,
isIgnored = roomMember.isIgnored,
role = mapRole(roomMember.suggestedRoleForPowerLevel),
)
fun mapRole(role: RoomMemberRole): RoomMember.Role =
when (role) {

View file

@ -16,6 +16,7 @@
package io.element.android.libraries.matrix.impl.roomdirectory
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription
import org.matrix.rustcomponents.sdk.PublicRoomJoinRule
@ -28,7 +29,7 @@ class RoomDescriptionMapper {
name = roomDescription.name,
topic = roomDescription.topic,
avatarUrl = roomDescription.avatarUrl,
alias = roomDescription.alias,
alias = roomDescription.alias?.let(::RoomAlias),
joinRule = when (roomDescription.joinRule) {
PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC
PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK

View file

@ -16,6 +16,7 @@
package io.element.android.libraries.matrix.impl.roomlist
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
@ -25,21 +26,25 @@ val RoomListFilter.predicate
is RoomListFilter.Any -> { _: RoomSummary -> true }
RoomListFilter.None -> { _: RoomSummary -> false }
RoomListFilter.Category.Group -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && !roomSummary.details.isDirect
roomSummary is RoomSummary.Filled && !roomSummary.details.isDirect && !roomSummary.isInvited()
}
RoomListFilter.Category.People -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && roomSummary.details.isDirect
roomSummary is RoomSummary.Filled && roomSummary.details.isDirect && !roomSummary.isInvited()
}
RoomListFilter.Favorite -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && roomSummary.details.isFavorite
roomSummary is RoomSummary.Filled && roomSummary.details.isFavorite && !roomSummary.isInvited()
}
RoomListFilter.Unread -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled &&
!roomSummary.isInvited() &&
(roomSummary.details.numUnreadNotifications > 0 || roomSummary.details.isMarkedUnread)
}
is RoomListFilter.NormalizedMatchRoomName -> { roomSummary: RoomSummary ->
roomSummary is RoomSummary.Filled && roomSummary.details.name.contains(pattern, ignoreCase = true)
}
RoomListFilter.Invite -> { roomSummary: RoomSummary ->
roomSummary.isInvited()
}
}
fun List<RoomSummary>.filter(filter: RoomListFilter): List<RoomSummary> {
@ -55,3 +60,5 @@ fun List<RoomSummary>.filter(filter: RoomListFilter): List<RoomSummary> {
else -> filter(filter.predicate)
}
}
private fun RoomSummary.isInvited() = this is RoomSummary.Filled && this.details.currentUserMembership == CurrentUserMembership.INVITED

View file

@ -16,9 +16,11 @@
package io.element.android.libraries.matrix.impl.roomlist
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
import io.element.android.libraries.matrix.impl.notificationsettings.RoomNotificationSettingsMapper
import io.element.android.libraries.matrix.impl.room.map
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory
import org.matrix.rustcomponents.sdk.RoomInfo
@ -32,7 +34,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
return RoomSummaryDetails(
roomId = RoomId(roomInfo.id),
name = roomInfo.name ?: roomInfo.id,
canonicalAlias = roomInfo.canonicalAlias,
canonicalAlias = roomInfo.canonicalAlias?.let(::RoomAlias),
isDirect = roomInfo.isDirect,
avatarUrl = roomInfo.avatarUrl,
numUnreadMentions = roomInfo.numUnreadMentions.toInt(),
@ -45,6 +47,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
hasRoomCall = roomInfo.hasRoomCall,
isDm = roomInfo.isDirect && roomInfo.activeMembersCount.toLong() == 2L,
isFavorite = roomInfo.isFavourite,
currentUserMembership = roomInfo.membership.map(),
)
}
}

View file

@ -17,6 +17,7 @@
package io.element.android.libraries.matrix.impl.roomlist
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
@ -54,6 +55,11 @@ class RoomListFilterTests {
name = "Room to search"
)
)
private val invitedRoom = aRoomSummaryFilled(
aRoomSummaryDetails(
currentUserMembership = CurrentUserMembership.INVITED
)
)
private val roomSummaries = listOf(
regularRoom,
@ -61,7 +67,8 @@ class RoomListFilterTests {
favoriteRoom,
markedAsUnreadRoom,
unreadNotificationRoom,
roomToSearch
roomToSearch,
invitedRoom
)
@Test
@ -100,6 +107,12 @@ class RoomListFilterTests {
assertThat(roomSummaries.filter(filter)).containsExactly(markedAsUnreadRoom, unreadNotificationRoom)
}
@Test
fun `Room list filter invites`() = runTest {
val filter = RoomListFilter.Invite
assertThat(roomSummaries.filter(filter)).containsExactly(invitedRoom)
}
@Test
fun `Room list filter normalized match room name`() = runTest {
val filter = RoomListFilter.NormalizedMatchRoomName("search")

View file

@ -18,7 +18,9 @@ package io.element.android.libraries.matrix.test
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
@ -31,6 +33,7 @@ import io.element.android.libraries.matrix.api.pusher.PushersService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
@ -48,6 +51,7 @@ import io.element.android.libraries.matrix.test.verification.FakeSessionVerifica
import io.element.android.tests.testutils.simulateLongTask
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
@ -72,6 +76,8 @@ class FakeMatrixClient(
private val encryptionService: FakeEncryptionService = FakeEncryptionService(),
private val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(),
private val accountManagementUrlString: Result<String?> = Result.success(null),
private val resolveRoomAliasResult: (RoomAlias) -> Result<RoomId> = { Result.success(A_ROOM_ID) },
private val getRoomPreviewResult: (RoomIdOrAlias) -> Result<RoomPreview> = { Result.failure(AN_EXCEPTION) },
) : MatrixClient {
var setDisplayNameCalled: Boolean = false
private set
@ -205,6 +211,10 @@ class FakeMatrixClient(
return RoomMembershipObserver()
}
suspend fun emitIgnoreUserList(users: List<UserId>) {
ignoredUsersFlow.emit(users.toImmutableList())
}
// Mocks
fun givenLogoutError(failure: Throwable?) {
@ -271,6 +281,14 @@ class FakeMatrixClient(
return Result.success(Unit)
}
override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result<RoomId> = simulateLongTask {
resolveRoomAliasResult(roomAlias)
}
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias): Result<RoomPreview> = simulateLongTask {
getRoomPreviewResult(roomIdOrAlias)
}
override suspend fun getRecentlyVisitedRooms(): Result<List<RoomId>> {
return Result.success(visitedRoomsId)
}

View file

@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.test
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.SpaceId
@ -50,6 +51,7 @@ val A_THREAD_ID = ThreadId("\$aThreadId")
val A_THREAD_ID_2 = ThreadId("\$aThreadId2")
val AN_EVENT_ID = EventId("\$anEventId")
val AN_EVENT_ID_2 = EventId("\$anEventId2")
val A_ROOM_ALIAS = RoomAlias("#alias1:domain")
val A_TRANSACTION_ID = TransactionId("aTransactionId")
const val A_UNIQUE_ID = "aUniqueId"

View file

@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.test.room
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.TransactionId
@ -73,8 +74,8 @@ class FakeMatrixRoom(
override val topic: String? = null,
override val avatarUrl: String? = null,
override val isEncrypted: Boolean = false,
override val alias: String? = null,
override val alternativeAliases: List<String> = emptyList(),
override val alias: RoomAlias? = null,
override val alternativeAliases: List<RoomAlias> = emptyList(),
override val isPublic: Boolean = true,
override val isSpace: Boolean = false,
override val isDirect: Boolean = false,
@ -750,7 +751,7 @@ data class EndPollInvocation(
)
fun aRoomInfo(
id: String = A_ROOM_ID.value,
id: RoomId = A_ROOM_ID,
name: String? = A_ROOM_NAME,
topic: String? = "A topic",
avatarUrl: String? = AN_AVATAR_URL,
@ -759,7 +760,7 @@ fun aRoomInfo(
isSpace: Boolean = false,
isTombstoned: Boolean = false,
isFavorite: Boolean = false,
canonicalAlias: String? = null,
canonicalAlias: RoomAlias? = null,
alternativeAliases: List<String> = emptyList(),
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
latestEvent: EventTimelineItem? = null,

View file

@ -17,8 +17,10 @@
package io.element.android.libraries.matrix.test.room
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.message.RoomMessage
@ -40,6 +42,7 @@ fun aRoomSummaryFilled(
numUnreadMentions: Int = 0,
numUnreadMessages: Int = 0,
notificationMode: RoomNotificationMode? = null,
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
) = RoomSummary.Filled(
aRoomSummaryDetails(
roomId = roomId,
@ -50,6 +53,7 @@ fun aRoomSummaryFilled(
numUnreadMentions = numUnreadMentions,
numUnreadMessages = numUnreadMessages,
notificationMode = notificationMode,
currentUserMembership = currentUserMembership,
)
)
@ -69,10 +73,11 @@ fun aRoomSummaryDetails(
isMarkedUnread: Boolean = false,
notificationMode: RoomNotificationMode? = null,
inviter: RoomMember? = null,
canonicalAlias: String? = null,
canonicalAlias: RoomAlias? = null,
hasRoomCall: Boolean = false,
isDm: Boolean = false,
isFavorite: Boolean = false,
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
) = RoomSummaryDetails(
roomId = roomId,
name = name,
@ -89,6 +94,7 @@ fun aRoomSummaryDetails(
hasRoomCall = hasRoomCall,
isDm = isDm,
isFavorite = isFavorite,
currentUserMembership = currentUserMembership,
)
fun aRoomMessage(

View file

@ -16,6 +16,7 @@
package io.element.android.libraries.matrix.test.roomdirectory
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription
import io.element.android.libraries.matrix.test.A_ROOM_ID
@ -24,7 +25,7 @@ fun aRoomDescription(
roomId: RoomId = A_ROOM_ID,
name: String? = null,
topic: String? = null,
alias: String? = null,
alias: RoomAlias? = null,
avatarUrl: String? = null,
joinRule: RoomDescription.JoinRule = RoomDescription.JoinRule.UNKNOWN,
isWorldReadable: Boolean = true,