Suggestion for room alias.

Rename `Mention` to `IntentionalMention` for clarity
Remove dead code, there is no intentional mention for Room or RoomAlias.
Rename `IntentionalMention.AtRoom` to `IntentionalMention.Room` to match Rust naming
This commit is contained in:
Benoit Marty 2024-08-21 14:09:29 +02:00
parent 4385a7779c
commit 4b8985e501
34 changed files with 399 additions and 222 deletions

View file

@ -25,6 +25,5 @@ interface PermalinkBuilder {
}
sealed class PermalinkBuilderError : Throwable() {
data object InvalidUserId : PermalinkBuilderError()
data object InvalidRoomAlias : PermalinkBuilderError()
data object InvalidData : PermalinkBuilderError()
}

View file

@ -16,12 +16,9 @@
package io.element.android.libraries.matrix.api.room
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
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: RoomAlias?) : Mention
sealed interface IntentionalMention {
data class User(val userId: UserId) : IntentionalMention
data object Room : IntentionalMention
}

View file

@ -129,9 +129,9 @@ interface MatrixRoom : Closeable {
suspend fun userAvatarUrl(userId: UserId): Result<String?>
suspend fun sendMessage(body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit>
suspend fun sendMessage(body: String, htmlBody: String?, intentionalMentions: List<IntentionalMention>): Result<Unit>
suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit>
suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, intentionalMentions: List<IntentionalMention>): Result<Unit>
suspend fun sendImage(
file: File,

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaUploadHandler
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.item.event.InReplyTo
import kotlinx.coroutines.flow.Flow
@ -52,15 +52,24 @@ interface Timeline : AutoCloseable {
fun paginationStatus(direction: PaginationDirection): StateFlow<PaginationStatus>
val timelineItems: Flow<List<MatrixTimelineItem>>
suspend fun sendMessage(body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit>
suspend fun sendMessage(
body: String,
htmlBody: String?,
intentionalMentions: List<IntentionalMention>,
): Result<Unit>
suspend fun editMessage(originalEventId: EventId?, transactionId: TransactionId?, body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit>
suspend fun editMessage(
originalEventId: EventId?,
transactionId: TransactionId?,
body: String, htmlBody: String?,
intentionalMentions: List<IntentionalMention>,
): Result<Unit>
suspend fun replyMessage(
eventId: EventId,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
fromNotification: Boolean = false,
): Result<Unit>

View file

@ -31,7 +31,7 @@ import javax.inject.Inject
class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder {
override fun permalinkForUser(userId: UserId): Result<String> {
if (!MatrixPatterns.isUserId(userId.value)) {
return Result.failure(PermalinkBuilderError.InvalidUserId)
return Result.failure(PermalinkBuilderError.InvalidData)
}
return runCatching {
matrixToUserPermalink(userId.value)
@ -40,7 +40,7 @@ class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder {
override fun permalinkForRoomAlias(roomAlias: RoomAlias): Result<String> {
if (!MatrixPatterns.isRoomAlias(roomAlias.value)) {
return Result.failure(PermalinkBuilderError.InvalidRoomAlias)
return Result.failure(PermalinkBuilderError.InvalidData)
}
return runCatching {
matrixToRoomAliasPermalink(roomAlias.value)

View file

@ -16,11 +16,11 @@
package io.element.android.libraries.matrix.impl.room
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.IntentionalMention
import org.matrix.rustcomponents.sdk.Mentions
fun List<Mention>.map(): Mentions {
val hasAtRoom = any { it is Mention.AtRoom }
val userIds = filterIsInstance<Mention.User>().map { it.userId.value }
return Mentions(userIds, hasAtRoom)
fun List<IntentionalMention>.map(): Mentions {
val hasRoom = any { it is IntentionalMention.Room }
val userIds = filterIsInstance<IntentionalMention.User>().map { it.userId.value }
return Mentions(userIds, hasRoom)
}

View file

@ -33,11 +33,11 @@ import io.element.android.libraries.matrix.api.media.MediaUploadHandler
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.IntentionalMention
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.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.StateEventType
@ -340,16 +340,21 @@ class RustMatrixRoom(
}
}
override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit> = withContext(roomDispatcher) {
override suspend fun editMessage(
eventId: EventId,
body: String,
htmlBody: String?,
intentionalMentions: List<IntentionalMention>
): Result<Unit> = withContext(roomDispatcher) {
runCatching {
MessageEventContent.from(body, htmlBody, mentions).use { newContent ->
MessageEventContent.from(body, htmlBody, intentionalMentions).use { newContent ->
innerRoom.edit(eventId.value, newContent)
}
}
}
override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit> {
return liveTimeline.sendMessage(body, htmlBody, mentions)
override suspend fun sendMessage(body: String, htmlBody: String?, intentionalMentions: List<IntentionalMention>): Result<Unit> {
return liveTimeline.sendMessage(body, htmlBody, intentionalMentions)
}
override suspend fun leave(): Result<Unit> = withContext(roomDispatcher) {

View file

@ -26,8 +26,8 @@ import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaUploadHandler
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
@ -263,8 +263,12 @@ class RustTimeline(
}
}
override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List<Mention>): Result<Unit> = withContext(dispatcher) {
MessageEventContent.from(body, htmlBody, mentions).use { content ->
override suspend fun sendMessage(
body: String,
htmlBody: String?,
intentionalMentions: List<IntentionalMention>,
): Result<Unit> = withContext(dispatcher) {
MessageEventContent.from(body, htmlBody, intentionalMentions).use { content ->
runCatching<Unit> {
inner.send(content)
}
@ -284,13 +288,13 @@ class RustTimeline(
transactionId: TransactionId?,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
): Result<Unit> =
withContext(dispatcher) {
runCatching<Unit> {
getEventTimelineItem(originalEventId, transactionId).use { item ->
inner.edit(
newContent = MessageEventContent.from(body, htmlBody, mentions),
newContent = MessageEventContent.from(body, htmlBody, intentionalMentions),
item = item,
)
}
@ -301,11 +305,11 @@ class RustTimeline(
eventId: EventId,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
fromNotification: Boolean,
): Result<Unit> = withContext(dispatcher) {
runCatching {
val msg = MessageEventContent.from(body, htmlBody, mentions)
val msg = MessageEventContent.from(body, htmlBody, intentionalMentions)
inner.sendReply(msg, eventId.value)
}
}

View file

@ -16,7 +16,7 @@
package io.element.android.libraries.matrix.impl.util
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.impl.room.map
import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation
import org.matrix.rustcomponents.sdk.messageEventContentFromHtml
@ -26,11 +26,11 @@ import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown
* Creates a [RoomMessageEventContentWithoutRelation] from a body, an html body and a list of mentions.
*/
object MessageEventContent {
fun from(body: String, htmlBody: String?, mentions: List<Mention>): RoomMessageEventContentWithoutRelation {
fun from(body: String, htmlBody: String?, intentionalMentions: List<IntentionalMention>): RoomMessageEventContentWithoutRelation {
return if (htmlBody != null) {
messageEventContentFromHtml(body, htmlBody)
} else {
messageEventContentFromMarkdown(body)
}.withMentions(mentions.map())
}.withMentions(intentionalMentions.map())
}
}

View file

@ -19,10 +19,11 @@ package io.element.android.libraries.matrix.test.permalink
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.permalink.PermalinkBuilder
import io.element.android.tests.testutils.lambda.lambdaError
class FakePermalinkBuilder(
private val permalinkForUserLambda: (UserId) -> Result<String> = { Result.failure(Exception("Not implemented")) },
private val permalinkForRoomAliasLambda: (RoomAlias) -> Result<String> = { Result.failure(Exception("Not implemented")) },
private val permalinkForUserLambda: (UserId) -> Result<String> = { lambdaError() },
private val permalinkForRoomAliasLambda: (RoomAlias) -> Result<String> = { lambdaError() },
) : PermalinkBuilder {
override fun permalinkForUser(userId: UserId): Result<String> {
return permalinkForUserLambda(userId)

View file

@ -35,7 +35,7 @@ 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.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.MatrixRoomNotificationSettingsState
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
@ -105,8 +105,8 @@ class FakeMatrixRoom(
private val setTopicResult: (String) -> Result<Unit> = { lambdaError() },
private val updateAvatarResult: (String, ByteArray) -> Result<Unit> = { _, _ -> lambdaError() },
private val removeAvatarResult: () -> Result<Unit> = { lambdaError() },
private val editMessageLambda: (EventId, String, String?, List<Mention>) -> Result<Unit> = { _, _, _, _ -> lambdaError() },
private val sendMessageResult: (String, String?, List<Mention>) -> Result<Unit> = { _, _, _ -> lambdaError() },
private val editMessageLambda: (EventId, String, String?, List<IntentionalMention>) -> Result<Unit> = { _, _, _, _ -> lambdaError() },
private val sendMessageResult: (String, String?, List<IntentionalMention>) -> Result<Unit> = { _, _, _ -> lambdaError() },
private val updateUserRoleResult: () -> Result<Unit> = { lambdaError() },
private val toggleReactionResult: (String, EventId) -> Result<Unit> = { _, _ -> lambdaError() },
private val retrySendMessageResult: (TransactionId) -> Result<Unit> = { lambdaError() },
@ -222,12 +222,12 @@ class FakeMatrixRoom(
return updateUserRoleResult()
}
override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List<Mention>) = simulateLongTask {
editMessageLambda(eventId, body, htmlBody, mentions)
override suspend fun editMessage(eventId: EventId, body: String, htmlBody: String?, intentionalMentions: List<IntentionalMention>) = simulateLongTask {
editMessageLambda(eventId, body, htmlBody, intentionalMentions)
}
override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List<Mention>) = simulateLongTask {
sendMessageResult(body, htmlBody, mentions)
override suspend fun sendMessage(body: String, htmlBody: String?, intentionalMentions: List<IntentionalMention>) = simulateLongTask {
sendMessageResult(body, htmlBody, intentionalMentions)
}
override suspend fun toggleReaction(emoji: String, eventId: EventId): Result<Unit> {

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.MediaUploadHandler
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.Mention
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.ReceiptType
@ -60,7 +60,7 @@ class FakeTimeline(
var sendMessageLambda: (
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
) -> Result<Unit> = { _, _, _ ->
Result.success(Unit)
}
@ -68,8 +68,8 @@ class FakeTimeline(
override suspend fun sendMessage(
body: String,
htmlBody: String?,
mentions: List<Mention>,
): Result<Unit> = sendMessageLambda(body, htmlBody, mentions)
intentionalMentions: List<IntentionalMention>,
): Result<Unit> = sendMessageLambda(body, htmlBody, intentionalMentions)
var redactEventLambda: (eventId: EventId?, transactionId: TransactionId?, reason: String?) -> Result<Boolean> = { _, _, _ ->
Result.success(true)
@ -86,7 +86,7 @@ class FakeTimeline(
transactionId: TransactionId?,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
) -> Result<Unit> = { _, _, _, _, _ ->
Result.success(Unit)
}
@ -96,20 +96,20 @@ class FakeTimeline(
transactionId: TransactionId?,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
): Result<Unit> = editMessageLambda(
originalEventId,
transactionId,
body,
htmlBody,
mentions
intentionalMentions
)
var replyMessageLambda: (
eventId: EventId,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
fromNotification: Boolean,
) -> Result<Unit> = { _, _, _, _, _ ->
Result.success(Unit)
@ -119,13 +119,13 @@ class FakeTimeline(
eventId: EventId,
body: String,
htmlBody: String?,
mentions: List<Mention>,
intentionalMentions: List<IntentionalMention>,
fromNotification: Boolean,
): Result<Unit> = replyMessageLambda(
eventId,
body,
htmlBody,
mentions,
intentionalMentions,
fromNotification,
)