Browse Source

Remove the migration screen. #3292

pull/3389/head
Benoit Marty 2 weeks ago
parent
commit
faa2f8108c
  1. 1
      features/preferences/impl/build.gradle.kts
  2. 4
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt
  3. 7
      features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt
  4. 25
      features/roomlist/api/src/main/kotlin/io/element/android/features/roomlist/api/migration/MigrationScreenStore.kt
  5. 1
      features/roomlist/impl/build.gradle.kts
  6. 3
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt
  7. 4
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt
  8. 3
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt
  9. 1
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt
  10. 4
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt
  11. 5
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/di/RoomListModule.kt
  12. 50
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenPresenter.kt
  13. 21
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenState.kt
  14. 55
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenView.kt
  15. 59
      features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/SharedPreferencesMigrationScreenStore.kt
  16. 26
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt
  17. 76
      features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenPresenterTest.kt
  18. 28
      features/roomlist/test/build.gradle.kts
  19. 40
      features/roomlist/test/src/main/kotlin/io/element/android/features/roomlist/impl/migration/InMemoryMigrationScreenStore.kt
  20. 6
      samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt

1
features/preferences/impl/build.gradle.kts

@ -92,7 +92,6 @@ dependencies { @@ -92,7 +92,6 @@ dependencies {
testImplementation(projects.features.rageshake.test)
testImplementation(projects.features.rageshake.impl)
testImplementation(projects.features.logout.test)
testImplementation(projects.features.roomlist.test)
testImplementation(projects.libraries.indicator.impl)
testImplementation(projects.libraries.pushproviders.test)
testImplementation(projects.libraries.fullscreenintent.test)

4
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt

@ -24,7 +24,6 @@ import coil.annotation.ExperimentalCoilApi @@ -24,7 +24,6 @@ import coil.annotation.ExperimentalCoilApi
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.ftue.api.state.FtueService
import io.element.android.features.preferences.impl.DefaultCacheService
import io.element.android.features.roomlist.api.migration.MigrationScreenStore
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.SessionScope
@ -47,7 +46,6 @@ class DefaultClearCacheUseCase @Inject constructor( @@ -47,7 +46,6 @@ class DefaultClearCacheUseCase @Inject constructor(
private val defaultCacheService: DefaultCacheService,
private val okHttpClient: Provider<OkHttpClient>,
private val ftueService: FtueService,
private val migrationScreenStore: MigrationScreenStore,
private val pushService: PushService,
) : ClearCacheUseCase {
override suspend fun invoke() = withContext(coroutineDispatchers.io) {
@ -64,8 +62,6 @@ class DefaultClearCacheUseCase @Inject constructor( @@ -64,8 +62,6 @@ class DefaultClearCacheUseCase @Inject constructor(
context.cacheDir.deleteRecursively()
// Clear some settings
ftueService.reset()
// Clear migration screen store
migrationScreenStore.reset()
// Ensure any error will be displayed again
pushService.setIgnoreRegistrationError(matrixClient.sessionId, false)
// Ensure the app is restarted

7
features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/tasks/DefaultClearCacheUseCaseTest.kt

@ -21,7 +21,6 @@ import app.cash.turbine.test @@ -21,7 +21,6 @@ import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.ftue.test.FakeFtueService
import io.element.android.features.preferences.impl.DefaultCacheService
import io.element.android.features.roomlist.impl.migration.InMemoryMigrationScreenStore
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.push.test.FakePushService
@ -47,10 +46,6 @@ class DefaultClearCacheUseCaseTest { @@ -47,10 +46,6 @@ class DefaultClearCacheUseCaseTest {
val ftueService = FakeFtueService(
resetLambda = resetFtueLambda,
)
val resetMigrationLambda = lambdaRecorder<Unit> { }
val migrationScreenStore = InMemoryMigrationScreenStore(
resetLambda = resetMigrationLambda,
)
val setIgnoreRegistrationErrorLambda = lambdaRecorder<SessionId, Boolean, Unit> { _, _ -> }
val pushService = FakePushService(
setIgnoreRegistrationErrorLambda = setIgnoreRegistrationErrorLambda
@ -62,14 +57,12 @@ class DefaultClearCacheUseCaseTest { @@ -62,14 +57,12 @@ class DefaultClearCacheUseCaseTest {
defaultCacheService = defaultCacheService,
okHttpClient = { OkHttpClient.Builder().build() },
ftueService = ftueService,
migrationScreenStore = migrationScreenStore,
pushService = pushService,
)
defaultCacheService.clearedCacheEventFlow.test {
sut.invoke()
clearCacheLambda.assertions().isCalledOnce()
resetFtueLambda.assertions().isCalledOnce()
resetMigrationLambda.assertions().isCalledOnce()
setIgnoreRegistrationErrorLambda.assertions().isCalledOnce()
.with(value(matrixClient.sessionId), value(false))
assertThat(awaitItem()).isEqualTo(matrixClient.sessionId)

25
features/roomlist/api/src/main/kotlin/io/element/android/features/roomlist/api/migration/MigrationScreenStore.kt

@ -1,25 +0,0 @@ @@ -1,25 +0,0 @@
/*
* Copyright (c) 2023 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.features.roomlist.api.migration
import io.element.android.libraries.matrix.api.core.SessionId
interface MigrationScreenStore {
fun isMigrationScreenNeeded(sessionId: SessionId): Boolean
fun setMigrationScreenShown(sessionId: SessionId)
fun reset()
}

1
features/roomlist/impl/build.gradle.kts

@ -84,7 +84,6 @@ dependencies { @@ -84,7 +84,6 @@ dependencies {
testImplementation(projects.services.analytics.test)
testImplementation(projects.services.toolbox.test)
testImplementation(projects.features.networkmonitor.test)
testImplementation(projects.features.roomlist.test)
testImplementation(projects.tests.testutils)
testImplementation(projects.features.leaveroom.test)
}

3
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt

@ -29,7 +29,6 @@ open class RoomListContentStateProvider : PreviewParameterProvider<RoomListConte @@ -29,7 +29,6 @@ open class RoomListContentStateProvider : PreviewParameterProvider<RoomListConte
aRoomsContentState(summaries = persistentListOf()),
aSkeletonContentState(),
anEmptyContentState(),
aMigrationContentState(),
)
}
@ -43,8 +42,6 @@ internal fun aRoomsContentState( @@ -43,8 +42,6 @@ internal fun aRoomsContentState(
summaries = summaries,
)
internal fun aMigrationContentState() = RoomListContentState.Migration
internal fun aSkeletonContentState() = RoomListContentState.Skeleton(16)
internal fun anEmptyContentState() = RoomListContentState.Empty

4
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt

@ -42,7 +42,6 @@ import io.element.android.features.networkmonitor.api.NetworkMonitor @@ -42,7 +42,6 @@ import io.element.android.features.networkmonitor.api.NetworkMonitor
import io.element.android.features.networkmonitor.api.NetworkStatus
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.migration.MigrationScreenState
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.features.roomlist.impl.search.RoomListSearchEvents
import io.element.android.features.roomlist.impl.search.RoomListSearchState
@ -93,7 +92,6 @@ class RoomListPresenter @Inject constructor( @@ -93,7 +92,6 @@ class RoomListPresenter @Inject constructor(
private val indicatorService: IndicatorService,
private val filtersPresenter: Presenter<RoomListFiltersState>,
private val searchPresenter: Presenter<RoomListSearchState>,
private val migrationScreenPresenter: Presenter<MigrationScreenState>,
private val sessionPreferencesStore: SessionPreferencesStore,
private val analyticsService: AnalyticsService,
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
@ -210,7 +208,6 @@ class RoomListPresenter @Inject constructor( @@ -210,7 +208,6 @@ class RoomListPresenter @Inject constructor(
roomListDataSource.allRooms.collect { value = AsyncData.Success(it) }
}
val loadingState by roomListDataSource.loadingState.collectAsState()
val showMigration = migrationScreenPresenter.present().isMigrating
val showEmpty by remember {
derivedStateOf {
(loadingState as? RoomList.LoadingState.Loaded)?.numberOfRooms == 0
@ -222,7 +219,6 @@ class RoomListPresenter @Inject constructor( @@ -222,7 +219,6 @@ class RoomListPresenter @Inject constructor(
}
}
return when {
showMigration -> RoomListContentState.Migration
showEmpty -> RoomListContentState.Empty
showSkeleton -> RoomListContentState.Skeleton(count = 16)
else -> {

3
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt

@ -43,7 +43,7 @@ data class RoomListState( @@ -43,7 +43,7 @@ data class RoomListState(
val eventSink: (RoomListEvents) -> Unit,
) {
val displayFilters = contentState is RoomListContentState.Rooms
val displayActions = contentState !is RoomListContentState.Migration
val displayActions = true
sealed interface ContextMenu {
data object Hidden : ContextMenu
@ -72,7 +72,6 @@ enum class SecurityBannerState { @@ -72,7 +72,6 @@ enum class SecurityBannerState {
@Immutable
sealed interface RoomListContentState {
data object Migration : RoomListContentState
data class Skeleton(val count: Int) : RoomListContentState
data object Empty : RoomListContentState
data class Rooms(

1
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt

@ -50,7 +50,6 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> { @@ -50,7 +50,6 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.RecoveryKeyConfirmation)),
aRoomListState(contentState = anEmptyContentState()),
aRoomListState(contentState = aSkeletonContentState()),
aRoomListState(matrixUser = MatrixUser(userId = UserId("@id:domain")), contentState = aMigrationContentState()),
aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")),
aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery)),
)

4
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt

@ -54,7 +54,6 @@ import io.element.android.features.roomlist.impl.filters.RoomListFiltersEmptySta @@ -54,7 +54,6 @@ import io.element.android.features.roomlist.impl.filters.RoomListFiltersEmptySta
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
import io.element.android.features.roomlist.impl.filters.selection.FilterSelectionState
import io.element.android.features.roomlist.impl.migration.MigrationScreenView
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@ -78,9 +77,6 @@ fun RoomListContentView( @@ -78,9 +77,6 @@ fun RoomListContentView(
) {
Box(modifier = modifier) {
when (contentState) {
is RoomListContentState.Migration -> {
MigrationScreenView(isMigrating = true)
}
is RoomListContentState.Skeleton -> {
SkeletonView(
count = contentState.count,

5
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/di/RoomListModule.kt

@ -21,8 +21,6 @@ import dagger.Binds @@ -21,8 +21,6 @@ import dagger.Binds
import dagger.Module
import io.element.android.features.roomlist.impl.filters.RoomListFiltersPresenter
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
import io.element.android.features.roomlist.impl.migration.MigrationScreenState
import io.element.android.features.roomlist.impl.search.RoomListSearchPresenter
import io.element.android.features.roomlist.impl.search.RoomListSearchState
import io.element.android.libraries.architecture.Presenter
@ -36,7 +34,4 @@ interface RoomListModule { @@ -36,7 +34,4 @@ interface RoomListModule {
@Binds
fun bindFiltersPresenter(presenter: RoomListFiltersPresenter): Presenter<RoomListFiltersState>
@Binds
fun bindMigrationScreenPresenter(presenter: MigrationScreenPresenter): Presenter<MigrationScreenState>
}

50
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenPresenter.kt

@ -1,50 +0,0 @@ @@ -1,50 +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.features.roomlist.impl.migration
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.features.roomlist.api.migration.MigrationScreenStore
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import javax.inject.Inject
class MigrationScreenPresenter @Inject constructor(
private val matrixClient: MatrixClient,
private val migrationScreenStore: MigrationScreenStore,
) : Presenter<MigrationScreenState> {
@Composable
override fun present(): MigrationScreenState {
val roomListState by matrixClient.roomListService.state.collectAsState()
var needsMigration by remember { mutableStateOf(migrationScreenStore.isMigrationScreenNeeded(matrixClient.sessionId)) }
if (roomListState == RoomListService.State.Running) {
LaunchedEffect(Unit) {
needsMigration = false
migrationScreenStore.setMigrationScreenShown(matrixClient.sessionId)
}
}
return MigrationScreenState(
isMigrating = needsMigration && roomListState != RoomListService.State.Running
)
}
}

21
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenState.kt

@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
/*
* Copyright (c) 2023 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.features.roomlist.impl.migration
data class MigrationScreenState(
val isMigrating: Boolean
)

55
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenView.kt

@ -1,55 +0,0 @@ @@ -1,55 +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.features.roomlist.impl.migration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import io.element.android.features.roomlist.impl.R
import io.element.android.libraries.designsystem.atomic.pages.SunsetPage
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@Composable
fun MigrationScreenView(
isMigrating: Boolean,
modifier: Modifier = Modifier,
) {
AnimatedVisibility(
visible = isMigrating,
enter = fadeIn(),
exit = fadeOut(),
label = "Migration view fade",
) {
SunsetPage(
modifier = modifier,
isLoading = true,
title = stringResource(id = R.string.screen_migration_title),
subtitle = stringResource(id = R.string.screen_migration_message),
overallContent = {}
)
}
}
@Composable
@PreviewsDayNight
internal fun MigrationScreenViewPreview() = ElementPreview {
MigrationScreenView(isMigrating = true)
}

59
features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/migration/SharedPreferencesMigrationScreenStore.kt

@ -1,59 +0,0 @@ @@ -1,59 +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.features.roomlist.impl.migration
import android.content.SharedPreferences
import androidx.core.content.edit
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.roomlist.api.migration.MigrationScreenStore
import io.element.android.libraries.androidutils.hash.hash
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.core.SessionId
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class SharedPreferencesMigrationScreenStore @Inject constructor(
private val sharedPreferences: SharedPreferences,
) : MigrationScreenStore {
override fun isMigrationScreenNeeded(sessionId: SessionId): Boolean {
return sharedPreferences.getBoolean(sessionId.toKey(), false).not()
}
override fun setMigrationScreenShown(sessionId: SessionId) {
sharedPreferences.edit().putBoolean(sessionId.toKey(), true).apply()
}
override fun reset() {
sharedPreferences.edit {
sharedPreferences.all.keys
.filter { it.startsWith(IS_MIGRATION_SCREEN_SHOWN_PREFIX) }
.forEach {
remove(it)
}
}
}
private fun SessionId.toKey(): String {
// Hash the sessionId to get rid of exotic char and take only the first 16 chars,
// The risk of collision is not high.
return IS_MIGRATION_SCREEN_SHOWN_PREFIX + value.hash().take(16)
}
companion object {
private const val IS_MIGRATION_SCREEN_SHOWN_PREFIX = "is_migration_screen_shown_"
}
}

26
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt

@ -33,7 +33,6 @@ import io.element.android.features.roomlist.impl.datasource.RoomListDataSource @@ -33,7 +33,6 @@ import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory
import io.element.android.features.roomlist.impl.filters.RoomListFiltersState
import io.element.android.features.roomlist.impl.filters.aRoomListFiltersState
import io.element.android.features.roomlist.impl.migration.MigrationScreenState
import io.element.android.features.roomlist.impl.model.createRoomListRoomSummary
import io.element.android.features.roomlist.impl.search.RoomListSearchEvents
import io.element.android.features.roomlist.impl.search.RoomListSearchState
@ -84,7 +83,6 @@ import io.element.android.libraries.push.test.notifications.FakeNotificationClea @@ -84,7 +83,6 @@ import io.element.android.libraries.push.test.notifications.FakeNotificationClea
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.MutablePresenter
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import io.element.android.tests.testutils.lambda.assert
@ -483,28 +481,6 @@ class RoomListPresenterTest { @@ -483,28 +481,6 @@ class RoomListPresenterTest {
}
}
@Test
fun `present - change in migration presenter state modifies contentState`() = runTest {
val migrationScreenPresenter = MutablePresenter(MigrationScreenState(true))
val scope = CoroutineScope(coroutineContext + SupervisorJob())
val presenter = createRoomListPresenter(
coroutineScope = scope,
migrationScreenPresenter = migrationScreenPresenter,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
// The migration screen is shown if the migration screen has not been shown before
assertThat(initialState.contentState).isInstanceOf(RoomListContentState.Migration::class.java)
// Set migration as done and set the room list service as running to trigger a refresh of the presenter value
migrationScreenPresenter.updateState(MigrationScreenState(false))
// The migration screen is not shown anymore
assertThat(awaitItem().contentState).isInstanceOf(RoomListContentState.Skeleton::class.java)
scope.cancel()
}
}
@Test
fun `present - when room service returns no room, then contentState is Empty`() = runTest {
val scope = CoroutineScope(coroutineContext + SupervisorJob())
@ -672,7 +648,6 @@ class RoomListPresenterTest { @@ -672,7 +648,6 @@ class RoomListPresenterTest {
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
coroutineScope: CoroutineScope,
migrationScreenPresenter: Presenter<MigrationScreenState> = Presenter { MigrationScreenState(false) },
analyticsService: AnalyticsService = FakeAnalyticsService(),
filtersPresenter: Presenter<RoomListFiltersState> = Presenter { aRoomListFiltersState() },
searchPresenter: Presenter<RoomListSearchState> = Presenter { aRoomListSearchState() },
@ -698,7 +673,6 @@ class RoomListPresenterTest { @@ -698,7 +673,6 @@ class RoomListPresenterTest {
sessionVerificationService = client.sessionVerificationService(),
encryptionService = client.encryptionService(),
),
migrationScreenPresenter = migrationScreenPresenter,
searchPresenter = searchPresenter,
sessionPreferencesStore = sessionPreferencesStore,
filtersPresenter = filtersPresenter,

76
features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/migration/MigrationScreenPresenterTest.kt

@ -1,76 +0,0 @@ @@ -1,76 +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.features.roomlist.impl.migration
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomlist.api.migration.MigrationScreenStore
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
class MigrationScreenPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@Test
fun `present - initial`() = runTest {
val presenter = createPresenter()
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.isMigrating).isTrue()
}
}
@Test
fun `present - migration end`() = runTest {
val matrixClient = FakeMatrixClient()
val migrationScreenStore = InMemoryMigrationScreenStore()
val presenter = createPresenter(matrixClient, migrationScreenStore)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.isMigrating).isTrue()
assertThat(migrationScreenStore.isMigrationScreenNeeded(A_SESSION_ID)).isTrue()
// Simulate room list loaded
(matrixClient.roomListService as FakeRoomListService).postState(RoomListService.State.Running)
val nextState = awaitItem()
assertThat(nextState.isMigrating).isFalse()
assertThat(migrationScreenStore.isMigrationScreenNeeded(A_SESSION_ID)).isFalse()
cancelAndIgnoreRemainingEvents()
}
}
private fun createPresenter(
matrixClient: MatrixClient = FakeMatrixClient(),
migrationScreenStore: MigrationScreenStore = InMemoryMigrationScreenStore(),
) = MigrationScreenPresenter(
matrixClient,
migrationScreenStore,
)
}

28
features/roomlist/test/build.gradle.kts

@ -1,28 +0,0 @@ @@ -1,28 +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.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.features.roomlist.test"
}
dependencies {
implementation(projects.features.roomlist.api)
implementation(projects.libraries.matrix.api)
implementation(projects.tests.testutils)
}

40
features/roomlist/test/src/main/kotlin/io/element/android/features/roomlist/impl/migration/InMemoryMigrationScreenStore.kt

@ -1,40 +0,0 @@ @@ -1,40 +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.features.roomlist.impl.migration
import io.element.android.features.roomlist.api.migration.MigrationScreenStore
import io.element.android.libraries.matrix.api.core.SessionId
class InMemoryMigrationScreenStore(
private val resetLambda: () -> Unit = { }
) : MigrationScreenStore {
private val store = mutableMapOf<SessionId, Boolean>()
override fun isMigrationScreenNeeded(sessionId: SessionId): Boolean {
// If store does not have key return true, else return the opposite of the value
return store[sessionId]?.not() ?: true
}
override fun setMigrationScreenShown(sessionId: SessionId) {
store[sessionId] = true
}
override fun reset() {
store.clear()
resetLambda()
}
}

6
samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt

@ -30,8 +30,6 @@ import io.element.android.features.roomlist.impl.datasource.RoomListDataSource @@ -30,8 +30,6 @@ import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory
import io.element.android.features.roomlist.impl.filters.RoomListFiltersPresenter
import io.element.android.features.roomlist.impl.filters.selection.DefaultFilterSelectionStrategy
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
import io.element.android.features.roomlist.impl.migration.SharedPreferencesMigrationScreenStore
import io.element.android.features.roomlist.impl.search.RoomListSearchDataSource
import io.element.android.features.roomlist.impl.search.RoomListSearchPresenter
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
@ -120,10 +118,6 @@ class RoomListScreen( @@ -120,10 +118,6 @@ class RoomListScreen(
encryptionService = encryptionService,
),
featureFlagService = featureFlagService,
migrationScreenPresenter = MigrationScreenPresenter(
matrixClient = matrixClient,
migrationScreenStore = SharedPreferencesMigrationScreenStore(context.getSharedPreferences("migration", Context.MODE_PRIVATE))
),
searchPresenter = RoomListSearchPresenter(
RoomListSearchDataSource(
roomListService = matrixClient.roomListService,

Loading…
Cancel
Save