From b2dce57abe0e860e0eaa758d3716d91b46196a0d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Dec 2024 11:40:53 +0100 Subject: [PATCH 1/3] Add a feature flag for the event cache. --- .../android/libraries/featureflag/api/FeatureFlags.kt | 7 +++++++ .../libraries/matrix/impl/RustMatrixClientFactory.kt | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index 9add32499f..b028978c94 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -161,4 +161,11 @@ enum class FeatureFlags( defaultValue = { buildMeta -> buildMeta.buildType != BuildType.RELEASE }, isFinished = false, ), + EventCache( + key = "feature.event_cache", + title = "Use SDK Event cache", + description = "Warning: you must kill and restart the app for the change to take effect.", + defaultValue = { false }, + isFinished = false, + ), } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index e688452510..d5af4ff67f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -109,9 +109,7 @@ class RustMatrixClientFactory @Inject constructor( .addRootCertificates(userCertificatesProvider.provides()) .autoEnableBackups(true) .autoEnableCrossSigning(true) - // TODO Add a feature flag to enable persistent storage - // See https://github.com/matrix-org/matrix-rust-sdk/pull/4396 - .useEventCachePersistentStorage(false) + .useEventCachePersistentStorage(featureFlagService.isFeatureEnabled(FeatureFlags.EventCache)) .roomKeyRecipientStrategy( strategy = if (featureFlagService.isFeatureEnabled(FeatureFlags.OnlySignedDeviceIsolationMode)) { CollectStrategy.IdentityBasedStrategy From 87de436c98783572a17074cad13a180bd8ad5b41 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Dec 2024 11:58:46 +0100 Subject: [PATCH 2/3] Add a way to clear the cache for a specific room. --- .../roomlist/impl/RoomListContextMenu.kt | 18 ++++++++++++++++++ .../features/roomlist/impl/RoomListEvents.kt | 1 + .../roomlist/impl/RoomListPresenter.kt | 10 +++++++++- .../features/roomlist/impl/RoomListState.kt | 1 + .../RoomListStateContextMenuShownProvider.kt | 1 + .../libraries/matrix/api/room/MatrixRoom.kt | 5 +++++ .../matrix/impl/room/RustMatrixRoom.kt | 6 ++++++ .../matrix/test/room/FakeMatrixRoom.kt | 4 ++++ 8 files changed, 45 insertions(+), 1 deletion(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt index 6ba1d8ed8e..f44f192e77 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContextMenu.kt @@ -61,6 +61,10 @@ fun RoomListContextMenu( onFavoriteChange = { isFavorite -> eventSink(RoomListEvents.SetRoomIsFavorite(contextMenu.roomId, isFavorite)) }, + onClearCacheRoomClick = { + eventSink(RoomListEvents.HideContextMenu) + eventSink(RoomListEvents.ClearCacheOfRoom(contextMenu.roomId)) + }, ) } } @@ -73,6 +77,7 @@ private fun RoomListModalBottomSheetContent( onFavoriteChange: (isFavorite: Boolean) -> Unit, onRoomMarkReadClick: () -> Unit, onRoomMarkUnreadClick: () -> Unit, + onClearCacheRoomClick: () -> Unit, ) { Column( modifier = Modifier.fillMaxWidth() @@ -177,6 +182,18 @@ private fun RoomListModalBottomSheetContent( ), style = ListItemStyle.Destructive, ) + if (contextMenu.eventCacheFeatureFlagEnabled) { + ListItem( + headlineContent = { + Text(text = "Clear cache for this room") + }, + modifier = Modifier.clickable { onClearCacheRoomClick() }, + leadingContent = ListItemContent.Icon( + iconSource = IconSource.Vector(CompoundIcons.Delete()) + ), + style = ListItemStyle.Primary, + ) + } } } @@ -195,5 +212,6 @@ internal fun RoomListModalBottomSheetContentPreview( onRoomSettingsClick = {}, onLeaveRoomClick = {}, onFavoriteChange = {}, + onClearCacheRoomClick = {}, ) } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt index 9a8f2353ba..67c4544aaa 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListEvents.kt @@ -25,4 +25,5 @@ sealed interface RoomListEvents { data class MarkAsRead(val roomId: RoomId) : ContextMenuEvents data class MarkAsUnread(val roomId: RoomId) : ContextMenuEvents data class SetRoomIsFavorite(val roomId: RoomId, val isFavorite: Boolean) : ContextMenuEvents + data class ClearCacheOfRoom(val roomId: RoomId) : ContextMenuEvents } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index a2468c32d0..fdd92e0c44 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -146,6 +146,7 @@ class RoomListPresenter @Inject constructor( AcceptDeclineInviteEvents.DeclineInvite(event.roomListRoomSummary.toInviteData()) ) } + is RoomListEvents.ClearCacheOfRoom -> coroutineScope.clearCacheOfRoom(event.roomId) } } @@ -255,7 +256,8 @@ class RoomListPresenter @Inject constructor( isDm = event.roomListRoomSummary.isDm, isFavorite = event.roomListRoomSummary.isFavorite, markAsUnreadFeatureFlagEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.MarkAsUnread), - hasNewContent = event.roomListRoomSummary.hasNewContent + hasNewContent = event.roomListRoomSummary.hasNewContent, + eventCacheFeatureFlagEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.EventCache), ) contextMenuState.value = initialState @@ -312,6 +314,12 @@ class RoomListPresenter @Inject constructor( } } + private fun CoroutineScope.clearCacheOfRoom(roomId: RoomId) = launch { + client.getRoom(roomId)?.use { room -> + room.clearEventCacheStorage() + } + } + /** * Checks if the user needs to migrate to a native sliding sync version. */ diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt index a6b9673b54..a0a5633165 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt @@ -46,6 +46,7 @@ data class RoomListState( val isDm: Boolean, val isFavorite: Boolean, val markAsUnreadFeatureFlagEnabled: Boolean, + val eventCacheFeatureFlagEnabled: Boolean, val hasNewContent: Boolean, ) : ContextMenu } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateContextMenuShownProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateContextMenuShownProvider.kt index 6b74c7934a..36b951f73c 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateContextMenuShownProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateContextMenuShownProvider.kt @@ -31,4 +31,5 @@ internal fun aContextMenuShown( markAsUnreadFeatureFlagEnabled = true, hasNewContent = hasNewContent, isFavorite = isFavorite, + eventCacheFeatureFlagEnabled = false, ) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 840308af23..45309f5d88 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -232,6 +232,11 @@ interface MatrixRoom : Closeable { */ suspend fun setUnreadFlag(isUnread: Boolean): Result + /** + * Clear the event cache storage for the current room. + */ + suspend fun clearEventCacheStorage(): Result + /** * Share a location message in the room. * diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index c84a37cdc3..f1e2495d60 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -569,6 +569,12 @@ class RustMatrixRoom( } } + override suspend fun clearEventCacheStorage(): Result = withContext(roomDispatcher) { + runCatching { + innerRoom.clearEventCacheStorage() + } + } + override suspend fun kickUser(userId: UserId, reason: String?): Result = withContext(roomDispatcher) { runCatching { innerRoom.kickUser(userId.value, reason) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 41d913b89c..c47f4238b9 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -574,6 +574,10 @@ class FakeMatrixRoom( fun givenRoomMembersState(state: MatrixRoomMembersState) { membersStateFlow.value = state } + + override suspend fun clearEventCacheStorage(): Result { + return Result.success(Unit) + } } fun defaultRoomPowerLevels() = MatrixRoomPowerLevels( From 299de21968a9b0a6ead41c91a0bd04831fcf033b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Dec 2024 17:53:02 +0100 Subject: [PATCH 3/3] Fix tests --- .../android/features/roomlist/impl/RoomListPresenterTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt index 69e9a7d401..ff929bda27 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt @@ -288,6 +288,7 @@ class RoomListPresenterTest { isDm = false, isFavorite = false, markAsUnreadFeatureFlagEnabled = true, + eventCacheFeatureFlagEnabled = false, hasNewContent = false, ) ) @@ -305,6 +306,7 @@ class RoomListPresenterTest { isDm = false, isFavorite = true, markAsUnreadFeatureFlagEnabled = true, + eventCacheFeatureFlagEnabled = false, hasNewContent = false, ) ) @@ -335,6 +337,7 @@ class RoomListPresenterTest { isDm = false, isFavorite = false, markAsUnreadFeatureFlagEnabled = true, + eventCacheFeatureFlagEnabled = false, hasNewContent = false, ) )