Merge branch 'develop' into feature/fga/mark_room_as_favorite
This commit is contained in:
commit
a8bc0cb4ca
538 changed files with 4465 additions and 1639 deletions
|
|
@ -55,10 +55,12 @@ import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber
|
|||
import io.element.android.libraries.matrix.impl.room.RustMatrixRoom
|
||||
import io.element.android.libraries.matrix.impl.roomlist.RoomListFactory
|
||||
import io.element.android.libraries.matrix.impl.roomlist.RustRoomListService
|
||||
import io.element.android.libraries.matrix.impl.roomlist.fullRoomWithTimeline
|
||||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.libraries.matrix.impl.sync.RustSyncService
|
||||
import io.element.android.libraries.matrix.impl.usersearch.UserProfileMapper
|
||||
import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper
|
||||
import io.element.android.libraries.matrix.impl.util.SessionDirectoryNameProvider
|
||||
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
|
||||
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
|
|
@ -76,12 +78,12 @@ import kotlinx.coroutines.withTimeout
|
|||
import org.matrix.rustcomponents.sdk.BackupState
|
||||
import org.matrix.rustcomponents.sdk.Client
|
||||
import org.matrix.rustcomponents.sdk.ClientDelegate
|
||||
import org.matrix.rustcomponents.sdk.FilterStateEventType
|
||||
import org.matrix.rustcomponents.sdk.FilterTimelineEventType
|
||||
import org.matrix.rustcomponents.sdk.NotificationProcessSetup
|
||||
import org.matrix.rustcomponents.sdk.PowerLevels
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.StateEventType
|
||||
import org.matrix.rustcomponents.sdk.TaskHandle
|
||||
import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
|
|
@ -133,6 +135,7 @@ class RustMatrixClient(
|
|||
sessionCoroutineScope = sessionCoroutineScope,
|
||||
dispatchers = dispatchers,
|
||||
).apply { start() }
|
||||
private val sessionDirectoryNameProvider = SessionDirectoryNameProvider()
|
||||
|
||||
private val isLoggingOut = AtomicBoolean(false)
|
||||
|
||||
|
|
@ -203,20 +206,20 @@ class RustMatrixClient(
|
|||
|
||||
private val eventFilters = TimelineEventTypeFilter.exclude(
|
||||
listOf(
|
||||
FilterStateEventType.ROOM_ALIASES,
|
||||
FilterStateEventType.ROOM_CANONICAL_ALIAS,
|
||||
FilterStateEventType.ROOM_GUEST_ACCESS,
|
||||
FilterStateEventType.ROOM_HISTORY_VISIBILITY,
|
||||
FilterStateEventType.ROOM_JOIN_RULES,
|
||||
FilterStateEventType.ROOM_PINNED_EVENTS,
|
||||
FilterStateEventType.ROOM_POWER_LEVELS,
|
||||
FilterStateEventType.ROOM_SERVER_ACL,
|
||||
FilterStateEventType.ROOM_TOMBSTONE,
|
||||
FilterStateEventType.SPACE_CHILD,
|
||||
FilterStateEventType.SPACE_PARENT,
|
||||
FilterStateEventType.POLICY_RULE_ROOM,
|
||||
FilterStateEventType.POLICY_RULE_SERVER,
|
||||
FilterStateEventType.POLICY_RULE_USER,
|
||||
StateEventType.ROOM_ALIASES,
|
||||
StateEventType.ROOM_CANONICAL_ALIAS,
|
||||
StateEventType.ROOM_GUEST_ACCESS,
|
||||
StateEventType.ROOM_HISTORY_VISIBILITY,
|
||||
StateEventType.ROOM_JOIN_RULES,
|
||||
StateEventType.ROOM_PINNED_EVENTS,
|
||||
StateEventType.ROOM_POWER_LEVELS,
|
||||
StateEventType.ROOM_SERVER_ACL,
|
||||
StateEventType.ROOM_TOMBSTONE,
|
||||
StateEventType.SPACE_CHILD,
|
||||
StateEventType.SPACE_PARENT,
|
||||
StateEventType.POLICY_RULE_ROOM,
|
||||
StateEventType.POLICY_RULE_SERVER,
|
||||
StateEventType.POLICY_RULE_USER,
|
||||
).map(FilterTimelineEventType::State)
|
||||
)
|
||||
|
||||
|
|
@ -270,12 +273,7 @@ class RustMatrixClient(
|
|||
|
||||
private suspend fun pairOfRoom(roomId: RoomId): Pair<RoomListItem, Room>? {
|
||||
val cachedRoomListItem = innerRoomListService.roomOrNull(roomId.value)
|
||||
val fullRoom = cachedRoomListItem?.let { roomListItem ->
|
||||
if (!roomListItem.isTimelineInitialized()) {
|
||||
roomListItem.initTimeline(eventFilters)
|
||||
}
|
||||
roomListItem.fullRoom()
|
||||
}
|
||||
val fullRoom = cachedRoomListItem?.fullRoomWithTimeline(filter = eventFilters)
|
||||
return if (cachedRoomListItem == null || fullRoom == null) {
|
||||
Timber.d("No room cached for $roomId")
|
||||
null
|
||||
|
|
@ -401,13 +399,12 @@ class RustMatrixClient(
|
|||
}
|
||||
|
||||
override suspend fun getCacheSize(): Long {
|
||||
// Do not use client.userId since it can throw if client has been closed (during clear cache)
|
||||
return baseDirectory.getCacheSize(userID = sessionId.value)
|
||||
return baseDirectory.getCacheSize()
|
||||
}
|
||||
|
||||
override suspend fun clearCache() {
|
||||
close()
|
||||
baseDirectory.deleteSessionDirectory(userID = sessionId.value, deleteCryptoDb = false)
|
||||
baseDirectory.deleteSessionDirectory(deleteCryptoDb = false)
|
||||
}
|
||||
|
||||
override suspend fun logout(ignoreSdkError: Boolean): String? = doLogout(
|
||||
|
|
@ -436,7 +433,7 @@ class RustMatrixClient(
|
|||
}
|
||||
}
|
||||
close()
|
||||
baseDirectory.deleteSessionDirectory(userID = sessionId.value, deleteCryptoDb = true)
|
||||
baseDirectory.deleteSessionDirectory(deleteCryptoDb = true)
|
||||
if (removeSession) {
|
||||
sessionStore.removeSession(sessionId.value)
|
||||
}
|
||||
|
|
@ -482,12 +479,10 @@ class RustMatrixClient(
|
|||
override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver
|
||||
|
||||
private suspend fun File.getCacheSize(
|
||||
userID: String,
|
||||
includeCryptoDb: Boolean = false,
|
||||
): Long = withContext(sessionDispatcher) {
|
||||
// Rust sanitises the user ID replacing invalid characters with an _
|
||||
val sanitisedUserID = userID.replace(":", "_")
|
||||
val sessionDirectory = File(this@getCacheSize, sanitisedUserID)
|
||||
val sessionDirectoryName = sessionDirectoryNameProvider.provides(sessionId)
|
||||
val sessionDirectory = File(this@getCacheSize, sessionDirectoryName)
|
||||
if (includeCryptoDb) {
|
||||
sessionDirectory.getSizeOfFiles()
|
||||
} else {
|
||||
|
|
@ -504,12 +499,10 @@ class RustMatrixClient(
|
|||
}
|
||||
|
||||
private suspend fun File.deleteSessionDirectory(
|
||||
userID: String,
|
||||
deleteCryptoDb: Boolean = false,
|
||||
): Boolean = withContext(sessionDispatcher) {
|
||||
// Rust sanitises the user ID replacing invalid characters with an _
|
||||
val sanitisedUserID = userID.replace(":", "_")
|
||||
val sessionDirectory = File(this@deleteSessionDirectory, sanitisedUserID)
|
||||
val sessionDirectoryName = sessionDirectoryNameProvider.provides(sessionId)
|
||||
val sessionDirectory = File(this@deleteSessionDirectory, sessionDirectoryName)
|
||||
if (deleteCryptoDb) {
|
||||
// Delete the folder and all its content
|
||||
sessionDirectory.deleteRecursively()
|
||||
|
|
|
|||
|
|
@ -31,11 +31,17 @@ fun MessageEventType.map(): MessageLikeEventType = when (this) {
|
|||
MessageEventType.KEY_VERIFICATION_KEY -> MessageLikeEventType.KEY_VERIFICATION_KEY
|
||||
MessageEventType.KEY_VERIFICATION_MAC -> MessageLikeEventType.KEY_VERIFICATION_MAC
|
||||
MessageEventType.KEY_VERIFICATION_DONE -> MessageLikeEventType.KEY_VERIFICATION_DONE
|
||||
MessageEventType.REACTION_SENT -> MessageLikeEventType.REACTION_SENT
|
||||
MessageEventType.REACTION -> MessageLikeEventType.REACTION
|
||||
MessageEventType.ROOM_ENCRYPTED -> MessageLikeEventType.ROOM_ENCRYPTED
|
||||
MessageEventType.ROOM_MESSAGE -> MessageLikeEventType.ROOM_MESSAGE
|
||||
MessageEventType.ROOM_REDACTION -> MessageLikeEventType.ROOM_REDACTION
|
||||
MessageEventType.STICKER -> MessageLikeEventType.STICKER
|
||||
MessageEventType.POLL_END -> MessageLikeEventType.POLL_END
|
||||
MessageEventType.POLL_RESPONSE -> MessageLikeEventType.POLL_RESPONSE
|
||||
MessageEventType.POLL_START -> MessageLikeEventType.POLL_START
|
||||
MessageEventType.UNSTABLE_POLL_END -> MessageLikeEventType.UNSTABLE_POLL_END
|
||||
MessageEventType.UNSTABLE_POLL_RESPONSE -> MessageLikeEventType.UNSTABLE_POLL_RESPONSE
|
||||
MessageEventType.UNSTABLE_POLL_START -> MessageLikeEventType.UNSTABLE_POLL_START
|
||||
}
|
||||
|
||||
fun MessageLikeEventType.map(): MessageEventType = when (this) {
|
||||
|
|
@ -50,9 +56,15 @@ fun MessageLikeEventType.map(): MessageEventType = when (this) {
|
|||
MessageLikeEventType.KEY_VERIFICATION_KEY -> MessageEventType.KEY_VERIFICATION_KEY
|
||||
MessageLikeEventType.KEY_VERIFICATION_MAC -> MessageEventType.KEY_VERIFICATION_MAC
|
||||
MessageLikeEventType.KEY_VERIFICATION_DONE -> MessageEventType.KEY_VERIFICATION_DONE
|
||||
MessageLikeEventType.REACTION_SENT -> MessageEventType.REACTION_SENT
|
||||
MessageLikeEventType.REACTION -> MessageEventType.REACTION
|
||||
MessageLikeEventType.ROOM_ENCRYPTED -> MessageEventType.ROOM_ENCRYPTED
|
||||
MessageLikeEventType.ROOM_MESSAGE -> MessageEventType.ROOM_MESSAGE
|
||||
MessageLikeEventType.ROOM_REDACTION -> MessageEventType.ROOM_REDACTION
|
||||
MessageLikeEventType.STICKER -> MessageEventType.STICKER
|
||||
MessageLikeEventType.POLL_END -> MessageEventType.POLL_END
|
||||
MessageLikeEventType.POLL_RESPONSE -> MessageEventType.POLL_RESPONSE
|
||||
MessageLikeEventType.POLL_START -> MessageEventType.POLL_START
|
||||
MessageLikeEventType.UNSTABLE_POLL_END -> MessageEventType.UNSTABLE_POLL_END
|
||||
MessageLikeEventType.UNSTABLE_POLL_RESPONSE -> MessageEventType.UNSTABLE_POLL_RESPONSE
|
||||
MessageLikeEventType.UNSTABLE_POLL_START -> MessageEventType.UNSTABLE_POLL_START
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.element.android.libraries.core.coroutine.parallelMap
|
|||
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.room.ForwardEventException
|
||||
import io.element.android.libraries.matrix.impl.roomlist.fullRoomWithTimeline
|
||||
import io.element.android.libraries.matrix.impl.roomlist.roomOrNull
|
||||
import io.element.android.libraries.matrix.impl.timeline.runWithTimelineListenerRegistered
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
|
@ -50,7 +51,9 @@ class RoomContentForwarder(
|
|||
) {
|
||||
val content = fromTimeline.getTimelineEventContentByEventId(eventId.value)
|
||||
val targetSlidingSyncRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) }
|
||||
val targetRooms = targetSlidingSyncRooms.mapNotNull { slidingSyncRoom -> slidingSyncRoom.use { it.fullRoom() } }
|
||||
val targetRooms = targetSlidingSyncRooms.map { slidingSyncRoom ->
|
||||
slidingSyncRoom.use { it.fullRoomWithTimeline(null) }
|
||||
}
|
||||
val failedForwardingTo = mutableSetOf<RoomId>()
|
||||
targetRooms.parallelMap { room ->
|
||||
room.use { targetRoom ->
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType
|
|||
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
||||
import io.element.android.libraries.matrix.api.room.tags.RoomNotableTags
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import io.element.android.libraries.matrix.impl.core.toProgressWatcher
|
||||
|
|
@ -53,6 +54,7 @@ import io.element.android.libraries.matrix.impl.room.location.toInner
|
|||
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
|
||||
import io.element.android.libraries.matrix.impl.room.tags.map
|
||||
import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline
|
||||
import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType
|
||||
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
|
||||
import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver
|
||||
import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl
|
||||
|
|
@ -74,6 +76,7 @@ import org.matrix.rustcomponents.sdk.RoomListItem
|
|||
import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation
|
||||
import org.matrix.rustcomponents.sdk.RoomNotableTagsListener
|
||||
import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle
|
||||
import org.matrix.rustcomponents.sdk.TypingNotificationsListener
|
||||
import org.matrix.rustcomponents.sdk.WidgetCapabilities
|
||||
import org.matrix.rustcomponents.sdk.WidgetCapabilitiesProvider
|
||||
import org.matrix.rustcomponents.sdk.messageEventContentFromHtml
|
||||
|
|
@ -115,6 +118,7 @@ class RustMatrixRoom(
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
override val notableTagsFlow: Flow<RoomNotableTags> = mxCallbackFlow {
|
||||
innerRoom.subscribeToNotableTags(object : RoomNotableTagsListener {
|
||||
override fun call(notableTags: RustRoomNotableTags) {
|
||||
|
|
@ -123,6 +127,22 @@ class RustMatrixRoom(
|
|||
})
|
||||
}
|
||||
|
||||
override val roomTypingMembersFlow: Flow<List<UserId>> = mxCallbackFlow {
|
||||
launch {
|
||||
val initial = emptyList<UserId>()
|
||||
channel.trySend(initial)
|
||||
}
|
||||
innerRoom.subscribeToTypingNotifications(object : TypingNotificationsListener {
|
||||
override fun call(typingUserIds: List<String>) {
|
||||
channel.trySend(
|
||||
typingUserIds
|
||||
.filter { it != sessionData.userId }
|
||||
.map(::UserId)
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Create a dispatcher for all room methods...
|
||||
private val roomDispatcher = coroutineDispatchers.io.limitedParallelism(32)
|
||||
|
||||
|
|
@ -441,6 +461,22 @@ class RustMatrixRoom(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun markAsRead(receiptType: ReceiptType?): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
if (receiptType != null) {
|
||||
innerRoom.markAsReadAndSendReadReceipt(receiptType.toRustReceiptType())
|
||||
} else {
|
||||
innerRoom.markAsRead()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun markAsUnread(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
innerRoom.markAsUnread()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sendLocation(
|
||||
body: String,
|
||||
geoUri: String,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.roomlist
|
|||
|
||||
import io.element.android.libraries.matrix.api.roomlist.DynamicRoomList
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -28,7 +29,6 @@ import kotlinx.coroutines.flow.launchIn
|
|||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind
|
||||
import org.matrix.rustcomponents.sdk.RoomListLoadingState
|
||||
import org.matrix.rustcomponents.sdk.RoomList as InnerRoomList
|
||||
import org.matrix.rustcomponents.sdk.RoomListService as InnerRoomListService
|
||||
|
|
@ -44,7 +44,7 @@ internal class RoomListFactory(
|
|||
*/
|
||||
fun createRoomList(
|
||||
pageSize: Int,
|
||||
initialFilter: DynamicRoomList.Filter = DynamicRoomList.Filter.All,
|
||||
initialFilter: RoomListFilter = RoomListFilter.all(),
|
||||
innerProvider: suspend () -> InnerRoomList
|
||||
): DynamicRoomList {
|
||||
val loadingStateFlow: MutableStateFlow<RoomList.LoadingState> = MutableStateFlow(RoomList.LoadingState.NotLoaded)
|
||||
|
|
@ -91,7 +91,7 @@ internal class RoomListFactory(
|
|||
private class RustDynamicRoomList(
|
||||
override val summaries: MutableStateFlow<List<RoomSummary>>,
|
||||
override val loadingState: MutableStateFlow<RoomList.LoadingState>,
|
||||
override val currentFilter: MutableStateFlow<DynamicRoomList.Filter>,
|
||||
override val currentFilter: MutableStateFlow<RoomListFilter>,
|
||||
override val loadedPages: MutableStateFlow<Int>,
|
||||
private val dynamicEvents: MutableSharedFlow<RoomListDynamicEvents>,
|
||||
private val processor: RoomSummaryListProcessor,
|
||||
|
|
@ -101,7 +101,7 @@ private class RustDynamicRoomList(
|
|||
processor.rebuildRoomSummaries()
|
||||
}
|
||||
|
||||
override suspend fun updateFilter(filter: DynamicRoomList.Filter) {
|
||||
override suspend fun updateFilter(filter: RoomListFilter) {
|
||||
currentFilter.emit(filter)
|
||||
val filterEvent = RoomListDynamicEvents.SetFilter(filter.toRustFilter())
|
||||
dynamicEvents.emit(filterEvent)
|
||||
|
|
@ -124,12 +124,3 @@ private fun RoomListLoadingState.toLoadingState(): RoomList.LoadingState {
|
|||
RoomListLoadingState.NotLoaded -> RoomList.LoadingState.NotLoaded
|
||||
}
|
||||
}
|
||||
|
||||
private fun DynamicRoomList.Filter.toRustFilter(): RoomListEntriesDynamicFilterKind {
|
||||
return when (this) {
|
||||
DynamicRoomList.Filter.All -> RoomListEntriesDynamicFilterKind.All
|
||||
is DynamicRoomList.Filter.NormalizedMatchRoomName -> RoomListEntriesDynamicFilterKind.NormalizedMatchRoomName(this.pattern)
|
||||
DynamicRoomList.Filter.None -> RoomListEntriesDynamicFilterKind.None
|
||||
DynamicRoomList.Filter.AllNonLeft -> RoomListEntriesDynamicFilterKind.AllNonLeft
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.impl.roomlist
|
||||
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind
|
||||
import org.matrix.rustcomponents.sdk.RoomListFilterCategory
|
||||
|
||||
fun RoomListFilter.toRustFilter(): RoomListEntriesDynamicFilterKind {
|
||||
return when (this) {
|
||||
is RoomListFilter.All -> RoomListEntriesDynamicFilterKind.All(filters.map { it.toRustFilter() })
|
||||
is RoomListFilter.Any -> RoomListEntriesDynamicFilterKind.Any(filters.map { it.toRustFilter() })
|
||||
RoomListFilter.Category.Group -> RoomListEntriesDynamicFilterKind.Category(RoomListFilterCategory.GROUP)
|
||||
RoomListFilter.Category.People -> RoomListEntriesDynamicFilterKind.Category(RoomListFilterCategory.PEOPLE)
|
||||
is RoomListFilter.FuzzyMatchRoomName -> RoomListEntriesDynamicFilterKind.FuzzyMatchRoomName(pattern)
|
||||
RoomListFilter.NonLeft -> RoomListEntriesDynamicFilterKind.NonLeft
|
||||
RoomListFilter.None -> RoomListEntriesDynamicFilterKind.None
|
||||
is RoomListFilter.NormalizedMatchRoomName -> RoomListEntriesDynamicFilterKind.NormalizedMatchRoomName(pattern)
|
||||
RoomListFilter.Unread -> RoomListEntriesDynamicFilterKind.Unread
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.impl.roomlist
|
||||
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomListItem
|
||||
import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter
|
||||
|
||||
/** Returns a `Room` with an initialized timeline using the given [filter]. */
|
||||
suspend fun RoomListItem.fullRoomWithTimeline(filter: TimelineEventTypeFilter? = null): Room {
|
||||
if (!isTimelineInitialized()) {
|
||||
initTimeline(filter)
|
||||
}
|
||||
return fullRoom()
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
|
|||
numUnreadMentions = roomInfo.numUnreadMentions.toInt(),
|
||||
numUnreadMessages = roomInfo.numUnreadMessages.toInt(),
|
||||
numUnreadNotifications = roomInfo.numUnreadNotifications.toInt(),
|
||||
isMarkedUnread = roomInfo.isMarkedUnread,
|
||||
lastMessage = latestRoomMessage,
|
||||
inviter = roomInfo.inviter?.let(RoomMemberMapper::map),
|
||||
userDefinedNotificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package io.element.android.libraries.matrix.impl.roomlist
|
|||
|
||||
import io.element.android.libraries.matrix.api.roomlist.DynamicRoomList
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomList
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||
import io.element.android.libraries.matrix.api.roomlist.loadAllIncrementally
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -45,7 +46,7 @@ internal class RustRoomListService(
|
|||
) : RoomListService {
|
||||
override val allRooms: DynamicRoomList = roomListFactory.createRoomList(
|
||||
pageSize = DEFAULT_PAGE_SIZE,
|
||||
initialFilter = DynamicRoomList.Filter.AllNonLeft,
|
||||
initialFilter = RoomListFilter.all(RoomListFilter.NonLeft),
|
||||
) {
|
||||
innerRoomListService.allRooms()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelin
|
|||
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.DmBeginningTimelineProcessor
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.FilterHiddenStateEventsProcessor
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
|
|
@ -84,8 +83,6 @@ class RustMatrixTimeline(
|
|||
dispatcher = dispatcher,
|
||||
)
|
||||
|
||||
private val filterHiddenStateEventsProcessor = FilterHiddenStateEventsProcessor()
|
||||
|
||||
private val dmBeginningTimelineProcessor = DmBeginningTimelineProcessor()
|
||||
|
||||
private val timelineItemFactory = MatrixTimelineItemMapper(
|
||||
|
|
@ -109,7 +106,6 @@ class RustMatrixTimeline(
|
|||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val timelineItems: Flow<List<MatrixTimelineItem>> = _timelineItems
|
||||
.mapLatest { items -> encryptedHistoryPostProcessor.process(items) }
|
||||
.mapLatest { items -> filterHiddenStateEventsProcessor.process(items) }
|
||||
.mapLatest { items ->
|
||||
dmBeginningTimelineProcessor.process(
|
||||
items = items,
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* 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.impl.timeline.postprocessor
|
||||
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
|
||||
|
||||
/**
|
||||
* This class is used to filter out 'hidden' state events from the timeline.
|
||||
*/
|
||||
class FilterHiddenStateEventsProcessor {
|
||||
fun process(items: List<MatrixTimelineItem>): List<MatrixTimelineItem> {
|
||||
return items.filter { item ->
|
||||
when (item) {
|
||||
is MatrixTimelineItem.Event -> {
|
||||
when (val content = item.event.content) {
|
||||
// If it's a state event, make sure it's visible
|
||||
is StateContent -> content.isVisibleInTimeline()
|
||||
// We can display any other event
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
is MatrixTimelineItem.Virtual -> true
|
||||
is MatrixTimelineItem.Other -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.impl.util
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
class SessionDirectoryNameProvider {
|
||||
// Rust sanitises the user ID replacing invalid characters with an _
|
||||
fun provides(sessionId: SessionId): String {
|
||||
return sessionId.value.replace(":", "_")
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ import javax.inject.Inject
|
|||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultCallWidgetSettingsProvider @Inject constructor() : CallWidgetSettingsProvider {
|
||||
override fun provide(baseUrl: String, widgetId: String): MatrixWidgetSettings {
|
||||
override fun provide(baseUrl: String, widgetId: String, encrypted: Boolean): MatrixWidgetSettings {
|
||||
val options = VirtualElementCallWidgetOptions(
|
||||
elementCallUrl = baseUrl,
|
||||
widgetId = widgetId,
|
||||
|
|
@ -40,7 +40,7 @@ class DefaultCallWidgetSettingsProvider @Inject constructor() : CallWidgetSettin
|
|||
confineToRoom = true,
|
||||
font = null,
|
||||
analyticsId = null,
|
||||
encryption = EncryptionSystem.PerParticipantKeys,
|
||||
encryption = if (encrypted) EncryptionSystem.PerParticipantKeys else EncryptionSystem.Unencrypted,
|
||||
)
|
||||
val rustWidgetSettings = newVirtualElementCallWidget(options)
|
||||
return MatrixWidgetSettings.fromRustWidgetSettings(rustWidgetSettings)
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* 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.impl.timeline.postprocessor
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
|
||||
import org.junit.Test
|
||||
|
||||
class FilterHiddenStateEventsProcessorTest {
|
||||
@Test
|
||||
fun test() {
|
||||
val items = listOf(
|
||||
// These are visible because they're not state events
|
||||
MatrixTimelineItem.Other,
|
||||
MatrixTimelineItem.Virtual("virtual", VirtualTimelineItem.ReadMarker),
|
||||
MatrixTimelineItem.Event("event", anEventTimelineItem()),
|
||||
// These are visible state events
|
||||
MatrixTimelineItem.Event("m.room.avatar", anEventTimelineItem(content = StateContent("", OtherState.RoomAvatar("")))),
|
||||
MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(content = StateContent("", OtherState.RoomCreate))),
|
||||
MatrixTimelineItem.Event("m.room.encrypted", anEventTimelineItem(content = StateContent("", OtherState.RoomEncryption))),
|
||||
MatrixTimelineItem.Event("m.room.name", anEventTimelineItem(content = StateContent("", OtherState.RoomName("")))),
|
||||
MatrixTimelineItem.Event("m.room.third_party_invite", anEventTimelineItem(content = StateContent("", OtherState.RoomThirdPartyInvite("")))),
|
||||
MatrixTimelineItem.Event("m.room.topic", anEventTimelineItem(content = StateContent("", OtherState.RoomTopic("")))),
|
||||
MatrixTimelineItem.Event("m.room.custom", anEventTimelineItem(content = StateContent("", OtherState.Custom("")))),
|
||||
// These ones are hidden
|
||||
MatrixTimelineItem.Event("m.room.aliases", anEventTimelineItem(content = StateContent("", OtherState.RoomAliases))),
|
||||
MatrixTimelineItem.Event("m.room.canonical_alias", anEventTimelineItem(content = StateContent("", OtherState.RoomCanonicalAlias))),
|
||||
MatrixTimelineItem.Event("m.room.guest_access", anEventTimelineItem(content = StateContent("", OtherState.RoomGuestAccess))),
|
||||
MatrixTimelineItem.Event("m.room.history_visibility", anEventTimelineItem(content = StateContent("", OtherState.RoomHistoryVisibility))),
|
||||
MatrixTimelineItem.Event("m.room.join_rules", anEventTimelineItem(content = StateContent("", OtherState.RoomJoinRules))),
|
||||
MatrixTimelineItem.Event("m.room.pinned_events", anEventTimelineItem(content = StateContent("", OtherState.RoomPinnedEvents))),
|
||||
MatrixTimelineItem.Event("m.room.power_levels", anEventTimelineItem(content = StateContent("", OtherState.RoomPowerLevels))),
|
||||
MatrixTimelineItem.Event("m.room.server_acl", anEventTimelineItem(content = StateContent("", OtherState.RoomServerAcl))),
|
||||
MatrixTimelineItem.Event("m.room.tombstone", anEventTimelineItem(content = StateContent("", OtherState.RoomTombstone))),
|
||||
MatrixTimelineItem.Event("m.space.child", anEventTimelineItem(content = StateContent("", OtherState.SpaceChild))),
|
||||
MatrixTimelineItem.Event("m.space.parent", anEventTimelineItem(content = StateContent("", OtherState.SpaceParent))),
|
||||
MatrixTimelineItem.Event("m.room.policy.rule.room", anEventTimelineItem(content = StateContent("", OtherState.PolicyRuleRoom))),
|
||||
MatrixTimelineItem.Event("m.room.policy.rule.server", anEventTimelineItem(content = StateContent("", OtherState.PolicyRuleServer))),
|
||||
MatrixTimelineItem.Event("m.room.policy.rule.user", anEventTimelineItem(content = StateContent("", OtherState.PolicyRuleUser))),
|
||||
)
|
||||
|
||||
val expected = listOf(
|
||||
MatrixTimelineItem.Other,
|
||||
MatrixTimelineItem.Virtual("virtual", VirtualTimelineItem.ReadMarker),
|
||||
MatrixTimelineItem.Event("event", anEventTimelineItem()),
|
||||
MatrixTimelineItem.Event("m.room.avatar", anEventTimelineItem(content = StateContent("", OtherState.RoomAvatar("")))),
|
||||
MatrixTimelineItem.Event("m.room.create", anEventTimelineItem(content = StateContent("", OtherState.RoomCreate))),
|
||||
MatrixTimelineItem.Event("m.room.encrypted", anEventTimelineItem(content = StateContent("", OtherState.RoomEncryption))),
|
||||
MatrixTimelineItem.Event("m.room.name", anEventTimelineItem(content = StateContent("", OtherState.RoomName("")))),
|
||||
MatrixTimelineItem.Event("m.room.third_party_invite", anEventTimelineItem(content = StateContent("", OtherState.RoomThirdPartyInvite("")))),
|
||||
MatrixTimelineItem.Event("m.room.topic", anEventTimelineItem(content = StateContent("", OtherState.RoomTopic("")))),
|
||||
MatrixTimelineItem.Event("m.room.custom", anEventTimelineItem(content = StateContent("", OtherState.Custom("")))),
|
||||
)
|
||||
|
||||
val processor = FilterHiddenStateEventsProcessor()
|
||||
|
||||
assertThat(processor.process(items)).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue