Merge develop into feature/fga/permalink_timeline
This commit is contained in:
commit
6808edda86
398 changed files with 2667 additions and 2461 deletions
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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?,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class RustMatrixClientFactory @Inject constructor(
|
|||
|
||||
val syncService = client.syncService()
|
||||
.withUtdHook(utdTracker)
|
||||
.withUnifiedInvitesInRoomList(true)
|
||||
.finish()
|
||||
|
||||
RustMatrixClient(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)!!
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue