Hide the join call button if the user is already in the call.

This is at the account level so if the user has joined the call on another device, the join button will be hidden.

Extract room call state presenter to its own module and update RoomCallState model.
Let RoomDetailsPresenter use the new RoomCallStatePresenter
This commit is contained in:
Benoit Marty 2024-11-05 17:39:39 +01:00 committed by Benoit Marty
parent 6b71994321
commit 2a35edb14a
27 changed files with 419 additions and 153 deletions

View file

@ -21,6 +21,7 @@ import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.bool.orFalse
@ -37,7 +38,6 @@ import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
import io.element.android.libraries.matrix.ui.room.canCall
import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember
import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
import io.element.android.libraries.matrix.ui.room.isOwnUserAdmin
@ -57,6 +57,7 @@ class RoomDetailsPresenter @Inject constructor(
private val notificationSettingsService: NotificationSettingsService,
private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory,
private val leaveRoomPresenter: Presenter<LeaveRoomState>,
private val roomCallStatePresenter: Presenter<RoomCallState>,
private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
@ -87,18 +88,16 @@ class RoomDetailsPresenter @Inject constructor(
}
}
val syncUpdateTimestamp by room.syncUpdateFlow.collectAsState()
val membersState by room.membersStateFlow.collectAsState()
val canInvite by getCanInvite(membersState)
val canEditName by getCanSendState(membersState, StateEventType.ROOM_NAME)
val canEditAvatar by getCanSendState(membersState, StateEventType.ROOM_AVATAR)
val canEditTopic by getCanSendState(membersState, StateEventType.ROOM_TOPIC)
val canJoinCall by room.canCall(updateKey = syncUpdateTimestamp)
val dmMember by room.getDirectRoomMember(membersState)
val currentMember by room.getCurrentRoomMember(membersState)
val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember)
val roomType by getRoomType(dmMember, currentMember)
val roomCallState = roomCallStatePresenter.present()
val topicState = remember(canEditTopic, roomTopic, roomType) {
val topic = roomTopic
@ -143,7 +142,7 @@ class RoomDetailsPresenter @Inject constructor(
canInvite = canInvite,
canEdit = (canEditAvatar || canEditName || canEditTopic) && roomType == RoomDetailsType.Room,
canShowNotificationSettings = canShowNotificationSettings.value,
canCall = canJoinCall,
roomCallState = roomCallState,
roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState,
leaveRoomState = leaveRoomState,

View file

@ -9,6 +9,7 @@ package io.element.android.features.roomdetails.impl
import androidx.compose.runtime.Immutable
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
@ -31,7 +32,7 @@ data class RoomDetailsState(
val canEdit: Boolean,
val canInvite: Boolean,
val canShowNotificationSettings: Boolean,
val canCall: Boolean,
val roomCallState: RoomCallState,
val leaveRoomState: LeaveRoomState,
val roomNotificationSettings: RoomNotificationSettings?,
val isFavorite: Boolean,

View file

@ -10,6 +10,8 @@ package io.element.android.features.roomdetails.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.leaveroom.api.aLeaveRoomState
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.roomcall.api.aStandByCallState
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.userprofile.api.UserProfileState
import io.element.android.features.userprofile.shared.aUserProfileState
@ -42,7 +44,7 @@ open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState>
// Also test the roomNotificationSettings ALL_MESSAGES in the same screenshot. Icon 'Mute' should be displayed
roomNotificationSettings = aRoomNotificationSettings(mode = RoomNotificationMode.ALL_MESSAGES, isDefault = true)
),
aRoomDetailsState(canCall = false, canInvite = false),
aRoomDetailsState(roomCallState = aStandByCallState(false), canInvite = false),
aRoomDetailsState(isPublic = false),
aRoomDetailsState(heroes = aMatrixUserList()),
aRoomDetailsState(pinnedMessagesCount = 3),
@ -89,7 +91,7 @@ fun aRoomDetailsState(
canInvite: Boolean = false,
canEdit: Boolean = false,
canShowNotificationSettings: Boolean = true,
canCall: Boolean = true,
roomCallState: RoomCallState = aStandByCallState(),
roomType: RoomDetailsType = RoomDetailsType.Room,
roomMemberDetailsState: UserProfileState? = null,
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
@ -112,7 +114,7 @@ fun aRoomDetailsState(
canInvite = canInvite,
canEdit = canEdit,
canShowNotificationSettings = canShowNotificationSettings,
canCall = canCall,
roomCallState = roomCallState,
roomType = roomType,
roomMemberDetailsState = roomMemberDetailsState,
leaveRoomState = leaveRoomState,

View file

@ -42,6 +42,7 @@ import im.vector.app.features.analytics.plan.Interaction
import io.element.android.compound.theme.ElementTheme
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.leaveroom.api.LeaveRoomView
import io.element.android.features.roomcall.api.hasPermissionToJoin
import io.element.android.features.userprofile.shared.blockuser.BlockUserDialogs
import io.element.android.features.userprofile.shared.blockuser.BlockUserSection
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
@ -299,7 +300,8 @@ private fun MainActionsSection(
)
}
}
if (state.canCall) {
if (state.roomCallState.hasPermissionToJoin()) {
// TODO Improve the view depending on all the cases here?
MainActionButton(
title = stringResource(CommonStrings.action_call),
imageVector = CompoundIcons.VideoCall(),

View file

@ -17,6 +17,7 @@ import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.leaveroom.api.aLeaveRoomState
import io.element.android.features.roomcall.api.aStandByCallState
import io.element.android.features.roomdetails.aMatrixRoom
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
@ -98,6 +99,7 @@ class RoomDetailsPresenterTest {
notificationSettingsService = matrixClient.notificationSettingsService(),
roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory,
leaveRoomPresenter = { leaveRoomState },
roomCallStatePresenter = { aStandByCallState() },
dispatchers = dispatchers,
isPinnedMessagesFeatureEnabled = { isPinnedMessagesFeatureEnabled },
analyticsService = analyticsService,