DeclineAndBlockEvents -> DeclineAndBlockEvent

This commit is contained in:
Benoit Marty
2026-08-25 09:55:46 +02:00
parent e395efe730
commit 4c56833ada
7 changed files with 38 additions and 38 deletions
@@ -8,10 +8,10 @@
package io.element.android.features.invite.impl.declineandblock package io.element.android.features.invite.impl.declineandblock
sealed interface DeclineAndBlockEvents { sealed interface DeclineAndBlockEvent {
data class UpdateReportReason(val reason: String) : DeclineAndBlockEvents data class UpdateReportReason(val reason: String) : DeclineAndBlockEvent
data object ToggleReportRoom : DeclineAndBlockEvents data object ToggleReportRoom : DeclineAndBlockEvent
data object ToggleBlockUser : DeclineAndBlockEvents data object ToggleBlockUser : DeclineAndBlockEvent
data object Decline : DeclineAndBlockEvents data object Decline : DeclineAndBlockEvent
data object ClearDeclineAction : DeclineAndBlockEvents data object ClearDeclineAction : DeclineAndBlockEvent
} }
@@ -49,13 +49,13 @@ class DeclineAndBlockPresenter(
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
fun handleEvent(event: DeclineAndBlockEvents) { fun handleEvent(event: DeclineAndBlockEvent) {
when (event) { when (event) {
DeclineAndBlockEvents.ClearDeclineAction -> declineAction.value = AsyncAction.Uninitialized DeclineAndBlockEvent.ClearDeclineAction -> declineAction.value = AsyncAction.Uninitialized
DeclineAndBlockEvents.Decline -> coroutineScope.decline(reportReason, blockUser, reportRoom, declineAction) DeclineAndBlockEvent.Decline -> coroutineScope.decline(reportReason, blockUser, reportRoom, declineAction)
DeclineAndBlockEvents.ToggleBlockUser -> blockUser = !blockUser DeclineAndBlockEvent.ToggleBlockUser -> blockUser = !blockUser
DeclineAndBlockEvents.ToggleReportRoom -> reportRoom = !reportRoom DeclineAndBlockEvent.ToggleReportRoom -> reportRoom = !reportRoom
is DeclineAndBlockEvents.UpdateReportReason -> reportReason = event.reason is DeclineAndBlockEvent.UpdateReportReason -> reportReason = event.reason
} }
} }
@@ -15,7 +15,7 @@ data class DeclineAndBlockState(
val reportReason: String, val reportReason: String,
val blockUser: Boolean, val blockUser: Boolean,
val declineAction: AsyncAction<Unit>, val declineAction: AsyncAction<Unit>,
val eventSink: (DeclineAndBlockEvents) -> Unit val eventSink: (DeclineAndBlockEvent) -> Unit
) { ) {
val canDecline = blockUser || reportRoom && reportReason.isNotEmpty() val canDecline = blockUser || reportRoom && reportReason.isNotEmpty()
} }
@@ -36,7 +36,7 @@ fun aDeclineAndBlockState(
reportReason: String = "", reportReason: String = "",
blockUser: Boolean = false, blockUser: Boolean = false,
declineAction: AsyncAction<Unit> = AsyncAction.Uninitialized, declineAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
eventSink: (DeclineAndBlockEvents) -> Unit = {}, eventSink: (DeclineAndBlockEvent) -> Unit = {},
) = DeclineAndBlockState( ) = DeclineAndBlockState(
reportRoom = reportRoom, reportRoom = reportRoom,
reportReason = reportReason, reportReason = reportReason,
@@ -56,8 +56,8 @@ fun DeclineAndBlockView(
async = state.declineAction, async = state.declineAction,
onSuccess = { onDeclineSuccess() }, onSuccess = { onDeclineSuccess() },
errorMessage = { stringResource(CommonStrings.error_unknown) }, errorMessage = { stringResource(CommonStrings.error_unknown) },
onRetry = { state.eventSink(DeclineAndBlockEvents.Decline) }, onRetry = { state.eventSink(DeclineAndBlockEvent.Decline) },
onErrorDismiss = { state.eventSink(DeclineAndBlockEvents.ClearDeclineAction) } onErrorDismiss = { state.eventSink(DeclineAndBlockEvent.ClearDeclineAction) }
) )
Scaffold( Scaffold(
@@ -89,7 +89,7 @@ fun DeclineAndBlockView(
Text(text = stringResource(R.string.screen_decline_and_block_block_user_option_description)) Text(text = stringResource(R.string.screen_decline_and_block_block_user_option_description))
}, },
onClick = { onClick = {
state.eventSink(DeclineAndBlockEvents.ToggleBlockUser) state.eventSink(DeclineAndBlockEvent.ToggleBlockUser)
}, },
trailingContent = ListItemContent.Switch(checked = state.blockUser) trailingContent = ListItemContent.Switch(checked = state.blockUser)
) )
@@ -104,7 +104,7 @@ fun DeclineAndBlockView(
Text(text = stringResource(R.string.screen_decline_and_block_report_user_option_description)) Text(text = stringResource(R.string.screen_decline_and_block_report_user_option_description))
}, },
onClick = { onClick = {
state.eventSink(DeclineAndBlockEvents.ToggleReportRoom) state.eventSink(DeclineAndBlockEvent.ToggleReportRoom)
}, },
trailingContent = ListItemContent.Switch(checked = state.reportRoom) trailingContent = ListItemContent.Switch(checked = state.reportRoom)
) )
@@ -113,7 +113,7 @@ fun DeclineAndBlockView(
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
TextField( TextField(
value = state.reportReason, value = state.reportReason,
onValueChange = { state.eventSink(DeclineAndBlockEvents.UpdateReportReason(it)) }, onValueChange = { state.eventSink(DeclineAndBlockEvent.UpdateReportReason(it)) },
placeholder = stringResource(R.string.screen_decline_and_block_report_user_reason_placeholder), placeholder = stringResource(R.string.screen_decline_and_block_report_user_reason_placeholder),
minLines = 3, minLines = 3,
enabled = !isDeclining, enabled = !isDeclining,
@@ -132,7 +132,7 @@ fun DeclineAndBlockView(
enabled = !isDeclining && state.canDecline, enabled = !isDeclining && state.canDecline,
onClick = { onClick = {
focusManager.clearFocus(force = true) focusManager.clearFocus(force = true)
state.eventSink(DeclineAndBlockEvents.Decline) state.eventSink(DeclineAndBlockEvent.Decline)
}, },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -53,21 +53,21 @@ class DeclineAndBlockPresenterTest {
assertThat(state.blockUser).isTrue() assertThat(state.blockUser).isTrue()
assertThat(state.reportReason).isEmpty() assertThat(state.reportReason).isEmpty()
assertThat(state.canDecline).isTrue() assertThat(state.canDecline).isTrue()
state.eventSink(DeclineAndBlockEvents.ToggleBlockUser) state.eventSink(DeclineAndBlockEvent.ToggleBlockUser)
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.reportRoom).isFalse() assertThat(state.reportRoom).isFalse()
assertThat(state.blockUser).isFalse() assertThat(state.blockUser).isFalse()
assertThat(state.reportReason).isEmpty() assertThat(state.reportReason).isEmpty()
assertThat(state.canDecline).isFalse() assertThat(state.canDecline).isFalse()
state.eventSink(DeclineAndBlockEvents.ToggleReportRoom) state.eventSink(DeclineAndBlockEvent.ToggleReportRoom)
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.reportRoom).isTrue() assertThat(state.reportRoom).isTrue()
assertThat(state.blockUser).isFalse() assertThat(state.blockUser).isFalse()
assertThat(state.reportReason).isEmpty() assertThat(state.reportReason).isEmpty()
assertThat(state.canDecline).isFalse() assertThat(state.canDecline).isFalse()
state.eventSink(DeclineAndBlockEvents.UpdateReportReason("Spam")) state.eventSink(DeclineAndBlockEvent.UpdateReportReason("Spam"))
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.reportRoom).isTrue() assertThat(state.reportRoom).isTrue()
@@ -87,7 +87,7 @@ class DeclineAndBlockPresenterTest {
) )
presenter.test { presenter.test {
awaitItem().also { state -> awaitItem().also { state ->
state.eventSink(DeclineAndBlockEvents.Decline) state.eventSink(DeclineAndBlockEvent.Decline)
} }
assertThat(awaitItem().declineAction.isLoading()).isTrue() assertThat(awaitItem().declineAction.isLoading()).isTrue()
awaitItem().also { state -> awaitItem().also { state ->
@@ -110,12 +110,12 @@ class DeclineAndBlockPresenterTest {
) )
presenter.test { presenter.test {
awaitItem().also { state -> awaitItem().also { state ->
state.eventSink(DeclineAndBlockEvents.Decline) state.eventSink(DeclineAndBlockEvent.Decline)
} }
assertThat(awaitItem().declineAction.isLoading()).isTrue() assertThat(awaitItem().declineAction.isLoading()).isTrue()
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat(state.declineAction).isInstanceOf(AsyncAction.Failure::class.java)
state.eventSink(DeclineAndBlockEvents.ClearDeclineAction) state.eventSink(DeclineAndBlockEvent.ClearDeclineAction)
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isInstanceOf(AsyncAction.Uninitialized::class.java) assertThat(state.declineAction).isInstanceOf(AsyncAction.Uninitialized::class.java)
@@ -137,7 +137,7 @@ class DeclineAndBlockPresenterTest {
) )
presenter.test { presenter.test {
awaitItem().also { state -> awaitItem().also { state ->
state.eventSink(DeclineAndBlockEvents.Decline) state.eventSink(DeclineAndBlockEvent.Decline)
} }
assertThat(awaitItem().declineAction.isLoading()).isTrue() assertThat(awaitItem().declineAction.isLoading()).isTrue()
awaitItem().also { state -> awaitItem().also { state ->
@@ -30,7 +30,7 @@ import org.junit.Test
class DeclineAndBlockViewTest : RobolectricTest() { class DeclineAndBlockViewTest : RobolectricTest() {
@Test @Test
fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest { fun `clicking on back invoke the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>(expectEvents = false) val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>(expectEvents = false)
ensureCalledOnce { ensureCalledOnce {
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
@@ -44,7 +44,7 @@ class DeclineAndBlockViewTest : RobolectricTest() {
@Test @Test
fun `a successful decline invokes the expected callback`() = runAndroidComposeUiTest { fun `a successful decline invokes the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>(expectEvents = false) val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>(expectEvents = false)
ensureCalledOnce { ensureCalledOnce {
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
@@ -58,7 +58,7 @@ class DeclineAndBlockViewTest : RobolectricTest() {
@Test @Test
fun `clicking on decline when enabled emits the expected event`() = runAndroidComposeUiTest { fun `clicking on decline when enabled emits the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>() val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>()
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
blockUser = true, blockUser = true,
@@ -66,12 +66,12 @@ class DeclineAndBlockViewTest : RobolectricTest() {
), ),
) )
clickOn(CommonStrings.action_decline) clickOn(CommonStrings.action_decline)
eventsRecorder.assertSingle(DeclineAndBlockEvents.Decline) eventsRecorder.assertSingle(DeclineAndBlockEvent.Decline)
} }
@Test @Test
fun `clicking on decline when disabled does not emit event`() = runAndroidComposeUiTest { fun `clicking on decline when disabled does not emit event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>(expectEvents = false) val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>(expectEvents = false)
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
blockUser = false, blockUser = false,
@@ -85,7 +85,7 @@ class DeclineAndBlockViewTest : RobolectricTest() {
@Test @Test
fun `clicking on block option emits the expected event`() = runAndroidComposeUiTest { fun `clicking on block option emits the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>() val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>()
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
blockUser = true, blockUser = true,
@@ -93,12 +93,12 @@ class DeclineAndBlockViewTest : RobolectricTest() {
), ),
) )
clickOn(R.string.screen_decline_and_block_block_user_option_title) clickOn(R.string.screen_decline_and_block_block_user_option_title)
eventsRecorder.assertSingle(DeclineAndBlockEvents.ToggleBlockUser) eventsRecorder.assertSingle(DeclineAndBlockEvent.ToggleBlockUser)
} }
@Test @Test
fun `clicking on report room option emits the expected event`() = runAndroidComposeUiTest { fun `clicking on report room option emits the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>() val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>()
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
reportRoom = true, reportRoom = true,
@@ -106,12 +106,12 @@ class DeclineAndBlockViewTest : RobolectricTest() {
), ),
) )
clickOn(CommonStrings.action_report_room) clickOn(CommonStrings.action_report_room)
eventsRecorder.assertSingle(DeclineAndBlockEvents.ToggleReportRoom) eventsRecorder.assertSingle(DeclineAndBlockEvent.ToggleReportRoom)
} }
@Test @Test
fun `typing text in the reason field emits the expected Event`() = runAndroidComposeUiTest { fun `typing text in the reason field emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<DeclineAndBlockEvents>() val eventsRecorder = EventsRecorder<DeclineAndBlockEvent>()
setDeclineAndBlockView( setDeclineAndBlockView(
aDeclineAndBlockState( aDeclineAndBlockState(
reportRoom = true, reportRoom = true,
@@ -120,7 +120,7 @@ class DeclineAndBlockViewTest : RobolectricTest() {
), ),
) )
onNodeWithText("").performTextInput("Spam!") onNodeWithText("").performTextInput("Spam!")
eventsRecorder.assertSingle(DeclineAndBlockEvents.UpdateReportReason("Spam!")) eventsRecorder.assertSingle(DeclineAndBlockEvent.UpdateReportReason("Spam!"))
} }
} }