DirectLogoutEvents -> DirectLogoutEvent

This commit is contained in:
Benoit Marty
2026-08-25 10:05:04 +02:00
parent a039fcd655
commit 93efe3348f
10 changed files with 42 additions and 42 deletions
@@ -15,7 +15,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import dev.zacsweers.metro.Inject
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
@@ -67,7 +67,7 @@ class ChooseSelfVerificationModePresenter(
fun handleEvent(event: ChooseSelfVerificationModeEvent) {
when (event) {
ChooseSelfVerificationModeEvent.SignOut -> directLogoutState.eventSink(DirectLogoutEvents.Logout(ignoreSdkError = false))
ChooseSelfVerificationModeEvent.SignOut -> directLogoutState.eventSink(DirectLogoutEvent.Logout(ignoreSdkError = false))
}
}
@@ -9,7 +9,7 @@
package io.element.android.features.ftue.impl.sessionverification.choosemode
import com.google.common.truth.Truth.assertThat
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.api.direct.aDirectLogoutState
import io.element.android.libraries.architecture.AsyncData
@@ -112,7 +112,7 @@ class ChooseSessionVerificationModePresenterTest {
@Test
fun `sing out action triggers a direct logout`() = runTest {
val logoutEventRecorder = lambdaRecorder<DirectLogoutEvents, Unit> {}
val logoutEventRecorder = lambdaRecorder<DirectLogoutEvent, Unit> {}
val logoutPresenter = Presenter<DirectLogoutState> {
aDirectLogoutState(eventSink = logoutEventRecorder)
}
@@ -121,7 +121,7 @@ class ChooseSessionVerificationModePresenterTest {
val initial = awaitItem()
initial.eventSink(ChooseSelfVerificationModeEvent.SignOut)
logoutEventRecorder.assertions().isCalledOnce()
.with(value(DirectLogoutEvents.Logout(ignoreSdkError = false)))
.with(value(DirectLogoutEvent.Logout(ignoreSdkError = false)))
}
}
@@ -8,7 +8,7 @@
package io.element.android.features.logout.api.direct
sealed interface DirectLogoutEvents {
data class Logout(val ignoreSdkError: Boolean) : DirectLogoutEvents
data object CloseDialogs : DirectLogoutEvents
sealed interface DirectLogoutEvent {
data class Logout(val ignoreSdkError: Boolean) : DirectLogoutEvent
data object CloseDialogs : DirectLogoutEvent
}
@@ -13,5 +13,5 @@ import io.element.android.libraries.architecture.AsyncAction
data class DirectLogoutState(
val canDoDirectSignOut: Boolean,
val logoutAction: AsyncAction<Unit>,
val eventSink: (DirectLogoutEvents) -> Unit,
val eventSink: (DirectLogoutEvent) -> Unit,
)
@@ -25,7 +25,7 @@ open class DirectLogoutStatePreviewParam : PreviewParameterProvider<DirectLogout
fun aDirectLogoutState(
canDoDirectSignOut: Boolean = true,
logoutAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
eventSink: (DirectLogoutEvents) -> Unit = {},
eventSink: (DirectLogoutEvent) -> Unit = {},
) = DirectLogoutState(
canDoDirectSignOut = canDoDirectSignOut,
logoutAction = logoutAction,
@@ -11,7 +11,7 @@ package io.element.android.features.logout.impl.direct
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewParameter
import dev.zacsweers.metro.ContributesBinding
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.api.direct.DirectLogoutStatePreviewParam
import io.element.android.features.logout.api.direct.DirectLogoutView
@@ -28,13 +28,13 @@ class DefaultDirectLogoutView : DirectLogoutView {
LogoutActionDialog(
state.logoutAction,
onConfirmClick = {
eventSink(DirectLogoutEvents.Logout(ignoreSdkError = false))
eventSink(DirectLogoutEvent.Logout(ignoreSdkError = false))
},
onForceLogoutClick = {
eventSink(DirectLogoutEvents.Logout(ignoreSdkError = true))
eventSink(DirectLogoutEvent.Logout(ignoreSdkError = true))
},
onDismissDialog = {
eventSink(DirectLogoutEvents.CloseDialogs)
eventSink(DirectLogoutEvent.CloseDialogs)
},
)
}
@@ -16,7 +16,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import dev.zacsweers.metro.Inject
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.impl.tools.isBackingUp
import io.element.android.libraries.architecture.AsyncAction
@@ -48,16 +48,16 @@ class DirectLogoutPresenter(
val isLastDevice by encryptionService.isLastDevice.collectAsState()
fun handleEvent(event: DirectLogoutEvents) {
fun handleEvent(event: DirectLogoutEvent) {
when (event) {
is DirectLogoutEvents.Logout -> {
is DirectLogoutEvent.Logout -> {
if (logoutAction.value.isConfirming() || event.ignoreSdkError) {
localCoroutineScope.logout(logoutAction, event.ignoreSdkError)
} else {
logoutAction.value = AsyncAction.ConfirmingNoParams
}
}
DirectLogoutEvents.CloseDialogs -> {
DirectLogoutEvent.CloseDialogs -> {
logoutAction.value = AsyncAction.Uninitialized
}
}
@@ -14,7 +14,7 @@ import androidx.activity.ComponentActivity
import androidx.compose.ui.test.AndroidComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.v2.runAndroidComposeUiTest
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.features.logout.api.direct.DirectLogoutState
import io.element.android.features.logout.api.direct.aDirectLogoutState
import io.element.android.libraries.architecture.AsyncAction
@@ -29,7 +29,7 @@ import org.junit.Test
class DefaultDirectLogoutViewTest : RobolectricTest() {
@Test
fun `clicking on confirm logout sends expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DirectLogoutEvents>()
val eventsRecorder = EventsRecorder<DirectLogoutEvent>()
setDefaultDirectLogoutView(
state = aDirectLogoutState(
logoutAction = AsyncAction.ConfirmingNoParams,
@@ -37,12 +37,12 @@ class DefaultDirectLogoutViewTest : RobolectricTest() {
)
)
clickOn(CommonStrings.action_signout)
eventsRecorder.assertSingle(DirectLogoutEvents.Logout(false))
eventsRecorder.assertSingle(DirectLogoutEvent.Logout(false))
}
@Test
fun `clicking on cancel logout sends expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DirectLogoutEvents>()
val eventsRecorder = EventsRecorder<DirectLogoutEvent>()
setDefaultDirectLogoutView(
state = aDirectLogoutState(
logoutAction = AsyncAction.ConfirmingNoParams,
@@ -50,13 +50,13 @@ class DefaultDirectLogoutViewTest : RobolectricTest() {
)
)
clickOn(CommonStrings.action_cancel)
eventsRecorder.assertSingle(DirectLogoutEvents.CloseDialogs)
eventsRecorder.assertSingle(DirectLogoutEvent.CloseDialogs)
}
@Ignore("Pressing back key should dismiss the dialog, and so generate the expected event, but it's not the case.")
@Test
fun `clicking on back invoke back callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DirectLogoutEvents>()
val eventsRecorder = EventsRecorder<DirectLogoutEvent>()
setDefaultDirectLogoutView(
state = aDirectLogoutState(
logoutAction = AsyncAction.ConfirmingNoParams,
@@ -64,12 +64,12 @@ class DefaultDirectLogoutViewTest : RobolectricTest() {
)
)
pressBackKey()
eventsRecorder.assertSingle(DirectLogoutEvents.CloseDialogs)
eventsRecorder.assertSingle(DirectLogoutEvent.CloseDialogs)
}
@Test
fun `clicking on confirm after error sends expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DirectLogoutEvents>()
val eventsRecorder = EventsRecorder<DirectLogoutEvent>()
setDefaultDirectLogoutView(
state = aDirectLogoutState(
logoutAction = AsyncAction.Failure(Exception("Error")),
@@ -77,12 +77,12 @@ class DefaultDirectLogoutViewTest : RobolectricTest() {
)
)
clickOn(CommonStrings.action_signout_anyway)
eventsRecorder.assertSingle(DirectLogoutEvents.Logout(true))
eventsRecorder.assertSingle(DirectLogoutEvent.Logout(true))
}
@Test
fun `clicking on cancel after error sends expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DirectLogoutEvents>()
val eventsRecorder = EventsRecorder<DirectLogoutEvent>()
setDefaultDirectLogoutView(
state = aDirectLogoutState(
logoutAction = AsyncAction.Failure(Exception("Error")),
@@ -90,7 +90,7 @@ class DefaultDirectLogoutViewTest : RobolectricTest() {
)
)
clickOn(CommonStrings.action_cancel)
eventsRecorder.assertSingle(DirectLogoutEvents.CloseDialogs)
eventsRecorder.assertSingle(DirectLogoutEvent.CloseDialogs)
}
}
@@ -13,7 +13,7 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.ReceiveTurbine
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
@@ -87,10 +87,10 @@ class DirectLogoutPresenterTest {
presenter.present()
}.test {
val initialState = awaitFirstItem()
initialState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
initialState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val confirmationState = awaitItem()
assertThat(confirmationState.logoutAction).isEqualTo(AsyncAction.ConfirmingNoParams)
initialState.eventSink.invoke(DirectLogoutEvents.CloseDialogs)
initialState.eventSink.invoke(DirectLogoutEvent.CloseDialogs)
val finalState = awaitItem()
assertThat(finalState.logoutAction).isEqualTo(AsyncAction.Uninitialized)
}
@@ -103,10 +103,10 @@ class DirectLogoutPresenterTest {
presenter.present()
}.test {
val initialState = awaitFirstItem()
initialState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
initialState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val confirmationState = awaitItem()
assertThat(confirmationState.logoutAction).isEqualTo(AsyncAction.ConfirmingNoParams)
confirmationState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
confirmationState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val loadingState = awaitItem()
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
val successState = awaitItem()
@@ -128,15 +128,15 @@ class DirectLogoutPresenterTest {
presenter.present()
}.test {
val initialState = awaitFirstItem()
initialState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
initialState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val confirmationState = awaitItem()
assertThat(confirmationState.logoutAction).isEqualTo(AsyncAction.ConfirmingNoParams)
confirmationState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
confirmationState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val loadingState = awaitItem()
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
val errorState = awaitItem()
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
errorState.eventSink.invoke(DirectLogoutEvents.CloseDialogs)
errorState.eventSink.invoke(DirectLogoutEvent.CloseDialogs)
val finalState = awaitItem()
assertThat(finalState.logoutAction).isEqualTo(AsyncAction.Uninitialized)
}
@@ -158,15 +158,15 @@ class DirectLogoutPresenterTest {
presenter.present()
}.test {
val initialState = awaitFirstItem()
initialState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
initialState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val confirmationState = awaitItem()
assertThat(confirmationState.logoutAction).isEqualTo(AsyncAction.ConfirmingNoParams)
confirmationState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = false))
confirmationState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = false))
val loadingState = awaitItem()
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
val errorState = awaitItem()
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
errorState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = true))
errorState.eventSink.invoke(DirectLogoutEvent.Logout(ignoreSdkError = true))
val loadingState2 = awaitItem()
assertThat(loadingState2.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
val successState = awaitItem()
@@ -19,7 +19,7 @@ import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedInject
import io.element.android.annotations.ContributesNode
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.logout.api.direct.DirectLogoutEvents
import io.element.android.features.logout.api.direct.DirectLogoutEvent
import io.element.android.features.logout.api.direct.DirectLogoutView
import io.element.android.libraries.androidutils.browser.openUrlInChromeCustomTab
import io.element.android.libraries.architecture.callback
@@ -96,7 +96,7 @@ class PreferencesRootNode(
onOpenBlockedUsers = callback::navigateToBlockedUsers,
onSignOutClick = {
if (state.directLogoutState.canDoDirectSignOut) {
state.directLogoutState.eventSink(DirectLogoutEvents.Logout(ignoreSdkError = false))
state.directLogoutState.eventSink(DirectLogoutEvent.Logout(ignoreSdkError = false))
} else {
callback.startSignOutFlow()
}