Add clear cache action in the developer settings (#643)
This commit is contained in:
parent
67c4df3b88
commit
bf80c251aa
13 changed files with 172 additions and 6 deletions
|
|
@ -62,6 +62,7 @@ dependencies {
|
||||||
testImplementation(projects.features.logout.impl)
|
testImplementation(projects.features.logout.impl)
|
||||||
testImplementation(projects.features.analytics.test)
|
testImplementation(projects.features.analytics.test)
|
||||||
testImplementation(projects.features.analytics.impl)
|
testImplementation(projects.features.analytics.impl)
|
||||||
|
testImplementation(projects.tests.testutils)
|
||||||
|
|
||||||
androidTestImplementation(libs.test.junitext)
|
androidTestImplementation(libs.test.junitext)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,4 +20,5 @@ import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
|
||||||
|
|
||||||
sealed interface DeveloperSettingsEvents {
|
sealed interface DeveloperSettingsEvents {
|
||||||
data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : DeveloperSettingsEvents
|
data class UpdateEnabledFeature(val feature: FeatureUiModel, val isEnabled: Boolean) : DeveloperSettingsEvents
|
||||||
|
object ClearCache: DeveloperSettingsEvents
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,17 @@ package io.element.android.features.preferences.impl.developer
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.key
|
import androidx.compose.runtime.key
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
||||||
|
import io.element.android.features.preferences.impl.tasks.ClearCacheUseCase
|
||||||
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import io.element.android.libraries.architecture.execute
|
||||||
import io.element.android.libraries.core.bool.orFalse
|
import io.element.android.libraries.core.bool.orFalse
|
||||||
import io.element.android.libraries.featureflag.api.Feature
|
import io.element.android.libraries.featureflag.api.Feature
|
||||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||||
|
|
@ -36,6 +41,7 @@ import javax.inject.Inject
|
||||||
|
|
||||||
class DeveloperSettingsPresenter @Inject constructor(
|
class DeveloperSettingsPresenter @Inject constructor(
|
||||||
private val featureFlagService: FeatureFlagService,
|
private val featureFlagService: FeatureFlagService,
|
||||||
|
private val clearCacheUseCase: ClearCacheUseCase,
|
||||||
) : Presenter<DeveloperSettingsState> {
|
) : Presenter<DeveloperSettingsState> {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -47,6 +53,9 @@ class DeveloperSettingsPresenter @Inject constructor(
|
||||||
val enabledFeatures = remember {
|
val enabledFeatures = remember {
|
||||||
mutableStateMapOf<String, Boolean>()
|
mutableStateMapOf<String, Boolean>()
|
||||||
}
|
}
|
||||||
|
val clearCacheAction = remember {
|
||||||
|
mutableStateOf<Async<Unit>>(Async.Uninitialized)
|
||||||
|
}
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
FeatureFlags.values().forEach { feature ->
|
FeatureFlags.values().forEach { feature ->
|
||||||
features[feature.key] = feature
|
features[feature.key] = feature
|
||||||
|
|
@ -64,11 +73,13 @@ class DeveloperSettingsPresenter @Inject constructor(
|
||||||
event.feature,
|
event.feature,
|
||||||
event.isEnabled
|
event.isEnabled
|
||||||
)
|
)
|
||||||
|
DeveloperSettingsEvents.ClearCache -> coroutineScope.clearCache(clearCacheAction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeveloperSettingsState(
|
return DeveloperSettingsState(
|
||||||
features = featureUiModels.toImmutableList(),
|
features = featureUiModels.toImmutableList(),
|
||||||
|
clearCacheAction = clearCacheAction.value,
|
||||||
eventSink = ::handleEvents
|
eventSink = ::handleEvents
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -103,6 +114,12 @@ class DeveloperSettingsPresenter @Inject constructor(
|
||||||
enabledFeatures[featureUiModel.key] = enabled
|
enabledFeatures[featureUiModel.key] = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.clearCache(clearCacheAction: MutableState<Async<Unit>>) = launch {
|
||||||
|
suspend {
|
||||||
|
clearCacheUseCase.execute()
|
||||||
|
}.execute(clearCacheAction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.developer
|
package io.element.android.features.preferences.impl.developer
|
||||||
|
|
||||||
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
|
import io.element.android.libraries.featureflag.ui.model.FeatureUiModel
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
data class DeveloperSettingsState(
|
data class DeveloperSettingsState constructor(
|
||||||
val features: ImmutableList<FeatureUiModel>,
|
val features: ImmutableList<FeatureUiModel>,
|
||||||
|
val clearCacheAction: Async<Unit>,
|
||||||
val eventSink: (DeveloperSettingsEvents) -> Unit
|
val eventSink: (DeveloperSettingsEvents) -> Unit
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,19 @@
|
||||||
package io.element.android.features.preferences.impl.developer
|
package io.element.android.features.preferences.impl.developer
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList
|
import io.element.android.libraries.featureflag.ui.model.aFeatureUiModelList
|
||||||
|
|
||||||
open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSettingsState> {
|
open class DeveloperSettingsStateProvider : PreviewParameterProvider<DeveloperSettingsState> {
|
||||||
override val values: Sequence<DeveloperSettingsState>
|
override val values: Sequence<DeveloperSettingsState>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
aDeveloperSettingsState(),
|
aDeveloperSettingsState(),
|
||||||
|
aDeveloperSettingsState().copy(clearCacheAction = Async.Loading()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun aDeveloperSettingsState() = DeveloperSettingsState(
|
fun aDeveloperSettingsState() = DeveloperSettingsState(
|
||||||
features = aFeatureUiModelList(),
|
features = aFeatureUiModelList(),
|
||||||
|
clearCacheAction = Async.Uninitialized,
|
||||||
eventSink = {}
|
eventSink = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,14 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.developer
|
package io.element.android.features.preferences.impl.developer
|
||||||
|
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
|
import io.element.android.libraries.architecture.isLoading
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||||
|
|
@ -52,6 +55,18 @@ fun DeveloperSettingsView(
|
||||||
onClick = onOpenShowkase
|
onClick = onOpenShowkase
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
PreferenceCategory(title = "Cache") {
|
||||||
|
PreferenceText(
|
||||||
|
title = "Clear cache",
|
||||||
|
icon = Icons.Default.Delete,
|
||||||
|
loadingCurrentValue = state.clearCacheAction.isLoading(),
|
||||||
|
onClick = {
|
||||||
|
if (state.clearCacheAction.isLoading().not()) {
|
||||||
|
state.eventSink(DeveloperSettingsEvents.ClearCache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* 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.preferences.impl.tasks
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
interface ClearCacheUseCase {
|
||||||
|
suspend fun execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContributesBinding(SessionScope::class)
|
||||||
|
class DefaultClearCacheUseCase @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
|
) : ClearCacheUseCase {
|
||||||
|
override suspend fun execute() = withContext(coroutineDispatchers.io) {
|
||||||
|
matrixClient.stopSync()
|
||||||
|
matrixClient.clearCache()
|
||||||
|
context.cacheDir.deleteRecursively()
|
||||||
|
matrixClient.startSync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,8 @@ import app.cash.molecule.RecompositionClock
|
||||||
import app.cash.molecule.moleculeFlow
|
import app.cash.molecule.moleculeFlow
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.features.preferences.impl.tasks.FakeClearCacheUseCase
|
||||||
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
|
@ -29,13 +31,15 @@ class DeveloperSettingsPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensures initial state is correct`() = runTest {
|
fun `present - ensures initial state is correct`() = runTest {
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService()
|
FakeFeatureFlagService(),
|
||||||
|
FakeClearCacheUseCase()
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.features).isEmpty()
|
assertThat(initialState.features).isEmpty()
|
||||||
|
assertThat(initialState.clearCacheAction).isEqualTo(Async.Uninitialized)
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +47,8 @@ class DeveloperSettingsPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensures feature list is loaded`() = runTest {
|
fun `present - ensures feature list is loaded`() = runTest {
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService()
|
FakeFeatureFlagService(),
|
||||||
|
FakeClearCacheUseCase()
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
|
|
@ -58,7 +63,8 @@ class DeveloperSettingsPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - ensures state is updated when enabled feature event is triggered`() = runTest {
|
fun `present - ensures state is updated when enabled feature event is triggered`() = runTest {
|
||||||
val presenter = DeveloperSettingsPresenter(
|
val presenter = DeveloperSettingsPresenter(
|
||||||
FakeFeatureFlagService()
|
FakeFeatureFlagService(),
|
||||||
|
FakeClearCacheUseCase()
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
|
|
@ -74,4 +80,25 @@ class DeveloperSettingsPresenterTest {
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - clear cache`() = runTest {
|
||||||
|
val clearCacheUseCase = FakeClearCacheUseCase()
|
||||||
|
val presenter = DeveloperSettingsPresenter(
|
||||||
|
FakeFeatureFlagService(),
|
||||||
|
clearCacheUseCase
|
||||||
|
)
|
||||||
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
|
presenter.present()
|
||||||
|
}.test {
|
||||||
|
skipItems(1)
|
||||||
|
val initialState = awaitItem()
|
||||||
|
assertThat(clearCacheUseCase.executeHasBeenCalled).isFalse()
|
||||||
|
initialState.eventSink(DeveloperSettingsEvents.ClearCache)
|
||||||
|
val stateAfterEvent = awaitItem()
|
||||||
|
assertThat(stateAfterEvent.clearCacheAction).isInstanceOf(Async.Loading::class.java)
|
||||||
|
assertThat(awaitItem().clearCacheAction).isInstanceOf(Async.Success::class.java)
|
||||||
|
assertThat(clearCacheUseCase.executeHasBeenCalled).isTrue()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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.preferences.impl.tasks
|
||||||
|
|
||||||
|
import io.element.android.tests.testutils.simulateLongTask
|
||||||
|
|
||||||
|
class FakeClearCacheUseCase : ClearCacheUseCase {
|
||||||
|
var executeHasBeenCalled = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
override suspend fun execute() = simulateLongTask {
|
||||||
|
executeHasBeenCalled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -50,6 +50,7 @@ interface MatrixClient : Closeable {
|
||||||
fun sessionVerificationService(): SessionVerificationService
|
fun sessionVerificationService(): SessionVerificationService
|
||||||
fun pushersService(): PushersService
|
fun pushersService(): PushersService
|
||||||
fun notificationService(): NotificationService
|
fun notificationService(): NotificationService
|
||||||
|
suspend fun clearCache()
|
||||||
suspend fun logout()
|
suspend fun logout()
|
||||||
suspend fun loadUserDisplayName(): Result<String>
|
suspend fun loadUserDisplayName(): Result<String>
|
||||||
suspend fun loadUserAvatarURLString(): Result<String?>
|
suspend fun loadUserAvatarURLString(): Result<String?>
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ dependencies {
|
||||||
// api(projects.libraries.rustsdk)
|
// api(projects.libraries.rustsdk)
|
||||||
implementation(libs.matrix.sdk)
|
implementation(libs.matrix.sdk)
|
||||||
implementation(projects.libraries.di)
|
implementation(projects.libraries.di)
|
||||||
|
implementation(projects.libraries.androidutils)
|
||||||
implementation(projects.services.toolbox.api)
|
implementation(projects.services.toolbox.api)
|
||||||
api(projects.libraries.matrix.api)
|
api(projects.libraries.matrix.api)
|
||||||
implementation(libs.dagger)
|
implementation(libs.dagger)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.impl
|
package io.element.android.libraries.matrix.impl
|
||||||
|
|
||||||
|
import io.element.android.libraries.androidutils.file.safeDelete
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.ProgressCallback
|
import io.element.android.libraries.matrix.api.core.ProgressCallback
|
||||||
|
|
@ -336,6 +337,10 @@ class RustMatrixClient constructor(
|
||||||
client.destroy()
|
client.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun clearCache() {
|
||||||
|
baseDirectory.deleteSessionDirectory(userID = client.userId(), deleteCryptoDb = false)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun logout() = withContext(dispatchers.io) {
|
override suspend fun logout() = withContext(dispatchers.io) {
|
||||||
try {
|
try {
|
||||||
client.logout()
|
client.logout()
|
||||||
|
|
@ -378,11 +383,29 @@ class RustMatrixClient constructor(
|
||||||
|
|
||||||
override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver
|
override fun roomMembershipObserver(): RoomMembershipObserver = roomMembershipObserver
|
||||||
|
|
||||||
private fun File.deleteSessionDirectory(userID: String): Boolean {
|
private fun File.deleteSessionDirectory(
|
||||||
|
userID: String,
|
||||||
|
deleteCryptoDb: Boolean = false,
|
||||||
|
): Boolean {
|
||||||
// Rust sanitises the user ID replacing invalid characters with an _
|
// Rust sanitises the user ID replacing invalid characters with an _
|
||||||
val sanitisedUserID = userID.replace(":", "_")
|
val sanitisedUserID = userID.replace(":", "_")
|
||||||
val sessionDirectory = File(this, sanitisedUserID)
|
val sessionDirectory = File(this, sanitisedUserID)
|
||||||
return sessionDirectory.deleteRecursively()
|
return if (deleteCryptoDb) {
|
||||||
|
// Delete the folder and all its content
|
||||||
|
sessionDirectory.deleteRecursively()
|
||||||
|
} else {
|
||||||
|
// Delete only the state.db file
|
||||||
|
listOf(
|
||||||
|
"matrix-sdk-state.sqlite3",
|
||||||
|
"matrix-sdk-state.sqlite3-shm",
|
||||||
|
"matrix-sdk-state.sqlite3-wal",
|
||||||
|
).map { fileName ->
|
||||||
|
File(sessionDirectory, fileName)
|
||||||
|
}.forEach { file ->
|
||||||
|
file.safeDelete()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,9 @@ class FakeMatrixClient(
|
||||||
|
|
||||||
override fun stopSync() = Unit
|
override fun stopSync() = Unit
|
||||||
|
|
||||||
|
override suspend fun clearCache() {
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun logout() {
|
override suspend fun logout() {
|
||||||
delay(100)
|
delay(100)
|
||||||
logoutFailure?.let { throw it }
|
logoutFailure?.let { throw it }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue