RolesAndPermissionsEvents -> RolesAndPermissionsEvent

This commit is contained in:
Benoit Marty
2026-08-25 10:15:35 +02:00
parent fc8d3b3065
commit 4e2d99c968
7 changed files with 44 additions and 44 deletions
@@ -10,9 +10,9 @@ package io.element.android.features.rolesandpermissions.impl.root
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
sealed interface RolesAndPermissionsEvents { sealed interface RolesAndPermissionsEvent {
data object ChangeOwnRole : RolesAndPermissionsEvents data object ChangeOwnRole : RolesAndPermissionsEvent
data class DemoteSelfTo(val role: RoomMember.Role) : RolesAndPermissionsEvents data class DemoteSelfTo(val role: RoomMember.Role) : RolesAndPermissionsEvent
data object ResetPermissions : RolesAndPermissionsEvents data object ResetPermissions : RolesAndPermissionsEvent
data object CancelPendingAction : RolesAndPermissionsEvents data object CancelPendingAction : RolesAndPermissionsEvent
} }
@@ -63,20 +63,20 @@ class RolesAndPermissionsPresenter(
val changeOwnRoleAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) } val changeOwnRoleAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
val resetPermissionsAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) } val resetPermissionsAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
fun handleEvent(event: RolesAndPermissionsEvents) { fun handleEvent(event: RolesAndPermissionsEvent) {
when (event) { when (event) {
is RolesAndPermissionsEvents.ChangeOwnRole -> { is RolesAndPermissionsEvent.ChangeOwnRole -> {
changeOwnRoleAction.value = AsyncAction.ConfirmingNoParams changeOwnRoleAction.value = AsyncAction.ConfirmingNoParams
} }
is RolesAndPermissionsEvents.CancelPendingAction -> { is RolesAndPermissionsEvent.CancelPendingAction -> {
changeOwnRoleAction.value = AsyncAction.Uninitialized changeOwnRoleAction.value = AsyncAction.Uninitialized
resetPermissionsAction.value = AsyncAction.Uninitialized resetPermissionsAction.value = AsyncAction.Uninitialized
} }
is RolesAndPermissionsEvents.DemoteSelfTo -> coroutineScope.demoteSelfTo( is RolesAndPermissionsEvent.DemoteSelfTo -> coroutineScope.demoteSelfTo(
role = event.role, role = event.role,
changeOwnRoleAction = changeOwnRoleAction, changeOwnRoleAction = changeOwnRoleAction,
) )
is RolesAndPermissionsEvents.ResetPermissions -> if (resetPermissionsAction.value.isConfirming()) { is RolesAndPermissionsEvent.ResetPermissions -> if (resetPermissionsAction.value.isConfirming()) {
coroutineScope.resetPermissions(resetPermissionsAction) coroutineScope.resetPermissions(resetPermissionsAction)
} else { } else {
resetPermissionsAction.value = AsyncAction.ConfirmingNoParams resetPermissionsAction.value = AsyncAction.ConfirmingNoParams
@@ -20,7 +20,7 @@ data class RolesAndPermissionsState(
val availableSelfDemoteActions: ImmutableList<SelfDemoteAction>, val availableSelfDemoteActions: ImmutableList<SelfDemoteAction>,
val changeOwnRoleAction: AsyncAction<Unit>, val changeOwnRoleAction: AsyncAction<Unit>,
val resetPermissionsAction: AsyncAction<Unit>, val resetPermissionsAction: AsyncAction<Unit>,
val eventSink: (RolesAndPermissionsEvents) -> Unit, val eventSink: (RolesAndPermissionsEvent) -> Unit,
) { ) {
val canSelfDemote = availableSelfDemoteActions.isNotEmpty() val canSelfDemote = availableSelfDemoteActions.isNotEmpty()
} }
@@ -58,7 +58,7 @@ internal fun aRolesAndPermissionsState(
availableSelfDemoteActions: List<SelfDemoteAction> = listOf(SelfDemoteAction.ToModerator, SelfDemoteAction.ToMember), availableSelfDemoteActions: List<SelfDemoteAction> = listOf(SelfDemoteAction.ToModerator, SelfDemoteAction.ToMember),
changeOwnRoleAction: AsyncAction<Unit> = AsyncAction.Uninitialized, changeOwnRoleAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
resetPermissionsAction: AsyncAction<Unit> = AsyncAction.Uninitialized, resetPermissionsAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
eventSink: (RolesAndPermissionsEvents) -> Unit = {}, eventSink: (RolesAndPermissionsEvent) -> Unit = {},
) = RolesAndPermissionsState( ) = RolesAndPermissionsState(
roomSupportsOwnerRole = roomSupportsOwners, roomSupportsOwnerRole = roomSupportsOwners,
adminCount = adminCount, adminCount = adminCount,
@@ -80,7 +80,7 @@ fun RolesAndPermissionsView(
if (state.canSelfDemote) { if (state.canSelfDemote) {
ListItem( ListItem(
content = { Text(stringResource(R.string.screen_room_roles_and_permissions_change_my_role)) }, content = { Text(stringResource(R.string.screen_room_roles_and_permissions_change_my_role)) },
onClick = { state.eventSink(RolesAndPermissionsEvents.ChangeOwnRole) }, onClick = { state.eventSink(RolesAndPermissionsEvent.ChangeOwnRole) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Edit())) leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Edit()))
) )
} }
@@ -94,7 +94,7 @@ fun RolesAndPermissionsView(
ListItem( ListItem(
content = { Text(stringResource(R.string.screen_room_roles_and_permissions_reset)) }, content = { Text(stringResource(R.string.screen_room_roles_and_permissions_reset)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())),
onClick = { state.eventSink(RolesAndPermissionsEvents.ResetPermissions) }, onClick = { state.eventSink(RolesAndPermissionsEvent.ResetPermissions) },
style = ListItemStyle.Destructive, style = ListItemStyle.Destructive,
) )
} }
@@ -107,12 +107,12 @@ fun RolesAndPermissionsView(
content = stringResource(R.string.screen_room_roles_and_permissions_reset_confirm_description), content = stringResource(R.string.screen_room_roles_and_permissions_reset_confirm_description),
submitText = stringResource(CommonStrings.action_reset), submitText = stringResource(CommonStrings.action_reset),
destructiveSubmit = true, destructiveSubmit = true,
onSubmitClick = { state.eventSink(RolesAndPermissionsEvents.ResetPermissions) }, onSubmitClick = { state.eventSink(RolesAndPermissionsEvent.ResetPermissions) },
onDismiss = { state.eventSink(RolesAndPermissionsEvents.CancelPendingAction) }, onDismiss = { state.eventSink(RolesAndPermissionsEvent.CancelPendingAction) },
) )
}, },
onSuccess = { state.eventSink(RolesAndPermissionsEvents.CancelPendingAction) }, onSuccess = { state.eventSink(RolesAndPermissionsEvent.CancelPendingAction) },
onErrorDismiss = { state.eventSink(RolesAndPermissionsEvents.CancelPendingAction) } onErrorDismiss = { state.eventSink(RolesAndPermissionsEvent.CancelPendingAction) }
) )
when (state.changeOwnRoleAction) { when (state.changeOwnRoleAction) {
@@ -128,7 +128,7 @@ fun RolesAndPermissionsView(
is AsyncAction.Failure -> { is AsyncAction.Failure -> {
ErrorDialog( ErrorDialog(
content = stringResource(CommonStrings.error_unknown), content = stringResource(CommonStrings.error_unknown),
onSubmit = { state.eventSink(RolesAndPermissionsEvents.CancelPendingAction) } onSubmit = { state.eventSink(RolesAndPermissionsEvent.CancelPendingAction) }
) )
} }
else -> Unit else -> Unit
@@ -139,7 +139,7 @@ fun RolesAndPermissionsView(
@Composable @Composable
private fun ChangeOwnRoleBottomSheet( private fun ChangeOwnRoleBottomSheet(
availableDemoteActions: ImmutableList<SelfDemoteAction>, availableDemoteActions: ImmutableList<SelfDemoteAction>,
eventSink: (RolesAndPermissionsEvents) -> Unit, eventSink: (RolesAndPermissionsEvent) -> Unit,
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val sheetState = rememberBottomSheetState( val sheetState = rememberBottomSheetState(
@@ -148,7 +148,7 @@ private fun ChangeOwnRoleBottomSheet(
) )
fun dismiss() { fun dismiss() {
sheetState.hide(coroutineScope) { sheetState.hide(coroutineScope) {
eventSink(RolesAndPermissionsEvents.CancelPendingAction) eventSink(RolesAndPermissionsEvent.CancelPendingAction)
} }
} }
ModalBottomSheet( ModalBottomSheet(
@@ -176,7 +176,7 @@ private fun ChangeOwnRoleBottomSheet(
content = { Text(stringResource(demoteAction.titleRes)) }, content = { Text(stringResource(demoteAction.titleRes)) },
onClick = { onClick = {
sheetState.hide(coroutineScope) { sheetState.hide(coroutineScope) {
eventSink(RolesAndPermissionsEvents.DemoteSelfTo(demoteAction.role)) eventSink(RolesAndPermissionsEvent.DemoteSelfTo(demoteAction.role))
} }
}, },
style = ListItemStyle.Destructive, style = ListItemStyle.Destructive,
@@ -45,7 +45,7 @@ class RolesAndPermissionPresenterTest {
val presenter = createRolesAndPermissionsPresenter() val presenter = createRolesAndPermissionsPresenter()
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RolesAndPermissionsEvents.ChangeOwnRole) initialState.eventSink(RolesAndPermissionsEvent.ChangeOwnRole)
assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.ConfirmingNoParams) assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.ConfirmingNoParams)
} }
} }
@@ -62,7 +62,7 @@ class RolesAndPermissionPresenterTest {
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.Moderator)) initialState.eventSink(RolesAndPermissionsEvent.DemoteSelfTo(RoomMember.Role.Moderator))
runCurrent() runCurrent()
assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Loading) assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Loading)
@@ -82,7 +82,7 @@ class RolesAndPermissionPresenterTest {
val presenter = createRolesAndPermissionsPresenter(room = room, dispatchers = testCoroutineDispatchers()) val presenter = createRolesAndPermissionsPresenter(room = room, dispatchers = testCoroutineDispatchers())
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.Moderator)) initialState.eventSink(RolesAndPermissionsEvent.DemoteSelfTo(RoomMember.Role.Moderator))
runCurrent() runCurrent()
assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Loading) assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Loading)
@@ -90,7 +90,7 @@ class RolesAndPermissionPresenterTest {
runCurrent() runCurrent()
assertThat(awaitItem().changeOwnRoleAction).isInstanceOf(AsyncAction.Failure::class.java) assertThat(awaitItem().changeOwnRoleAction).isInstanceOf(AsyncAction.Failure::class.java)
initialState.eventSink(RolesAndPermissionsEvents.CancelPendingAction) initialState.eventSink(RolesAndPermissionsEvent.CancelPendingAction)
assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Uninitialized) assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Uninitialized)
} }
} }
@@ -100,8 +100,8 @@ class RolesAndPermissionPresenterTest {
val presenter = createRolesAndPermissionsPresenter() val presenter = createRolesAndPermissionsPresenter()
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RolesAndPermissionsEvents.ChangeOwnRole) initialState.eventSink(RolesAndPermissionsEvent.ChangeOwnRole)
awaitItem().eventSink(RolesAndPermissionsEvents.CancelPendingAction) awaitItem().eventSink(RolesAndPermissionsEvent.CancelPendingAction)
assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Uninitialized) assertThat(awaitItem().changeOwnRoleAction).isEqualTo(AsyncAction.Uninitialized)
} }
@@ -119,9 +119,9 @@ class RolesAndPermissionPresenterTest {
) )
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RolesAndPermissionsEvents.ResetPermissions) initialState.eventSink(RolesAndPermissionsEvent.ResetPermissions)
// Confirmation // Confirmation
awaitItem().eventSink(RolesAndPermissionsEvents.ResetPermissions) awaitItem().eventSink(RolesAndPermissionsEvent.ResetPermissions)
assertThat(awaitItem().resetPermissionsAction).isEqualTo(AsyncAction.Loading) assertThat(awaitItem().resetPermissionsAction).isEqualTo(AsyncAction.Loading)
assertThat(awaitItem().resetPermissionsAction).isEqualTo(AsyncAction.Success(Unit)) assertThat(awaitItem().resetPermissionsAction).isEqualTo(AsyncAction.Success(Unit))
@@ -134,8 +134,8 @@ class RolesAndPermissionPresenterTest {
val presenter = createRolesAndPermissionsPresenter() val presenter = createRolesAndPermissionsPresenter()
presenter.test { presenter.test {
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(RolesAndPermissionsEvents.ResetPermissions) initialState.eventSink(RolesAndPermissionsEvent.ResetPermissions)
awaitItem().eventSink(RolesAndPermissionsEvents.CancelPendingAction) awaitItem().eventSink(RolesAndPermissionsEvent.CancelPendingAction)
assertThat(awaitItem().resetPermissionsAction).isEqualTo(AsyncAction.Uninitialized) assertThat(awaitItem().resetPermissionsAction).isEqualTo(AsyncAction.Uninitialized)
} }
@@ -92,19 +92,19 @@ class RolesAndPermissionsViewTest : RobolectricTest() {
@Test @Test
@Config(qualifiers = "h640dp") @Config(qualifiers = "h640dp")
fun `tapping on reset permissions triggers ResetPermissions event`() = runAndroidComposeUiTest { fun `tapping on reset permissions triggers ResetPermissions event`() = runAndroidComposeUiTest {
val recorder = EventsRecorder<RolesAndPermissionsEvents>() val recorder = EventsRecorder<RolesAndPermissionsEvent>()
setRolesAndPermissionsView( setRolesAndPermissionsView(
state = aRolesAndPermissionsState( state = aRolesAndPermissionsState(
eventSink = recorder, eventSink = recorder,
), ),
) )
clickOn(R.string.screen_room_roles_and_permissions_reset) clickOn(R.string.screen_room_roles_and_permissions_reset)
recorder.assertSingle(RolesAndPermissionsEvents.ResetPermissions) recorder.assertSingle(RolesAndPermissionsEvent.ResetPermissions)
} }
@Test @Test
fun `tapping on Reset in the reset permissions confirmation dialog triggers ResetPermissions event`() = runAndroidComposeUiTest { fun `tapping on Reset in the reset permissions confirmation dialog triggers ResetPermissions event`() = runAndroidComposeUiTest {
val recorder = EventsRecorder<RolesAndPermissionsEvents>() val recorder = EventsRecorder<RolesAndPermissionsEvent>()
setRolesAndPermissionsView( setRolesAndPermissionsView(
state = aRolesAndPermissionsState( state = aRolesAndPermissionsState(
resetPermissionsAction = AsyncAction.ConfirmingNoParams, resetPermissionsAction = AsyncAction.ConfirmingNoParams,
@@ -112,12 +112,12 @@ class RolesAndPermissionsViewTest : RobolectricTest() {
), ),
) )
clickOn(CommonStrings.action_reset) clickOn(CommonStrings.action_reset)
recorder.assertSingle(RolesAndPermissionsEvents.ResetPermissions) recorder.assertSingle(RolesAndPermissionsEvent.ResetPermissions)
} }
@Test @Test
fun `tapping on Cancel in the reset permissions confirmation dialog triggers CancelPendingAction event`() = runAndroidComposeUiTest { fun `tapping on Cancel in the reset permissions confirmation dialog triggers CancelPendingAction event`() = runAndroidComposeUiTest {
val recorder = EventsRecorder<RolesAndPermissionsEvents>() val recorder = EventsRecorder<RolesAndPermissionsEvent>()
setRolesAndPermissionsView( setRolesAndPermissionsView(
state = aRolesAndPermissionsState( state = aRolesAndPermissionsState(
resetPermissionsAction = AsyncAction.ConfirmingNoParams, resetPermissionsAction = AsyncAction.ConfirmingNoParams,
@@ -125,12 +125,12 @@ class RolesAndPermissionsViewTest : RobolectricTest() {
), ),
) )
clickOn(CommonStrings.action_cancel) clickOn(CommonStrings.action_cancel)
recorder.assertSingle(RolesAndPermissionsEvents.CancelPendingAction) recorder.assertSingle(RolesAndPermissionsEvent.CancelPendingAction)
} }
@Test @Test
fun `tapping on 'Demote to moderator' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest { fun `tapping on 'Demote to moderator' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest {
val recorder = EventsRecorder<RolesAndPermissionsEvents>() val recorder = EventsRecorder<RolesAndPermissionsEvent>()
setRolesAndPermissionsView( setRolesAndPermissionsView(
state = aRolesAndPermissionsState( state = aRolesAndPermissionsState(
changeOwnRoleAction = AsyncAction.ConfirmingNoParams, changeOwnRoleAction = AsyncAction.ConfirmingNoParams,
@@ -139,12 +139,12 @@ class RolesAndPermissionsViewTest : RobolectricTest() {
) )
clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_moderator) clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_moderator)
mainClock.advanceTimeBy(1_000L) mainClock.advanceTimeBy(1_000L)
recorder.assertSingle(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.Moderator)) recorder.assertSingle(RolesAndPermissionsEvent.DemoteSelfTo(RoomMember.Role.Moderator))
} }
@Test @Test
fun `tapping on 'Demote to member' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest { fun `tapping on 'Demote to member' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest {
val recorder = EventsRecorder<RolesAndPermissionsEvents>() val recorder = EventsRecorder<RolesAndPermissionsEvent>()
setRolesAndPermissionsView( setRolesAndPermissionsView(
state = aRolesAndPermissionsState( state = aRolesAndPermissionsState(
changeOwnRoleAction = AsyncAction.ConfirmingNoParams, changeOwnRoleAction = AsyncAction.ConfirmingNoParams,
@@ -153,12 +153,12 @@ class RolesAndPermissionsViewTest : RobolectricTest() {
) )
clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_member) clickOn(R.string.screen_room_roles_and_permissions_change_role_demote_to_member)
mainClock.advanceTimeBy(1_000L) mainClock.advanceTimeBy(1_000L)
recorder.assertSingle(RolesAndPermissionsEvents.DemoteSelfTo(RoomMember.Role.User)) recorder.assertSingle(RolesAndPermissionsEvent.DemoteSelfTo(RoomMember.Role.User))
} }
@Test @Test
fun `tapping on 'Cancel' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest { fun `tapping on 'Cancel' in the demote self bottom sheet triggers the right event`() = runAndroidComposeUiTest {
val recorder = EventsRecorder<RolesAndPermissionsEvents>() val recorder = EventsRecorder<RolesAndPermissionsEvent>()
setRolesAndPermissionsView( setRolesAndPermissionsView(
state = aRolesAndPermissionsState( state = aRolesAndPermissionsState(
changeOwnRoleAction = AsyncAction.ConfirmingNoParams, changeOwnRoleAction = AsyncAction.ConfirmingNoParams,
@@ -167,7 +167,7 @@ class RolesAndPermissionsViewTest : RobolectricTest() {
) )
clickOn(CommonStrings.action_cancel) clickOn(CommonStrings.action_cancel)
mainClock.advanceTimeBy(1_000L) mainClock.advanceTimeBy(1_000L)
recorder.assertSingle(RolesAndPermissionsEvents.CancelPendingAction) recorder.assertSingle(RolesAndPermissionsEvent.CancelPendingAction)
} }
} }