RageshakeDetectionEvents -> RageshakeDetectionEvent

This commit is contained in:
Benoit Marty 2026-01-19 18:17:58 +01:00
parent 31fc60f40e
commit dca227d3d7
6 changed files with 33 additions and 33 deletions

View file

@ -17,7 +17,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.rageshake.api.crash.CrashDetectionEvents 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.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.features.rageshake.api.detection.RageshakeDetectionView
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@ -40,7 +40,7 @@ fun RootView(
fun onOpenBugReport() { fun onOpenBugReport() {
state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed) state.crashDetectionState.eventSink(CrashDetectionEvents.ResetAppHasCrashed)
state.rageshakeDetectionState.eventSink(RageshakeDetectionEvents.Dismiss) state.rageshakeDetectionState.eventSink(RageshakeDetectionEvent.Dismiss)
onOpenBugReport.invoke() onOpenBugReport.invoke()
} }

View file

@ -10,10 +10,10 @@ package io.element.android.features.rageshake.api.detection
import io.element.android.features.rageshake.api.screenshot.ImageResult import io.element.android.features.rageshake.api.screenshot.ImageResult
sealed interface RageshakeDetectionEvents { sealed interface RageshakeDetectionEvent {
data object Dismiss : RageshakeDetectionEvents data object Dismiss : RageshakeDetectionEvent
data object Disable : RageshakeDetectionEvents data object Disable : RageshakeDetectionEvent
data object StartDetection : RageshakeDetectionEvents data object StartDetection : RageshakeDetectionEvent
data object StopDetection : RageshakeDetectionEvents data object StopDetection : RageshakeDetectionEvent
data class ProcessScreenshot(val imageResult: ImageResult) : RageshakeDetectionEvents data class ProcessScreenshot(val imageResult: ImageResult) : RageshakeDetectionEvent
} }

View file

@ -15,5 +15,5 @@ data class RageshakeDetectionState(
val showDialog: Boolean, val showDialog: Boolean,
val isStarted: Boolean, val isStarted: Boolean,
val preferenceState: RageshakePreferencesState, val preferenceState: RageshakePreferencesState,
val eventSink: (RageshakeDetectionEvents) -> Unit val eventSink: (RageshakeDetectionEvent) -> Unit
) )

View file

@ -35,22 +35,22 @@ fun RageshakeDetectionView(
val context = LocalContext.current val context = LocalContext.current
OnLifecycleEvent { _, event -> OnLifecycleEvent { _, event ->
when (event) { when (event) {
Lifecycle.Event.ON_RESUME -> eventSink(RageshakeDetectionEvents.StartDetection) Lifecycle.Event.ON_RESUME -> eventSink(RageshakeDetectionEvent.StartDetection)
Lifecycle.Event.ON_PAUSE -> eventSink(RageshakeDetectionEvents.StopDetection) Lifecycle.Event.ON_PAUSE -> eventSink(RageshakeDetectionEvent.StopDetection)
else -> Unit else -> Unit
} }
} }
when { when {
state.takeScreenshot -> TakeScreenshot( state.takeScreenshot -> TakeScreenshot(
onScreenshot = { eventSink(RageshakeDetectionEvents.ProcessScreenshot(it)) } onScreenshot = { eventSink(RageshakeDetectionEvent.ProcessScreenshot(it)) }
) )
state.showDialog -> { state.showDialog -> {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
context.vibrate() context.vibrate()
} }
RageshakeDialogContent( RageshakeDialogContent(
onNoClick = { eventSink(RageshakeDetectionEvents.Dismiss) }, onNoClick = { eventSink(RageshakeDetectionEvent.Dismiss) },
onDisableClick = { eventSink(RageshakeDetectionEvents.Disable) }, onDisableClick = { eventSink(RageshakeDetectionEvent.Disable) },
onYesClick = onOpenBugReport onYesClick = onOpenBugReport
) )
} }

View file

@ -16,7 +16,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding 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.RageshakeDetectionPresenter
import io.element.android.features.rageshake.api.detection.RageshakeDetectionState 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.RageshakePreferencesEvents
@ -48,16 +48,16 @@ class DefaultRageshakeDetectionPresenter(
mutableStateOf(false) mutableStateOf(false)
} }
fun handleEvent(event: RageshakeDetectionEvents) { fun handleEvent(event: RageshakeDetectionEvent) {
when (event) { when (event) {
RageshakeDetectionEvents.Disable -> { RageshakeDetectionEvent.Disable -> {
preferencesState.eventSink(RageshakePreferencesEvents.SetIsEnabled(false)) preferencesState.eventSink(RageshakePreferencesEvents.SetIsEnabled(false))
showDialog.value = false showDialog.value = false
} }
RageshakeDetectionEvents.StartDetection -> isStarted.value = true RageshakeDetectionEvent.StartDetection -> isStarted.value = true
RageshakeDetectionEvents.StopDetection -> isStarted.value = false RageshakeDetectionEvent.StopDetection -> isStarted.value = false
is RageshakeDetectionEvents.ProcessScreenshot -> localCoroutineScope.processScreenshot(takeScreenshot, showDialog, event.imageResult) is RageshakeDetectionEvent.ProcessScreenshot -> localCoroutineScope.processScreenshot(takeScreenshot, showDialog, event.imageResult)
RageshakeDetectionEvents.Dismiss -> showDialog.value = false RageshakeDetectionEvent.Dismiss -> showDialog.value = false
} }
} }

View file

@ -13,7 +13,7 @@ import app.cash.molecule.RecompositionMode
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.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.api.screenshot.ImageResult
import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePreferencesPresenter
import io.element.android.features.rageshake.impl.rageshake.FakeRageShake import io.element.android.features.rageshake.impl.rageshake.FakeRageShake
@ -87,9 +87,9 @@ class RageshakeDetectionPresenterTest {
}.test { }.test {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection)
assertThat(awaitItem().isStarted).isTrue() assertThat(awaitItem().isStarted).isTrue()
initialState.eventSink.invoke(RageshakeDetectionEvents.StopDetection) initialState.eventSink.invoke(RageshakeDetectionEvent.StopDetection)
assertThat(awaitItem().isStarted).isFalse() assertThat(awaitItem().isStarted).isFalse()
} }
} }
@ -114,15 +114,15 @@ class RageshakeDetectionPresenterTest {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.isStarted).isFalse() assertThat(initialState.isStarted).isFalse()
initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection)
assertThat(awaitItem().isStarted).isTrue() assertThat(awaitItem().isStarted).isTrue()
rageshake.triggerPhoneRageshake() rageshake.triggerPhoneRageshake()
assertThat(awaitItem().takeScreenshot).isTrue() assertThat(awaitItem().takeScreenshot).isTrue()
initialState.eventSink.invoke( initialState.eventSink.invoke(
RageshakeDetectionEvents.ProcessScreenshot(ImageResult.Success(aBitmap)) RageshakeDetectionEvent.ProcessScreenshot(ImageResult.Success(aBitmap))
) )
assertThat(awaitItem().showDialog).isTrue() assertThat(awaitItem().showDialog).isTrue()
initialState.eventSink.invoke(RageshakeDetectionEvents.Dismiss) initialState.eventSink.invoke(RageshakeDetectionEvent.Dismiss)
val finalState = awaitItem() val finalState = awaitItem()
assertThat(finalState.showDialog).isFalse() assertThat(finalState.showDialog).isFalse()
assertThat(rageshakeDataStore.isEnabled().first()).isTrue() assertThat(rageshakeDataStore.isEnabled().first()).isTrue()
@ -149,15 +149,15 @@ class RageshakeDetectionPresenterTest {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.isStarted).isFalse() assertThat(initialState.isStarted).isFalse()
initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection)
assertThat(awaitItem().isStarted).isTrue() assertThat(awaitItem().isStarted).isTrue()
rageshake.triggerPhoneRageshake() rageshake.triggerPhoneRageshake()
assertThat(awaitItem().takeScreenshot).isTrue() assertThat(awaitItem().takeScreenshot).isTrue()
initialState.eventSink.invoke( initialState.eventSink.invoke(
RageshakeDetectionEvents.ProcessScreenshot(ImageResult.Error(AN_EXCEPTION)) RageshakeDetectionEvent.ProcessScreenshot(ImageResult.Error(AN_EXCEPTION))
) )
assertThat(awaitItem().showDialog).isTrue() assertThat(awaitItem().showDialog).isTrue()
initialState.eventSink.invoke(RageshakeDetectionEvents.Dismiss) initialState.eventSink.invoke(RageshakeDetectionEvent.Dismiss)
val finalState = awaitItem() val finalState = awaitItem()
assertThat(finalState.showDialog).isFalse() assertThat(finalState.showDialog).isFalse()
assertThat(rageshakeDataStore.isEnabled().first()).isTrue() assertThat(rageshakeDataStore.isEnabled().first()).isTrue()
@ -184,15 +184,15 @@ class RageshakeDetectionPresenterTest {
skipItems(1) skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.isStarted).isFalse() assertThat(initialState.isStarted).isFalse()
initialState.eventSink.invoke(RageshakeDetectionEvents.StartDetection) initialState.eventSink.invoke(RageshakeDetectionEvent.StartDetection)
assertThat(awaitItem().isStarted).isTrue() assertThat(awaitItem().isStarted).isTrue()
rageshake.triggerPhoneRageshake() rageshake.triggerPhoneRageshake()
assertThat(awaitItem().takeScreenshot).isTrue() assertThat(awaitItem().takeScreenshot).isTrue()
initialState.eventSink.invoke( initialState.eventSink.invoke(
RageshakeDetectionEvents.ProcessScreenshot(ImageResult.Success(aBitmap)) RageshakeDetectionEvent.ProcessScreenshot(ImageResult.Success(aBitmap))
) )
assertThat(awaitItem().showDialog).isTrue() assertThat(awaitItem().showDialog).isTrue()
initialState.eventSink.invoke(RageshakeDetectionEvents.Disable) initialState.eventSink.invoke(RageshakeDetectionEvent.Disable)
skipItems(1) skipItems(1)
assertThat(awaitItem().showDialog).isFalse() assertThat(awaitItem().showDialog).isFalse()
assertThat(rageshakeDataStore.isEnabled().first()).isFalse() assertThat(rageshakeDataStore.isEnabled().first()).isFalse()