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

@ -18,7 +18,3 @@ package io.element.android.libraries.deeplink
internal const val SCHEME = "elementx"
internal const val HOST = "open"
object DeepLinkPaths {
const val INVITE_LIST = "invites"
}

View file

@ -36,13 +36,4 @@ class DeepLinkCreator @Inject constructor() {
}
}
}
fun inviteList(sessionId: SessionId): String {
return buildString {
append("$SCHEME://$HOST/")
append(sessionId.value)
append("/")
append(DeepLinkPaths.INVITE_LIST)
}
}
}

View file

@ -29,7 +29,4 @@ sealed interface DeeplinkData {
/** The target is a room, with the given [sessionId], [roomId] and optionally a [threadId]. */
data class Room(override val sessionId: SessionId, val roomId: RoomId, val threadId: ThreadId?) : DeeplinkData
/** The target is the invites list, with the given [sessionId]. */
data class InviteList(override val sessionId: SessionId) : DeeplinkData
}

View file

@ -39,7 +39,6 @@ class DeeplinkParser @Inject constructor() {
return when (val screenPathComponent = pathBits.elementAtOrNull(1)) {
null -> DeeplinkData.Root(sessionId)
DeepLinkPaths.INVITE_LIST -> DeeplinkData.InviteList(sessionId)
else -> {
val roomId = screenPathComponent.let(::RoomId)
val threadId = pathBits.elementAtOrNull(2)?.let(::ThreadId)

View file

@ -33,11 +33,4 @@ class DeepLinkCreatorTest {
assertThat(sut.room(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID))
.isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId")
}
@Test
fun inviteList() {
val sut = DeepLinkCreator()
assertThat(sut.inviteList(A_SESSION_ID))
.isEqualTo("elementx://open/@alice:server.org/invites")
}
}

View file

@ -36,8 +36,6 @@ class DeeplinkParserTest {
"elementx://open/@alice:server.org/!aRoomId:domain"
const val A_URI_WITH_ROOM_WITH_THREAD =
"elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId"
const val A_URI_FOR_INVITE_LIST =
"elementx://open/@alice:server.org/invites"
}
private val sut = DeeplinkParser()
@ -50,8 +48,6 @@ class DeeplinkParserTest {
.isEqualTo(DeeplinkData.Room(A_SESSION_ID, A_ROOM_ID, null))
assertThat(sut.getFromIntent(createIntent(A_URI_WITH_ROOM_WITH_THREAD)))
.isEqualTo(DeeplinkData.Room(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID))
assertThat(sut.getFromIntent(createIntent(A_URI_FOR_INVITE_LIST)))
.isEqualTo(DeeplinkData.InviteList(A_SESSION_ID))
}
@Test

View file

@ -0,0 +1,37 @@
/*
* 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.designsystem.atomic.atoms
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun RoomPreviewDescriptionAtom(description: String, modifier: Modifier = Modifier) {
Text(
modifier = modifier,
text = description,
style = ElementTheme.typography.fontBodySmRegular,
textAlign = TextAlign.Center,
color = ElementTheme.colors.textSecondary,
maxLines = 3,
overflow = TextOverflow.Ellipsis,
)
}

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.designsystem.atomic.atoms
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun RoomPreviewSubtitleAtom(subtitle: String, modifier: Modifier = Modifier) {
Text(
modifier = modifier,
text = subtitle,
style = ElementTheme.typography.fontBodyLgRegular,
textAlign = TextAlign.Center,
color = ElementTheme.colors.textSecondary,
)
}

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.designsystem.atomic.atoms
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun RoomPreviewTitleAtom(title: String, modifier: Modifier = Modifier) {
Text(
modifier = modifier,
text = title,
style = ElementTheme.typography.fontHeadingMdBold,
textAlign = TextAlign.Center,
color = ElementTheme.colors.textPrimary,
)
}

View file

@ -0,0 +1,74 @@
/*
* 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.designsystem.atomic.molecules
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun RoomPreviewMembersCountMolecule(
memberCount: Long,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier
.background(color = ElementTheme.colors.bgSubtleSecondary, shape = CircleShape)
.widthIn(min = 48.dp)
.padding(start = 2.dp, end = 6.dp, top = 2.dp, bottom = 2.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
Icon(
imageVector = CompoundIcons.UserProfile(),
contentDescription = null,
tint = ElementTheme.colors.iconSecondary,
)
Text(
text = "$memberCount",
style = ElementTheme.typography.fontBodySmMedium,
color = ElementTheme.colors.textSecondary,
)
}
}
@PreviewsDayNight
@Composable
internal fun RoomPreviewMembersCountMoleculePreview() = ElementPreview {
Column(
modifier = Modifier.padding(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
RoomPreviewMembersCountMolecule(memberCount = 1)
RoomPreviewMembersCountMolecule(memberCount = 888)
RoomPreviewMembersCountMolecule(memberCount = 123_456)
}
}

View file

@ -0,0 +1,56 @@
/*
* 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.designsystem.atomic.organisms
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun RoomPreviewOrganism(
avatar: @Composable () -> Unit,
title: @Composable () -> Unit,
subtitle: @Composable () -> Unit,
modifier: Modifier = Modifier,
description: @Composable (() -> Unit)? = null,
memberCount: @Composable (() -> Unit)? = null,
) {
Column(
modifier = modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
avatar()
Spacer(modifier = Modifier.height(16.dp))
title()
Spacer(modifier = Modifier.height(8.dp))
subtitle()
Spacer(modifier = Modifier.height(8.dp))
if (memberCount != null) {
memberCount()
}
Spacer(modifier = Modifier.height(8.dp))
if (description != null) {
description()
}
Spacer(modifier = Modifier.height(24.dp))
}
}

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,

View file

@ -43,7 +43,9 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
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
@ -105,7 +107,7 @@ internal fun SelectedRoomPreview() = ElementPreview {
fun aRoomSummaryDetails(
roomId: RoomId = RoomId("!room:domain"),
name: String = "roomName",
canonicalAlias: String? = null,
canonicalAlias: RoomAlias? = null,
isDirect: Boolean = true,
avatarUrl: String? = null,
lastMessage: RoomMessage? = null,
@ -118,6 +120,7 @@ fun aRoomSummaryDetails(
numUnreadNotifications: Int = 0,
isMarkedUnread: Boolean = false,
isFavorite: Boolean = false,
currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED,
) = RoomSummaryDetails(
roomId = roomId,
name = name,
@ -134,4 +137,5 @@ fun aRoomSummaryDetails(
numUnreadNotifications = numUnreadNotifications,
isMarkedUnread = isMarkedUnread,
isFavorite = isFavorite,
currentUserMembership = currentUserMembership,
)

View file

@ -30,9 +30,4 @@ interface IntentProvider {
roomId: RoomId?,
threadId: ThreadId?,
): Intent
/**
* Provide an intent to start the application on the invite list.
*/
fun getInviteListIntent(sessionId: SessionId): Intent
}

View file

@ -157,7 +157,7 @@ class NotificationCreator @Inject constructor(
// .addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent))
.apply {
// Build the pending intent for when the notification is clicked
setContentIntent(pendingIntentFactory.createInviteListPendingIntent(inviteNotifiableEvent.sessionId))
setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(inviteNotifiableEvent.sessionId, inviteNotifiableEvent.roomId))
if (inviteNotifiableEvent.noisy) {
// Compat

View file

@ -19,7 +19,6 @@ package io.element.android.libraries.push.impl.notifications.factories
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.PendingIntentCompat
import io.element.android.libraries.androidutils.uri.createIgnoredUri
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.core.EventId
@ -128,9 +127,4 @@ class PendingIntentFactory @Inject constructor(
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
}
fun createInviteListPendingIntent(sessionId: SessionId): PendingIntent {
val intent = intentProvider.getInviteListIntent(sessionId)
return PendingIntentCompat.getActivity(context, 0, intent, 0, false)!!
}
}

View file

@ -24,6 +24,4 @@ import io.element.android.libraries.push.impl.intent.IntentProvider
class FakeIntentProvider : IntentProvider {
override fun getViewRoomIntent(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?) = Intent()
override fun getInviteListIntent(sessionId: SessionId) = Intent()
}

View file

@ -18,6 +18,7 @@ package io.element.android.libraries.roomselect.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
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.ui.components.aRoomSummaryDetails
@ -65,6 +66,6 @@ private fun aForwardMessagesRoomList() = persistentListOf(
aRoomSummaryDetails(
roomId = RoomId("!room2:domain"),
name = "Room with alias",
canonicalAlias = "#alias:example.org",
canonicalAlias = RoomAlias("#alias:example.org"),
),
)

View file

@ -243,7 +243,7 @@ private fun RoomSummaryView(
// Alias
summary.canonicalAlias?.let { alias ->
Text(
text = alias,
text = alias.value,
color = ElementTheme.colors.textSecondary,
style = ElementTheme.typography.fontBodySmRegular,
maxLines = 1,

View file

@ -39,8 +39,10 @@ import io.element.android.libraries.designsystem.theme.currentUserMentionPillBac
import io.element.android.libraries.designsystem.theme.currentUserMentionPillText
import io.element.android.libraries.designsystem.theme.mentionPillBackground
import io.element.android.libraries.designsystem.theme.mentionPillText
import io.element.android.libraries.matrix.api.core.RoomAlias
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.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import kotlinx.collections.immutable.persistentListOf
@ -139,8 +141,9 @@ internal fun MentionSpanPreview() {
return when (uriString) {
"https://matrix.to/#/@me:matrix.org" -> PermalinkData.UserLink(UserId("@me:matrix.org"))
"https://matrix.to/#/@other:matrix.org" -> PermalinkData.UserLink(UserId("@other:matrix.org"))
"https://matrix.to/#/#room:matrix.org" -> PermalinkData.RoomAliasLink(
roomAlias = "#room:matrix.org",
"https://matrix.to/#/#room:matrix.org" -> PermalinkData.RoomLink(
roomIdOrAlias = RoomAlias("#room:matrix.org").toRoomIdOrAlias(),
eventId = null,
viaParameters = persistentListOf(),
)
else -> TODO()

View file

@ -18,13 +18,14 @@ package io.element.android.libraries.textcomposer.impl.mentions
import android.graphics.Color
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.RoomAlias
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.PermalinkData
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@ -68,9 +69,8 @@ class MentionSpanProviderTest {
@Test
fun `getting mention span for a room should return a MentionSpan with normal colors`() {
permalinkParser.givenResult(
PermalinkData.RoomAliasLink(
roomAlias = "#room:matrix.org",
viaParameters = persistentListOf(),
PermalinkData.RoomLink(
roomIdOrAlias = RoomAlias("#room:matrix.org").toRoomIdOrAlias(),
)
)
val mentionSpan = mentionSpanProvider.getMentionSpanFor("#room:matrix.org", "https://matrix.to/#/#room:matrix.org")
@ -81,12 +81,11 @@ class MentionSpanProviderTest {
@Test
fun `getting mention span for @room should return a MentionSpan with normal colors`() {
permalinkParser.givenResult(
PermalinkData.RoomAliasLink(
roomAlias = "#",
viaParameters = persistentListOf(),
PermalinkData.RoomLink(
roomIdOrAlias = RoomAlias("#room:matrix.org").toRoomIdOrAlias(),
)
)
val mentionSpan = mentionSpanProvider.getMentionSpanFor("@room", "#")
val mentionSpan = mentionSpanProvider.getMentionSpanFor("@room", "#room:matrix.org")
assertThat(mentionSpan.backgroundColor).isEqualTo(otherColor)
assertThat(mentionSpan.textColor).isEqualTo(otherColor)
}