From 20ed6bb0d2141200a2562fda1a142c3fffa2e7df Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 27 Nov 2024 11:40:47 +0100 Subject: [PATCH] knock requests : add permissions check --- .../impl/list/KnockRequestsListEvents.kt | 1 + .../impl/list/KnockRequestsListPresenter.kt | 62 +++++++++++++--- .../impl/list/KnockRequestsListState.kt | 8 +- .../list/KnockRequestsListStateProvider.kt | 45 +++++++++++- .../impl/list/KnockRequestsListView.kt | 73 +++++++++++++------ 5 files changed, 150 insertions(+), 39 deletions(-) diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListEvents.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListEvents.kt index d84e5209b9..132c137ce2 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListEvents.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListEvents.kt @@ -12,6 +12,7 @@ import io.element.android.features.knockrequests.impl.KnockRequest sealed interface KnockRequestsListEvents { data class Accept(val knockRequest: KnockRequest) : KnockRequestsListEvents data class Decline(val knockRequest: KnockRequest) : KnockRequestsListEvents + data class DeclineAndBan(val knockRequest: KnockRequest) : KnockRequestsListEvents data object AcceptAll : KnockRequestsListEvents data object DismissCurrentAction : KnockRequestsListEvents } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenter.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenter.kt index e7168e967b..8ae993c9ef 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenter.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenter.kt @@ -8,35 +8,77 @@ package io.element.android.features.knockrequests.impl.list import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.ui.room.canBanAsState +import io.element.android.libraries.matrix.ui.room.canInviteAsState +import io.element.android.libraries.matrix.ui.room.canKickAsState import kotlinx.collections.immutable.persistentListOf import javax.inject.Inject -class KnockRequestsListPresenter @Inject constructor() : Presenter { +class KnockRequestsListPresenter @Inject constructor( + private val room: MatrixRoom, +) : Presenter { @Composable override fun present(): KnockRequestsListState { - val actions = remember { - mutableStateOf(KnockRequestsCurrentAction.None) - } + val currentAction = remember { mutableStateOf(KnockRequestsCurrentAction.None) } + val syncUpdateFlow = room.syncUpdateFlow.collectAsState() + val canBan by room.canBanAsState(syncUpdateFlow.value) + val canDecline by room.canKickAsState(syncUpdateFlow.value) + val canAccept by room.canInviteAsState(syncUpdateFlow.value) fun handleEvents(event: KnockRequestsListEvents) { when (event) { - KnockRequestsListEvents.AcceptAll -> Unit - is KnockRequestsListEvents.Accept -> Unit - is KnockRequestsListEvents.Decline -> Unit - KnockRequestsListEvents.DismissCurrentAction -> { - actions.value = KnockRequestsCurrentAction.None + KnockRequestsListEvents.AcceptAll -> { + currentAction.value = KnockRequestsCurrentAction.AcceptAll(AsyncAction.Uninitialized) } + is KnockRequestsListEvents.Accept -> { + currentAction.value = KnockRequestsCurrentAction.Accept(event.knockRequest, AsyncAction.Uninitialized) + } + is KnockRequestsListEvents.Decline -> { + currentAction.value = KnockRequestsCurrentAction.Decline(event.knockRequest, AsyncAction.Uninitialized) + } + is KnockRequestsListEvents.DeclineAndBan -> { + currentAction.value = KnockRequestsCurrentAction.DeclineAndBan(event.knockRequest, AsyncAction.Uninitialized) + } + KnockRequestsListEvents.DismissCurrentAction -> { + currentAction.value = KnockRequestsCurrentAction.None + } + } + } + + LaunchedEffect(currentAction) { + when (val action = currentAction.value) { + is KnockRequestsCurrentAction.Accept -> { + // Accept the knock request + } + is KnockRequestsCurrentAction.Decline -> { + // Decline the knock request + } + is KnockRequestsCurrentAction.DeclineAndBan -> { + // Decline and ban the user + } + is KnockRequestsCurrentAction.AcceptAll -> { + // Accept all knock requests + } + KnockRequestsCurrentAction.None -> Unit } } return KnockRequestsListState( knockRequests = AsyncData.Success(persistentListOf()), - currentAction = actions.value, + currentAction = currentAction.value, + canAccept = canAccept, + canDecline = canDecline, + canBan = canBan, eventSink = ::handleEvents ) } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt index 072ff5bdee..8c4cd3e0ed 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListState.kt @@ -15,6 +15,9 @@ import kotlinx.collections.immutable.ImmutableList data class KnockRequestsListState( val knockRequests: AsyncData>, val currentAction: KnockRequestsCurrentAction, + val canAccept: Boolean, + val canDecline: Boolean, + val canBan: Boolean, val eventSink: (KnockRequestsListEvents) -> Unit, ) { val canAcceptAll = knockRequests is AsyncData.Success && knockRequests.data.size > 1 @@ -22,7 +25,8 @@ data class KnockRequestsListState( sealed interface KnockRequestsCurrentAction { data object None : KnockRequestsCurrentAction - data class Accept(val async: AsyncAction) : KnockRequestsCurrentAction - data class Decline(val async: AsyncAction) : KnockRequestsCurrentAction + data class Accept(val knockRequest: KnockRequest, val async: AsyncAction) : KnockRequestsCurrentAction + data class Decline(val knockRequest: KnockRequest, val async: AsyncAction) : KnockRequestsCurrentAction + data class DeclineAndBan(val knockRequest: KnockRequest, val async: AsyncAction) : KnockRequestsCurrentAction data class AcceptAll(val async: AsyncAction) : KnockRequestsCurrentAction } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt index 761c850180..5a94a000ae 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListStateProvider.kt @@ -52,7 +52,40 @@ open class KnockRequestsListStateProvider : PreviewParameterProvider> = AsyncData.Success(persistentListOf()), - actions: KnockRequestsCurrentAction = KnockRequestsCurrentAction.None, + currentAction: KnockRequestsCurrentAction = KnockRequestsCurrentAction.None, + canAccept: Boolean = true, + canDecline: Boolean = true, + canBan: Boolean = true, eventSink: (KnockRequestsListEvents) -> Unit = {}, ) = KnockRequestsListState( knockRequests = knockRequests, - currentAction = actions, + currentAction = currentAction, + canAccept = canAccept, + canDecline = canDecline, + canBan = canBan, eventSink = eventSink, ) diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt index 416a00194c..bbf7facfd8 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListView.kt @@ -101,6 +101,9 @@ private fun KnockRequestsListContent(state: KnockRequestsListState, modifier: Mo } else { KnockRequestsList( knockRequests = knockRequests, + canAccept = state.canAccept, + canDecline = state.canDecline, + canBan = state.canBan, onAcceptClick = ::onAcceptClick, onDeclineClick = ::onDeclineClick, ) @@ -154,6 +157,13 @@ private fun KnockRequestsActionsView( onErrorDismiss = onDismiss, ) } + is KnockRequestsCurrentAction.DeclineAndBan -> { + AsyncActionView( + async = actions.async, + onSuccess = {}, + onErrorDismiss = onDismiss, + ) + } KnockRequestsCurrentAction.None -> Unit } } @@ -162,6 +172,9 @@ private fun KnockRequestsActionsView( @Composable private fun KnockRequestsList( knockRequests: ImmutableList, + canAccept: Boolean, + canDecline: Boolean, + canBan: Boolean, onAcceptClick: (KnockRequest) -> Unit, onDeclineClick: (KnockRequest) -> Unit, modifier: Modifier = Modifier, @@ -171,6 +184,9 @@ private fun KnockRequestsList( KnockRequestItem( knockRequest = knockRequest, onAcceptClick = onAcceptClick, + canBan = canBan, + canDecline = canDecline, + canAccept = canAccept, onDeclineClick = onDeclineClick, ) if (index != knockRequests.size - 1) { @@ -183,6 +199,9 @@ private fun KnockRequestsList( @Composable private fun KnockRequestItem( knockRequest: KnockRequest, + canAccept: Boolean, + canDecline: Boolean, + canBan: Boolean, onAcceptClick: (KnockRequest) -> Unit, onDeclineClick: (KnockRequest) -> Unit, modifier: Modifier = Modifier, @@ -194,7 +213,7 @@ private fun KnockRequestItem( ) { Avatar(knockRequest.getAvatarData(AvatarSize.KnockRequestItem)) Spacer(modifier = Modifier.width(16.dp)) - Column(modifier = Modifier) { + Column { // Name Text( modifier = Modifier.clipToBounds(), @@ -222,37 +241,43 @@ private fun KnockRequestItem( style = ElementTheme.typography.fontBodyMdRegular, ) } + // Actions Spacer(modifier = Modifier.height(12.dp)) Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) { - OutlinedButton( - text = stringResource(CommonStrings.action_decline), - onClick = { - onDeclineClick(knockRequest) - }, - size = ButtonSize.MediumLowPadding, - modifier = Modifier.weight(1f), - ) - Button( - text = stringResource(CommonStrings.action_accept), + if (canDecline) { + OutlinedButton( + text = stringResource(CommonStrings.action_decline), + onClick = { + onDeclineClick(knockRequest) + }, + size = ButtonSize.MediumLowPadding, + modifier = Modifier.weight(1f), + ) + } + if (canAccept) { + Button( + text = stringResource(CommonStrings.action_accept), + onClick = { + onAcceptClick(knockRequest) + }, + size = ButtonSize.MediumLowPadding, + modifier = Modifier.weight(1f), + ) + } + } + if (canBan) { + Spacer(modifier = Modifier.height(12.dp)) + TextButton( + text = stringResource(CommonStrings.screen_knock_requests_list_decline_and_ban_action_title), onClick = { onAcceptClick(knockRequest) }, - size = ButtonSize.MediumLowPadding, - modifier = Modifier.weight(1f), + destructive = true, + size = ButtonSize.Small, + modifier = Modifier.fillMaxWidth(), ) } - Spacer(modifier = Modifier.height(12.dp)) - TextButton( - text = stringResource(CommonStrings.screen_knock_requests_list_decline_and_ban_action_title), - onClick = { - onAcceptClick(knockRequest) - }, - destructive = true, - size = ButtonSize.Small, - modifier = Modifier.fillMaxWidth(), - ) - } } }