From d0260df4d5441c5b7110311aac7add2c28dc35aa Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jan 2026 18:16:18 +0100 Subject: [PATCH 1/6] Ensure the latest screenshot is rendered. Fixes #6008 --- .../features/rageshake/impl/bugreport/BugReportView.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt index 612d3aa68c..c2c34835c9 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage +import coil3.request.CachePolicy import coil3.request.ImageRequest import io.element.android.features.rageshake.impl.R import io.element.android.libraries.architecture.AsyncAction @@ -135,6 +136,9 @@ fun BugReportView( val context = LocalContext.current val model = ImageRequest.Builder(context) .data(state.screenshotUri) + // Since `screenshotUri` always has the same value, we need to disable memory cache to + // ensure the image is reloaded when the URI content changes + .memoryCachePolicy(CachePolicy.DISABLED) .build() AsyncImage( modifier = Modifier.fillMaxWidth(fraction = 0.5f), From f5dd10388e23ddc46a050a834b774424f46948e6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jan 2026 18:17:13 +0100 Subject: [PATCH 2/6] Improve the code. --- .../DefaultRageshakeDetectionPresenter.kt | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt index a7813ed6fb..e7251c8700 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt @@ -12,7 +12,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import dev.zacsweers.metro.AppScope @@ -62,16 +61,6 @@ class DefaultRageshakeDetectionPresenter( } } - val state = remember(preferencesState, isStarted.value, takeScreenshot.value, showDialog.value) { - RageshakeDetectionState( - isStarted = isStarted.value, - takeScreenshot = takeScreenshot.value, - showDialog = showDialog.value, - preferenceState = preferencesState, - eventSink = ::handleEvent, - ) - } - LaunchedEffect(preferencesState.sensitivity) { rageShake.setSensitivity(preferencesState.sensitivity) } @@ -83,14 +72,25 @@ class DefaultRageshakeDetectionPresenter( !showDialog.value LaunchedEffect(shouldStart) { - handleRageShake(shouldStart, state, takeScreenshot) + handleRageShake( + start = shouldStart, + sensitivity = preferencesState.sensitivity, + takeScreenshot = takeScreenshot, + ) } - return state + + return RageshakeDetectionState( + isStarted = isStarted.value, + takeScreenshot = takeScreenshot.value, + showDialog = showDialog.value, + preferenceState = preferencesState, + eventSink = ::handleEvent, + ) } - private fun handleRageShake(start: Boolean, state: RageshakeDetectionState, takeScreenshot: MutableState) { + private fun handleRageShake(start: Boolean, sensitivity: Float, takeScreenshot: MutableState) { if (start) { - rageShake.start(state.preferenceState.sensitivity) + rageShake.start(sensitivity) rageShake.setInterceptor { takeScreenshot.value = true } From 7a366a0c882a441ed7730f9ac18daec71ec79a6c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jan 2026 18:17:58 +0100 Subject: [PATCH 3/6] RageshakeDetectionEvents -> RageshakeDetectionEvent --- .../element/android/appnav/root/RootView.kt | 4 ++-- ...onEvents.kt => RageshakeDetectionEvent.kt} | 12 +++++----- .../api/detection/RageshakeDetectionState.kt | 2 +- .../api/detection/RageshakeDetectionView.kt | 10 ++++---- .../DefaultRageshakeDetectionPresenter.kt | 14 +++++------ .../RageshakeDetectionPresenterTest.kt | 24 +++++++++---------- 6 files changed, 33 insertions(+), 33 deletions(-) rename features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/{RageshakeDetectionEvents.kt => RageshakeDetectionEvent.kt} (60%) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt b/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt index 2bc76d7a5b..23f0d7f44a 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.rageshake.api.crash.CrashDetectionEvents import io.element.android.features.rageshake.api.crash.CrashDetectionView -import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvents +import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvent import io.element.android.features.rageshake.api.detection.RageshakeDetectionView import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -40,7 +40,7 @@ fun RootView( fun onOpenBugReport() { state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed) - state.rageshakeDetectionState.eventSink(RageshakeDetectionEvents.Dismiss) + state.rageshakeDetectionState.eventSink(RageshakeDetectionEvent.Dismiss) onOpenBugReport.invoke() } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionEvents.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionEvent.kt similarity index 60% rename from features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionEvents.kt rename to features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionEvent.kt index 921ae861f2..83ae545d95 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionEvents.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionEvent.kt @@ -10,10 +10,10 @@ package io.element.android.features.rageshake.api.detection import io.element.android.features.rageshake.api.screenshot.ImageResult -sealed interface RageshakeDetectionEvents { - data object Dismiss : RageshakeDetectionEvents - data object Disable : RageshakeDetectionEvents - data object StartDetection : RageshakeDetectionEvents - data object StopDetection : RageshakeDetectionEvents - data class ProcessScreenshot(val imageResult: ImageResult) : RageshakeDetectionEvents +sealed interface RageshakeDetectionEvent { + data object Dismiss : RageshakeDetectionEvent + data object Disable : RageshakeDetectionEvent + data object StartDetection : RageshakeDetectionEvent + data object StopDetection : RageshakeDetectionEvent + data class ProcessScreenshot(val imageResult: ImageResult) : RageshakeDetectionEvent } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt index a240fed687..2e458e983a 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionState.kt @@ -15,5 +15,5 @@ data class RageshakeDetectionState( val showDialog: Boolean, val isStarted: Boolean, val preferenceState: RageshakePreferencesState, - val eventSink: (RageshakeDetectionEvents) -> Unit + val eventSink: (RageshakeDetectionEvent) -> Unit ) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt index dff6d9b716..745a362637 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt @@ -35,22 +35,22 @@ fun RageshakeDetectionView( val context = LocalContext.current OnLifecycleEvent { _, event -> when (event) { - Lifecycle.Event.ON_RESUME -> eventSink(RageshakeDetectionEvents.StartDetection) - Lifecycle.Event.ON_PAUSE -> eventSink(RageshakeDetectionEvents.StopDetection) + Lifecycle.Event.ON_RESUME -> eventSink(RageshakeDetectionEvent.StartDetection) + Lifecycle.Event.ON_PAUSE -> eventSink(RageshakeDetectionEvent.StopDetection) else -> Unit } } when { state.takeScreenshot -> TakeScreenshot( - onScreenshot = { eventSink(RageshakeDetectionEvents.ProcessScreenshot(it)) } + onScreenshot = { eventSink(RageshakeDetectionEvent.ProcessScreenshot(it)) } ) state.showDialog -> { LaunchedEffect(Unit) { context.vibrate() } RageshakeDialogContent( - onNoClick = { eventSink(RageshakeDetectionEvents.Dismiss) }, - onDisableClick = { eventSink(RageshakeDetectionEvents.Disable) }, + onNoClick = { eventSink(RageshakeDetectionEvent.Dismiss) }, + onDisableClick = { eventSink(RageshakeDetectionEvent.Disable) }, onYesClick = onOpenBugReport ) } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt index e7251c8700..3fa0a7ef6b 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt @@ -16,7 +16,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvents +import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvent import io.element.android.features.rageshake.api.detection.RageshakeDetectionPresenter import io.element.android.features.rageshake.api.detection.RageshakeDetectionState import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvents @@ -48,16 +48,16 @@ class DefaultRageshakeDetectionPresenter( mutableStateOf(false) } - fun handleEvent(event: RageshakeDetectionEvents) { + fun handleEvent(event: RageshakeDetectionEvent) { when (event) { - RageshakeDetectionEvents.Disable -> { + RageshakeDetectionEvent.Disable -> { preferencesState.eventSink(RageshakePreferencesEvents.SetIsEnabled(false)) showDialog.value = false } - RageshakeDetectionEvents.StartDetection -> isStarted.value = true - RageshakeDetectionEvents.StopDetection -> isStarted.value = false - is RageshakeDetectionEvents.ProcessScreenshot -> localCoroutineScope.processScreenshot(takeScreenshot, showDialog, event.imageResult) - RageshakeDetectionEvents.Dismiss -> showDialog.value = false + RageshakeDetectionEvent.StartDetection -> isStarted.value = true + RageshakeDetectionEvent.StopDetection -> isStarted.value = false + is RageshakeDetectionEvent.ProcessScreenshot -> localCoroutineScope.processScreenshot(takeScreenshot, showDialog, event.imageResult) + RageshakeDetectionEvent.Dismiss -> showDialog.value = false } } diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt index d76ab73aa8..9db39e0ee9 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt @@ -13,7 +13,7 @@ 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.rageshake.api.detection.RageshakeDetectionEvents +import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvent import io.element.android.features.rageshake.api.screenshot.ImageResult import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter import io.element.android.features.rageshake.impl.rageshake.FakeRageShake @@ -87,9 +87,9 @@ class RageshakeDetectionPresenterTest { }.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) + initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection) assertThat(awaitItem().isStarted).isTrue() - initialState.eventSink.invoke(RageshakeDetectionEvents.StopDetection) + initialState.eventSink.invoke(RageshakeDetectionEvent.StopDetection) assertThat(awaitItem().isStarted).isFalse() } } @@ -114,15 +114,15 @@ class RageshakeDetectionPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.isStarted).isFalse() - initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) + initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection) assertThat(awaitItem().isStarted).isTrue() rageshake.triggerPhoneRageshake() assertThat(awaitItem().takeScreenshot).isTrue() initialState.eventSink.invoke( - RageshakeDetectionEvents.ProcessScreenshot(ImageResult.Success(aBitmap)) + RageshakeDetectionEvent.ProcessScreenshot(ImageResult.Success(aBitmap)) ) assertThat(awaitItem().showDialog).isTrue() - initialState.eventSink.invoke(RageshakeDetectionEvents.Dismiss) + initialState.eventSink.invoke(RageshakeDetectionEvent.Dismiss) val finalState = awaitItem() assertThat(finalState.showDialog).isFalse() assertThat(rageshakeDataStore.isEnabled().first()).isTrue() @@ -149,15 +149,15 @@ class RageshakeDetectionPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.isStarted).isFalse() - initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) + initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection) assertThat(awaitItem().isStarted).isTrue() rageshake.triggerPhoneRageshake() assertThat(awaitItem().takeScreenshot).isTrue() initialState.eventSink.invoke( - RageshakeDetectionEvents.ProcessScreenshot(ImageResult.Error(AN_EXCEPTION)) + RageshakeDetectionEvent.ProcessScreenshot(ImageResult.Error(AN_EXCEPTION)) ) assertThat(awaitItem().showDialog).isTrue() - initialState.eventSink.invoke(RageshakeDetectionEvents.Dismiss) + initialState.eventSink.invoke(RageshakeDetectionEvent.Dismiss) val finalState = awaitItem() assertThat(finalState.showDialog).isFalse() assertThat(rageshakeDataStore.isEnabled().first()).isTrue() @@ -184,15 +184,15 @@ class RageshakeDetectionPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.isStarted).isFalse() - initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) + initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection) assertThat(awaitItem().isStarted).isTrue() rageshake.triggerPhoneRageshake() assertThat(awaitItem().takeScreenshot).isTrue() initialState.eventSink.invoke( - RageshakeDetectionEvents.ProcessScreenshot(ImageResult.Success(aBitmap)) + RageshakeDetectionEvent.ProcessScreenshot(ImageResult.Success(aBitmap)) ) assertThat(awaitItem().showDialog).isTrue() - initialState.eventSink.invoke(RageshakeDetectionEvents.Disable) + initialState.eventSink.invoke(RageshakeDetectionEvent.Disable) skipItems(1) assertThat(awaitItem().showDialog).isFalse() assertThat(rageshakeDataStore.isEnabled().first()).isFalse() From f5c22a74890ad6476f5201bc114adee9654d0daf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jan 2026 18:18:44 +0100 Subject: [PATCH 4/6] RageshakePreferencesEvents -> RageshakePreferencesEvent --- ...ePreferencesEvents.kt => RageshakePreferencesEvent.kt} | 6 +++--- .../api/preferences/RageshakePreferencesState.kt | 2 +- .../api/preferences/RageshakePreferencesStateProvider.kt | 2 +- .../rageshake/api/preferences/RageshakePreferencesView.kt | 4 ++-- .../impl/detection/DefaultRageshakeDetectionPresenter.kt | 4 ++-- .../preferences/DefaultRageshakePreferencesPresenter.kt | 8 ++++---- .../impl/preferences/RageshakePreferencesPresenterTest.kt | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) rename features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/{RageshakePreferencesEvents.kt => RageshakePreferencesEvent.kt} (84%) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesEvents.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesEvent.kt similarity index 84% rename from features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesEvents.kt rename to features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesEvent.kt index 49458c2e34..8b1540c0d5 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesEvents.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesEvent.kt @@ -8,7 +8,7 @@ package io.element.android.features.rageshake.api.preferences -sealed interface RageshakePreferencesEvents { - data class SetSensitivity(val sensitivity: Float) : RageshakePreferencesEvents - data class SetIsEnabled(val isEnabled: Boolean) : RageshakePreferencesEvents +sealed interface RageshakePreferencesEvent { + data class SetSensitivity(val sensitivity: Float) : RageshakePreferencesEvent + data class SetIsEnabled(val isEnabled: Boolean) : RageshakePreferencesEvent } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesState.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesState.kt index faba80a3c5..00e65d3e13 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesState.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesState.kt @@ -13,5 +13,5 @@ data class RageshakePreferencesState( val isEnabled: Boolean, val isSupported: Boolean, val sensitivity: Float, - val eventSink: (RageshakePreferencesEvents) -> Unit, + val eventSink: (RageshakePreferencesEvent) -> Unit, ) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesStateProvider.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesStateProvider.kt index d1a863745f..1de65c1a69 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesStateProvider.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesStateProvider.kt @@ -23,7 +23,7 @@ fun aRageshakePreferencesState( isEnabled: Boolean = false, isSupported: Boolean = true, sensitivity: Float = 0.3f, - eventSink: (RageshakePreferencesEvents) -> Unit = {} + eventSink: (RageshakePreferencesEvent) -> Unit = {} ) = RageshakePreferencesState( isFeatureEnabled = isFeatureEnabled, isEnabled = isEnabled, diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt index e4f32982f9..7ea35308e9 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/preferences/RageshakePreferencesView.kt @@ -29,11 +29,11 @@ fun RageshakePreferencesView( modifier: Modifier = Modifier, ) { fun onSensitivityChanged(sensitivity: Float) { - state.eventSink(RageshakePreferencesEvents.SetSensitivity(sensitivity = sensitivity)) + state.eventSink(RageshakePreferencesEvent.SetSensitivity(sensitivity = sensitivity)) } fun onEnabledChanged(isEnabled: Boolean) { - state.eventSink(RageshakePreferencesEvents.SetIsEnabled(isEnabled = isEnabled)) + state.eventSink(RageshakePreferencesEvent.SetIsEnabled(isEnabled = isEnabled)) } Column(modifier = modifier) { diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt index 3fa0a7ef6b..49014d72a7 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/detection/DefaultRageshakeDetectionPresenter.kt @@ -19,7 +19,7 @@ import dev.zacsweers.metro.ContributesBinding import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvent import io.element.android.features.rageshake.api.detection.RageshakeDetectionPresenter import io.element.android.features.rageshake.api.detection.RageshakeDetectionState -import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvents +import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvent import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter import io.element.android.features.rageshake.api.screenshot.ImageResult import io.element.android.features.rageshake.impl.rageshake.RageShake @@ -51,7 +51,7 @@ class DefaultRageshakeDetectionPresenter( fun handleEvent(event: RageshakeDetectionEvent) { when (event) { RageshakeDetectionEvent.Disable -> { - preferencesState.eventSink(RageshakePreferencesEvents.SetIsEnabled(false)) + preferencesState.eventSink(RageshakePreferencesEvent.SetIsEnabled(false)) showDialog.value = false } RageshakeDetectionEvent.StartDetection -> isStarted.value = true diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/preferences/DefaultRageshakePreferencesPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/preferences/DefaultRageshakePreferencesPresenter.kt index f16d99c634..7f463135f9 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/preferences/DefaultRageshakePreferencesPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/preferences/DefaultRageshakePreferencesPresenter.kt @@ -19,7 +19,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.features.rageshake.api.RageshakeFeatureAvailability -import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvents +import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvent import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState import io.element.android.features.rageshake.impl.rageshake.RageShake @@ -48,10 +48,10 @@ class DefaultRageshakePreferencesPresenter( rageshakeDataStore.sensitivity() }.collectAsState(initial = 0f) - fun handleEvent(event: RageshakePreferencesEvents) { + fun handleEvent(event: RageshakePreferencesEvent) { when (event) { - is RageshakePreferencesEvents.SetIsEnabled -> localCoroutineScope.setIsEnabled(event.isEnabled) - is RageshakePreferencesEvents.SetSensitivity -> localCoroutineScope.setSensitivity(event.sensitivity) + is RageshakePreferencesEvent.SetIsEnabled -> localCoroutineScope.setIsEnabled(event.isEnabled) + is RageshakePreferencesEvent.SetSensitivity -> localCoroutineScope.setSensitivity(event.sensitivity) } } diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt index 8fda5c3d97..749d0aefe7 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt @@ -12,7 +12,7 @@ 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.rageshake.api.preferences.RageshakePreferencesEvents +import io.element.android.features.rageshake.api.preferences.RageshakePreferencesEvent import io.element.android.features.rageshake.impl.rageshake.A_SENSITIVITY import io.element.android.features.rageshake.impl.rageshake.FakeRageShake import io.element.android.features.rageshake.impl.rageshake.FakeRageshakeDataStore @@ -73,9 +73,9 @@ class RageshakePreferencesPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.isEnabled).isTrue() - initialState.eventSink.invoke(RageshakePreferencesEvents.SetIsEnabled(false)) + initialState.eventSink.invoke(RageshakePreferencesEvent.SetIsEnabled(false)) assertThat(awaitItem().isEnabled).isFalse() - initialState.eventSink.invoke(RageshakePreferencesEvents.SetIsEnabled(true)) + initialState.eventSink.invoke(RageshakePreferencesEvent.SetIsEnabled(true)) assertThat(awaitItem().isEnabled).isTrue() } } @@ -93,7 +93,7 @@ class RageshakePreferencesPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.sensitivity).isEqualTo(A_SENSITIVITY) - initialState.eventSink.invoke(RageshakePreferencesEvents.SetSensitivity(A_SENSITIVITY + 1f)) + initialState.eventSink.invoke(RageshakePreferencesEvent.SetSensitivity(A_SENSITIVITY + 1f)) assertThat(awaitItem().sensitivity).isEqualTo(A_SENSITIVITY + 1f) } } From 54e08f34471853c37c8d84973dd8a62c2f461ef0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jan 2026 18:19:20 +0100 Subject: [PATCH 5/6] CrashDetectionEvents -> CrashDetectionEvent --- .../kotlin/io/element/android/appnav/root/RootView.kt | 4 ++-- .../{CrashDetectionEvents.kt => CrashDetectionEvent.kt} | 6 +++--- .../features/rageshake/api/crash/CrashDetectionState.kt | 2 +- .../features/rageshake/api/crash/CrashDetectionView.kt | 2 +- .../impl/crash/DefaultCrashDetectionPresenter.kt | 8 ++++---- .../impl/crash/ui/CrashDetectionPresenterTest.kt | 6 +++--- 6 files changed, 14 insertions(+), 14 deletions(-) rename features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/{CrashDetectionEvents.kt => CrashDetectionEvent.kt} (65%) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt b/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt index 23f0d7f44a..32c8e52084 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/root/RootView.kt @@ -15,7 +15,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter -import io.element.android.features.rageshake.api.crash.CrashDetectionEvents +import io.element.android.features.rageshake.api.crash.CrashDetectionEvent import io.element.android.features.rageshake.api.crash.CrashDetectionView import io.element.android.features.rageshake.api.detection.RageshakeDetectionEvent import io.element.android.features.rageshake.api.detection.RageshakeDetectionView @@ -39,7 +39,7 @@ fun RootView( children() fun onOpenBugReport() { - state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed) + state.crashDetectionState.eventSink(CrashDetectionEvent.ResetAppHasCrashed) state.rageshakeDetectionState.eventSink(RageshakeDetectionEvent.Dismiss) onOpenBugReport.invoke() } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionEvents.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionEvent.kt similarity index 65% rename from features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionEvents.kt rename to features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionEvent.kt index 89c49338d1..9a95910c13 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionEvents.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionEvent.kt @@ -8,7 +8,7 @@ package io.element.android.features.rageshake.api.crash -sealed interface CrashDetectionEvents { - data object ResetAllCrashData : CrashDetectionEvents - data object ResetAppHasCrashed : CrashDetectionEvents +sealed interface CrashDetectionEvent { + data object ResetAllCrashData : CrashDetectionEvent + data object ResetAppHasCrashed : CrashDetectionEvent } diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionState.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionState.kt index dd08cbf86c..9c29dc4e7b 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionState.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionState.kt @@ -11,5 +11,5 @@ package io.element.android.features.rageshake.api.crash data class CrashDetectionState( val appName: String, val crashDetected: Boolean, - val eventSink: (CrashDetectionEvents) -> Unit + val eventSink: (CrashDetectionEvent) -> Unit ) diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt index 57d28527ca..5db1d4f076 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt @@ -22,7 +22,7 @@ fun CrashDetectionView( onOpenBugReport: () -> Unit = { }, ) { fun onPopupDismissed() { - state.eventSink(CrashDetectionEvents.ResetAllCrashData) + state.eventSink(CrashDetectionEvent.ResetAllCrashData) } if (state.crashDetected) { diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/DefaultCrashDetectionPresenter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/DefaultCrashDetectionPresenter.kt index 25afadec57..b75d36f21f 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/DefaultCrashDetectionPresenter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/crash/DefaultCrashDetectionPresenter.kt @@ -18,7 +18,7 @@ import androidx.compose.runtime.rememberCoroutineScope import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import io.element.android.features.rageshake.api.RageshakeFeatureAvailability -import io.element.android.features.rageshake.api.crash.CrashDetectionEvents +import io.element.android.features.rageshake.api.crash.CrashDetectionEvent import io.element.android.features.rageshake.api.crash.CrashDetectionPresenter import io.element.android.features.rageshake.api.crash.CrashDetectionState import io.element.android.libraries.core.meta.BuildMeta @@ -48,10 +48,10 @@ class DefaultCrashDetectionPresenter( } }.collectAsState(false) - fun handleEvent(event: CrashDetectionEvents) { + fun handleEvent(event: CrashDetectionEvent) { when (event) { - CrashDetectionEvents.ResetAllCrashData -> localCoroutineScope.resetAll() - CrashDetectionEvents.ResetAppHasCrashed -> localCoroutineScope.resetAppHasCrashed() + CrashDetectionEvent.ResetAllCrashData -> localCoroutineScope.resetAll() + CrashDetectionEvent.ResetAppHasCrashed -> localCoroutineScope.resetAppHasCrashed() } } diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt index dcaaa20a69..b2b496cf39 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt @@ -12,7 +12,7 @@ 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.rageshake.api.crash.CrashDetectionEvents +import io.element.android.features.rageshake.api.crash.CrashDetectionEvent import io.element.android.features.rageshake.impl.crash.A_CRASH_DATA import io.element.android.features.rageshake.impl.crash.DefaultCrashDetectionPresenter import io.element.android.features.rageshake.impl.crash.FakeCrashDataStore @@ -80,7 +80,7 @@ class CrashDetectionPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.crashDetected).isTrue() - initialState.eventSink.invoke(CrashDetectionEvents.ResetAppHasCrashed) + initialState.eventSink.invoke(CrashDetectionEvent.ResetAppHasCrashed) assertThat(awaitItem().crashDetected).isFalse() } } @@ -96,7 +96,7 @@ class CrashDetectionPresenterTest { skipItems(1) val initialState = awaitItem() assertThat(initialState.crashDetected).isTrue() - initialState.eventSink.invoke(CrashDetectionEvents.ResetAllCrashData) + initialState.eventSink.invoke(CrashDetectionEvent.ResetAllCrashData) assertThat(awaitItem().crashDetected).isFalse() } } From 809511a785d5449aeab9a2e08e808138b05107a1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 19 Jan 2026 18:21:31 +0100 Subject: [PATCH 6/6] Use Presenter.test extension --- .../impl/bugreport/BugReportPresenterTest.kt | 48 +++++-------------- .../crash/ui/CrashDetectionPresenterTest.kt | 28 +++-------- .../RageshakeDetectionPresenterTest.kt | 24 +++------- .../RageshakePreferencesPresenterTest.kt | 20 ++------ 4 files changed, 30 insertions(+), 90 deletions(-) diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt index f5b0508063..148c375e25 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.rageshake.impl.bugreport -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.rageshake.api.reporter.BugReporter import io.element.android.features.rageshake.impl.crash.A_CRASH_DATA @@ -22,6 +19,7 @@ import io.element.android.features.rageshake.impl.screenshot.ScreenshotHolder import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.test.A_FAILURE_REASON import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -37,9 +35,7 @@ class BugReportPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.hasCrashLogs).isFalse() assertThat(initialState.formState).isEqualTo(BugReportFormState.Default) @@ -53,9 +49,7 @@ class BugReportPresenterTest { @Test fun `present - set description`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetDescription(A_SHORT_DESCRIPTION)) assertThat(awaitItem().submitEnabled).isTrue() @@ -67,9 +61,7 @@ class BugReportPresenterTest { @Test fun `present - can contact`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetCanContact(true)) assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(canContact = true)) @@ -81,9 +73,7 @@ class BugReportPresenterTest { @Test fun `present - send logs`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // Since this is true by default, start by disabling initialState.eventSink.invoke(BugReportEvents.SetSendLog(false)) @@ -96,9 +86,7 @@ class BugReportPresenterTest { @Test fun `present - send screenshot`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetSendScreenshot(true)) assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(sendScreenshot = true)) @@ -110,9 +98,7 @@ class BugReportPresenterTest { @Test fun `present - send notification settings`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetSendPushRules(true)) assertThat(awaitItem().formState).isEqualTo(BugReportFormState.Default.copy(sendPushRules = true)) @@ -127,9 +113,7 @@ class BugReportPresenterTest { crashDataStore = FakeCrashDataStore(crashData = A_CRASH_DATA, appHasCrashed = true), screenshotHolder = FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.hasCrashLogs).isTrue() @@ -148,9 +132,7 @@ class BugReportPresenterTest { FakeCrashDataStore(crashData = A_CRASH_DATA, appHasCrashed = true), FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetDescription(A_LONG_DESCRIPTION)) skipItems(1) @@ -174,9 +156,7 @@ class BugReportPresenterTest { FakeCrashDataStore(crashData = A_CRASH_DATA, appHasCrashed = true), FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetDescription(A_LONG_DESCRIPTION)) skipItems(1) @@ -200,9 +180,7 @@ class BugReportPresenterTest { @Test fun `present - send failure description too short`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetDescription(A_SHORT_DESCRIPTION)) skipItems(1) @@ -223,9 +201,7 @@ class BugReportPresenterTest { FakeCrashDataStore(crashData = A_CRASH_DATA, appHasCrashed = true), FakeScreenshotHolder(screenshotUri = A_SCREENSHOT_URI), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() initialState.eventSink.invoke(BugReportEvents.SetDescription(A_LONG_DESCRIPTION)) skipItems(1) diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt index b2b496cf39..137f13bdc7 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/crash/ui/CrashDetectionPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.rageshake.impl.crash.ui -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.rageshake.api.crash.CrashDetectionEvent import io.element.android.features.rageshake.impl.crash.A_CRASH_DATA @@ -19,6 +16,7 @@ import io.element.android.features.rageshake.impl.crash.FakeCrashDataStore import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf @@ -33,9 +31,7 @@ class CrashDetectionPresenterTest { @Test fun `present - initial state no crash`() = runTest { val presenter = createPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.crashDetected).isFalse() } @@ -46,9 +42,7 @@ class CrashDetectionPresenterTest { val presenter = createPresenter( FakeCrashDataStore(appHasCrashed = true) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.crashDetected).isTrue() @@ -61,9 +55,7 @@ class CrashDetectionPresenterTest { FakeCrashDataStore(appHasCrashed = true), isFeatureAvailableFlow = flowOf(false), ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.crashDetected).isFalse() } @@ -74,9 +66,7 @@ class CrashDetectionPresenterTest { val presenter = createPresenter( FakeCrashDataStore(appHasCrashed = true) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.crashDetected).isTrue() @@ -90,9 +80,7 @@ class CrashDetectionPresenterTest { val presenter = createPresenter( FakeCrashDataStore(appHasCrashed = true, crashData = A_CRASH_DATA) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.crashDetected).isTrue() @@ -109,9 +97,7 @@ class CrashDetectionPresenterTest { crashDataStore = crashDataStore, isFeatureAvailableFlow = isFeatureAvailableFlow, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.crashDetected).isFalse() crashDataStore.setCrashData("Some crash data") diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt index 9db39e0ee9..1e2a556dff 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/detection/RageshakeDetectionPresenterTest.kt @@ -9,9 +9,6 @@ package io.element.android.features.rageshake.impl.detection import android.graphics.Bitmap -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.rageshake.api.detection.RageshakeDetectionEvent import io.element.android.features.rageshake.api.screenshot.ImageResult @@ -21,6 +18,7 @@ import io.element.android.features.rageshake.impl.rageshake.FakeRageshakeDataSto import io.element.android.features.rageshake.impl.screenshot.FakeScreenshotHolder import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import io.mockk.mockk import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf @@ -57,9 +55,7 @@ class RageshakeDetectionPresenterTest { rageshakeFeatureAvailability = { flowOf(true) }, ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.takeScreenshot).isFalse() @@ -82,9 +78,7 @@ class RageshakeDetectionPresenterTest { rageshakeFeatureAvailability = { flowOf(true) }, ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection) @@ -108,9 +102,7 @@ class RageshakeDetectionPresenterTest { rageshakeFeatureAvailability = { flowOf(true) }, ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.isStarted).isFalse() @@ -143,9 +135,7 @@ class RageshakeDetectionPresenterTest { rageshakeFeatureAvailability = { flowOf(true) }, ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.isStarted).isFalse() @@ -178,9 +168,7 @@ class RageshakeDetectionPresenterTest { rageshakeFeatureAvailability = { flowOf(true) }, ) ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.isStarted).isFalse() diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt index 749d0aefe7..ac491fb860 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/preferences/RageshakePreferencesPresenterTest.kt @@ -8,15 +8,13 @@ package io.element.android.features.rageshake.impl.preferences -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.rageshake.api.preferences.RageshakePreferencesEvent import io.element.android.features.rageshake.impl.rageshake.A_SENSITIVITY import io.element.android.features.rageshake.impl.rageshake.FakeRageShake import io.element.android.features.rageshake.impl.rageshake.FakeRageshakeDataStore import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -33,9 +31,7 @@ class RageshakePreferencesPresenterTest { FakeRageshakeDataStore(isEnabled = true), rageshakeFeatureAvailability = { flowOf(true) }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.isSupported).isTrue() @@ -50,9 +46,7 @@ class RageshakePreferencesPresenterTest { FakeRageshakeDataStore(isEnabled = true), rageshakeFeatureAvailability = { flowOf(true) }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.isSupported).isFalse() @@ -67,9 +61,7 @@ class RageshakePreferencesPresenterTest { FakeRageshakeDataStore(isEnabled = true), rageshakeFeatureAvailability = { flowOf(true) }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.isEnabled).isTrue() @@ -87,9 +79,7 @@ class RageshakePreferencesPresenterTest { FakeRageshakeDataStore(isEnabled = true), rageshakeFeatureAvailability = { flowOf(true) }, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem() assertThat(initialState.sensitivity).isEqualTo(A_SENSITIVITY)