Add banner for optional migration to simplified sliding sync (#3429)

* Add banner for optional migration to native sliding sync

- Add `MatrixClient.isNativeSlidingSyncSupported()` and `MatrixClient.isUsingNativeSlidingSync` to check whether the home server supports native sliding sync and we're already using it.
- Add `NativeSlidingSyncMigrationBanner` composable to the `RoomList` screen when the home server supports native sliding sync but the current session is not using it.
- Add an extra logout successful action to the logout flow, create `EnableNativeSlidingSyncUseCase` so it can be used there.

* Update screenshots

* Make sure the sliding sync migration banner has lower priority than the encryption setup ones

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa 2024-09-09 18:13:19 +02:00 committed by GitHub
parent 7549d5f475
commit 67e262fdc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 283 additions and 12 deletions

View file

@ -39,6 +39,7 @@ fun DialogLikeBannerMolecule(
onSubmitClick: () -> Unit,
onDismissClick: (() -> Unit)?,
modifier: Modifier = Modifier,
actionText: String = stringResource(CommonStrings.action_continue),
) {
Box(modifier = modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
Surface(
@ -74,7 +75,7 @@ fun DialogLikeBannerMolecule(
)
Spacer(modifier = Modifier.height(12.dp))
Button(
text = stringResource(CommonStrings.action_continue),
text = actionText,
size = ButtonSize.Medium,
modifier = Modifier.fillMaxWidth(),
onClick = onSubmitClick,

View file

@ -126,4 +126,10 @@ interface MatrixClient : Closeable {
*/
suspend fun getUrl(url: String): Result<String>
suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview>
/** Returns `true` if the home server supports native sliding sync. */
suspend fun isNativeSlidingSyncSupported(): Boolean
/** Returns `true` if the current session is using native sliding sync. */
fun isUsingNativeSlidingSync(): Boolean
}

View file

@ -93,6 +93,7 @@ import org.matrix.rustcomponents.sdk.IgnoredUsersListener
import org.matrix.rustcomponents.sdk.NotificationProcessSetup
import org.matrix.rustcomponents.sdk.PowerLevels
import org.matrix.rustcomponents.sdk.SendQueueRoomErrorListener
import org.matrix.rustcomponents.sdk.SlidingSyncVersion
import org.matrix.rustcomponents.sdk.TaskHandle
import org.matrix.rustcomponents.sdk.use
import timber.log.Timber
@ -528,6 +529,14 @@ class RustMatrixClient(
})
}.buffer(Channel.UNLIMITED)
override suspend fun isNativeSlidingSyncSupported(): Boolean {
return client.availableSlidingSyncVersions().contains(SlidingSyncVersion.Native)
}
override fun isUsingNativeSlidingSync(): Boolean {
return client.session().slidingSyncVersion == SlidingSyncVersion.Native
}
internal fun setDelegate(delegate: RustClientSessionDelegate) {
client.setDelegate(delegate)
}

View file

@ -77,6 +77,8 @@ class FakeMatrixClient(
private val clearCacheLambda: () -> Unit = { lambdaError() },
private val userIdServerNameLambda: () -> String = { lambdaError() },
private val getUrlLambda: (String) -> Result<String> = { lambdaError() },
var isNativeSlidingSyncSupportedLambda: suspend () -> Boolean = { true },
var isUsingNativeSlidingSyncLambda: () -> Boolean = { true },
) : MatrixClient {
var setDisplayNameCalled: Boolean = false
private set
@ -316,4 +318,12 @@ class FakeMatrixClient(
override suspend fun getUrl(url: String): Result<String> {
return getUrlLambda(url)
}
override suspend fun isNativeSlidingSyncSupported(): Boolean {
return isNativeSlidingSyncSupportedLambda()
}
override fun isUsingNativeSlidingSync(): Boolean {
return isUsingNativeSlidingSyncLambda()
}
}

View file

@ -17,4 +17,8 @@ dependencies {
implementation(libs.coroutines.core)
implementation(projects.libraries.matrix.api)
implementation(libs.androidx.datastore.preferences)
testImplementation(projects.libraries.preferences.test)
testImplementation(libs.test.truth)
testImplementation(libs.coroutines.test)
}

View file

@ -0,0 +1,23 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.preferences.api.store
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import javax.inject.Inject
class EnableNativeSlidingSyncUseCase @Inject constructor(
private val appPreferencesStore: AppPreferencesStore,
private val appCoroutineScope: CoroutineScope,
) {
operator fun invoke() {
appCoroutineScope.launch {
appPreferencesStore.setSimplifiedSlidingSyncEnabled(true)
}
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.preferences.api.store
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Test
class EnableNativeSlidingSyncUseCaseTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `ensure that the use case sets the simplified sliding sync enabled flag`() = runTest {
val preferencesStore = InMemoryAppPreferencesStore()
val useCase = EnableNativeSlidingSyncUseCase(preferencesStore, this)
assertThat(preferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()).isFalse()
useCase()
advanceUntilIdle()
assertThat(preferencesStore.isSimplifiedSlidingSyncEnabledFlow().first()).isTrue()
}
}