From ec420332c373b35843b22c805bdbaaff55dfc8fa Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 12 Jan 2026 10:48:20 +0100 Subject: [PATCH] WIP: Support using Element Call for voice calls in DMs --- .../android/features/call/api/CallType.kt | 3 +- .../RingingCallNotificationCreator.kt | 3 +- .../receivers/DeclineCallBroadcastReceiver.kt | 5 ++- .../call/impl/ui/CallScreenPresenter.kt | 1 + .../call/impl/ui/IncomingCallActivity.kt | 9 +++- .../call/impl/utils/ActiveCallManager.kt | 2 + .../call/impl/utils/CallWidgetProvider.kt | 1 + .../impl/utils/DefaultCallWidgetProvider.kt | 2 + .../messages/impl/MessagesFlowNode.kt | 6 ++- .../features/messages/impl/MessagesNode.kt | 6 ++- .../features/messages/impl/MessagesView.kt | 4 +- .../impl/threads/ThreadedMessagesNode.kt | 6 ++- .../messages/impl/timeline/TimelineView.kt | 2 +- .../impl/timeline/components/CallMenuItem.kt | 43 +++++++++++++------ .../components/TimelineItemCallNotifyView.kt | 2 +- .../timeline/components/TimelineItemRow.kt | 2 +- .../impl/topbars/MessagesViewTopBar.kt | 2 +- .../features/roomcall/api/RoomCallState.kt | 2 + .../roomcall/api/RoomCallStateProvider.kt | 3 ++ .../roomcall/impl/RoomCallStatePresenter.kt | 1 + .../roomdetails/impl/RoomDetailsFlowNode.kt | 11 ++++- .../userprofile/impl/UserProfileFlowNode.kt | 3 +- .../api/widget/CallWidgetSettingsProvider.kt | 1 + .../DefaultCallWidgetSettingsProvider.kt | 25 ++++++++--- .../widget/FakeCallWidgetSettingsProvider.kt | 12 +++++- .../push/impl/push/DefaultPushHandler.kt | 7 ++- 26 files changed, 122 insertions(+), 42 deletions(-) diff --git a/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt b/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt index 5beb9f7c54..4f25bd654a 100644 --- a/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt +++ b/features/call/api/src/main/kotlin/io/element/android/features/call/api/CallType.kt @@ -26,9 +26,10 @@ sealed interface CallType : NodeInputs, Parcelable { data class RoomCall( val sessionId: SessionId, val roomId: RoomId, + val voiceIntent: Boolean ) : CallType { override fun toString(): String { - return "RoomCall(sessionId=$sessionId, roomId=$roomId)" + return "RoomCall(sessionId=$sessionId, roomId=$roomId, voiceIntent=$voiceIntent)" } } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt index e7d270ef8e..89ca335344 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt @@ -88,7 +88,8 @@ class RingingCallNotificationCreator( .setImportant(true) .build() - val answerIntent = IntentProvider.getPendingIntent(context, CallType.RoomCall(sessionId, roomId)) + // TODO + val answerIntent = IntentProvider.getPendingIntent(context, CallType.RoomCall(sessionId, roomId, voiceIntent = false)) val notificationData = CallNotificationData( sessionId = sessionId, roomId = roomId, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/receivers/DeclineCallBroadcastReceiver.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/receivers/DeclineCallBroadcastReceiver.kt index b9775892c3..56f2f34da5 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/receivers/DeclineCallBroadcastReceiver.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/receivers/DeclineCallBroadcastReceiver.kt @@ -45,8 +45,9 @@ class DeclineCallBroadcastReceiver : BroadcastReceiver() { callType = CallType.RoomCall( sessionId = notificationData.sessionId, roomId = notificationData.roomId, - ), - notificationData = notificationData, + // TODO + voiceIntent = false + ) ) } } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt index ba670e03aa..33eee90574 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt @@ -226,6 +226,7 @@ class CallScreenPresenter( sessionId = inputs.sessionId, roomId = inputs.roomId, clientId = UUID.randomUUID().toString(), + voiceOnly = inputs.voiceIntent, languageTag = languageTag, theme = theme, ).getOrThrow() diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt index faedd2648c..5dea00a337 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt @@ -112,7 +112,14 @@ class IncomingCallActivity : AppCompatActivity() { } private fun onAnswer(notificationData: CallNotificationData) { - elementCallEntryPoint.startCall(CallType.RoomCall(notificationData.sessionId, notificationData.roomId)) + elementCallEntryPoint.startCall( + CallType.RoomCall( + notificationData.sessionId, + notificationData.roomId, + // TODO + voiceIntent = false + ) + ) } private fun onCancel() { diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index a6663943bd..40f66db623 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -146,6 +146,8 @@ class DefaultActiveCallManager( callType = CallType.RoomCall( sessionId = notificationData.sessionId, roomId = notificationData.roomId, + // TODO + voiceIntent = false, ), callState = CallState.Ringing(notificationData), ) diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallWidgetProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallWidgetProvider.kt index 6ce73bc5e6..d4fae4826e 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallWidgetProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/CallWidgetProvider.kt @@ -16,6 +16,7 @@ interface CallWidgetProvider { suspend fun getWidget( sessionId: SessionId, roomId: RoomId, + voiceOnly: Boolean, clientId: String, languageTag: String?, theme: String?, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt index 1728a0cace..f94a1ecd59 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt @@ -32,6 +32,7 @@ class DefaultCallWidgetProvider( override suspend fun getWidget( sessionId: SessionId, roomId: RoomId, + voiceOnly: Boolean, clientId: String, languageTag: String?, theme: String?, @@ -50,6 +51,7 @@ class DefaultCallWidgetProvider( baseUrl = baseUrl, encrypted = isEncrypted, direct = room.isDm(), + voiceOnly = voiceOnly, hasActiveCall = roomInfo.hasRoomCall, ) val callUrl = room.generateWidgetWebViewUrl( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index f0b88e1956..4ba68c81f7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -272,10 +272,11 @@ class MessagesFlowNode( backstack.push(NavTarget.EditPoll(Timeline.Mode.Live, eventId)) } - override fun navigateToRoomCall(roomId: RoomId) { + override fun navigateToRoomCall(roomId: RoomId, voiceIntent: Boolean) { val callType = CallType.RoomCall( sessionId = sessionId, roomId = roomId, + voiceIntent = voiceIntent ) analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) elementCallEntryPoint.startCall(callType) @@ -488,10 +489,11 @@ class MessagesFlowNode( backstack.push(NavTarget.EditPoll(Timeline.Mode.Thread(navTarget.threadRootId), eventId)) } - override fun navigateToRoomCall(roomId: RoomId) { + override fun navigateToRoomCall(roomId: RoomId, voiceOnly: Boolean) { val callType = CallType.RoomCall( sessionId = sessionId, roomId = roomId, + voiceIntent = voiceOnly ) analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) elementCallEntryPoint.startCall(callType) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index e892f80c7d..83dc7aebe4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -125,7 +125,7 @@ class MessagesNode( fun navigateToSendLocation() fun navigateToCreatePoll() fun navigateToEditPoll(eventId: EventId) - fun navigateToRoomCall(roomId: RoomId) + fun navigateToRoomCall(roomId: RoomId, voiceIntent: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToRoomDetails() fun navigateToPinnedMessagesList() @@ -279,7 +279,9 @@ class MessagesNode( }, onSendLocationClick = callback::navigateToSendLocation, onCreatePollClick = callback::navigateToCreatePoll, - onJoinCallClick = { callback.navigateToRoomCall(room.roomId) }, + onJoinCallClick = { voiceOnly -> + callback.navigateToRoomCall(room.roomId, voiceOnly) + }, onViewAllPinnedMessagesClick = callback::navigateToPinnedMessagesList, modifier = modifier, knockRequestsBannerView = { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 559392583f..082e31b51b 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -130,7 +130,7 @@ fun MessagesView( onLinkClick: (String, Boolean) -> Unit, onSendLocationClick: () -> Unit, onCreatePollClick: () -> Unit, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceIntent: Boolean) -> Unit, onViewAllPinnedMessagesClick: () -> Unit, modifier: Modifier = Modifier, forceJumpToBottomVisibility: Boolean = false, @@ -423,7 +423,7 @@ private fun MessagesViewContent( onMessageLongClick: (TimelineItem.Event) -> Unit, onSendLocationClick: () -> Unit, onCreatePollClick: () -> Unit, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceIntent: Boolean) -> Unit, onViewAllPinnedMessagesClick: () -> Unit, forceJumpToBottomVisibility: Boolean, onSwipeToReply: (TimelineItem.Event) -> Unit, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 46145ba6b9..9ef97e6ffa 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -130,7 +130,7 @@ class ThreadedMessagesNode( fun navigateToSendLocation() fun navigateToCreatePoll() fun navigateToEditPoll(eventId: EventId) - fun navigateToRoomCall(roomId: RoomId) + fun navigateToRoomCall(roomId: RoomId, voiceOnly: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) } @@ -281,7 +281,9 @@ class ThreadedMessagesNode( }, onSendLocationClick = callback::navigateToSendLocation, onCreatePollClick = callback::navigateToCreatePoll, - onJoinCallClick = { callback.navigateToRoomCall(room.roomId) }, + onJoinCallClick = { voiceIntent -> + callback.navigateToRoomCall(room.roomId, voiceIntent) + }, onViewAllPinnedMessagesClick = {}, modifier = modifier, knockRequestsBannerView = {}, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index e44a6e170c..08d29e2ba6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -100,7 +100,7 @@ fun TimelineView( onReactionLongClick: (emoji: String, TimelineItem.Event) -> Unit, onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceIntent: Boolean) -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState(), forceJumpToBottomVisibility: Boolean = false, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/CallMenuItem.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/CallMenuItem.kt index 73e6c1873a..989cbff1e6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/CallMenuItem.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/CallMenuItem.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.timeline.components import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.size @@ -35,7 +36,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun CallMenuItem( roomCallState: RoomCallState, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceOnly: Boolean) -> Unit, modifier: Modifier = Modifier, ) { when (roomCallState) { @@ -52,7 +53,7 @@ internal fun CallMenuItem( is RoomCallState.OnGoing -> { OnGoingCallMenuItem( roomCallState = roomCallState, - onJoinCallClick = onJoinCallClick, + onJoinCallClick = { onJoinCallClick(roomCallState.isVoiceIntent) }, modifier = modifier, ) } @@ -62,18 +63,30 @@ internal fun CallMenuItem( @Composable private fun StandByCallMenuItem( roomCallState: RoomCallState.StandBy, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceOnly: Boolean) -> Unit, modifier: Modifier = Modifier, ) { - IconButton( - modifier = modifier, - onClick = onJoinCallClick, - enabled = roomCallState.canStartCall, - ) { - Icon( - imageVector = CompoundIcons.VideoCallSolid(), - contentDescription = stringResource(CommonStrings.a11y_start_call), - ) + Row(modifier = modifier) { + IconButton( + modifier = modifier, + onClick = { onJoinCallClick(true) }, + enabled = roomCallState.canStartCall, + ) { + Icon( + imageVector = CompoundIcons.VoiceCallSolid(), + contentDescription = stringResource(CommonStrings.a11y_start_call), + ) + } + IconButton( + modifier = modifier, + onClick = { onJoinCallClick(false) }, + enabled = roomCallState.canStartCall, + ) { + Icon( + imageVector = CompoundIcons.VideoCallSolid(), + contentDescription = stringResource(CommonStrings.a11y_start_call), + ) + } } } @@ -96,7 +109,11 @@ private fun OnGoingCallMenuItem( ) { Icon( modifier = Modifier.size(20.dp), - imageVector = CompoundIcons.VideoCallSolid(), + imageVector = if (roomCallState.isVoiceIntent) { + CompoundIcons.VoiceCallSolid() + } else { + CompoundIcons.VideoCallSolid() + }, contentDescription = null ) Spacer(Modifier.width(8.dp)) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index c921135b96..203b4949b0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -46,7 +46,7 @@ internal fun TimelineItemCallNotifyView( event: TimelineItem.Event, roomCallState: RoomCallState, onLongClick: (TimelineItem.Event) -> Unit, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceOnly: Boolean) -> Unit, modifier: Modifier = Modifier ) { Row( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 15e47e5269..f55c1303eb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -72,7 +72,7 @@ internal fun TimelineItemRow( onMoreReactionsClick: (TimelineItem.Event) -> Unit, onReadReceiptClick: (TimelineItem.Event) -> Unit, onSwipeToReply: (TimelineItem.Event) -> Unit, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceIntent: Boolean) -> Unit, eventSink: (TimelineEvent.TimelineItemEvent) -> Unit, modifier: Modifier = Modifier, eventContentView: @Composable (TimelineItem.Event, Modifier, (ContentAvoidingLayoutData) -> Unit) -> Unit = diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index 5d3746f82e..a7faa0f20f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -66,7 +66,7 @@ internal fun MessagesViewTopBar( dmUserIdentityState: IdentityState?, sharedHistoryIcon: SharedHistoryIcon, onRoomDetailsClick: () -> Unit, - onJoinCallClick: () -> Unit, + onJoinCallClick: (voiceIntent: Boolean) -> Unit, onBackClick: () -> Unit, modifier: Modifier = Modifier, ) { diff --git a/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallState.kt b/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallState.kt index 1a6b17ec89..a6650c0c32 100644 --- a/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallState.kt +++ b/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallState.kt @@ -18,10 +18,12 @@ sealed interface RoomCallState { data class StandBy( val canStartCall: Boolean, + // TODO: add is DM to know if should show the voice call option? ) : RoomCallState data class OnGoing( val canJoinCall: Boolean, + val isVoiceIntent: Boolean, val isUserInTheCall: Boolean, val isUserLocallyInTheCall: Boolean, ) : RoomCallState diff --git a/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallStateProvider.kt b/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallStateProvider.kt index be86c2441d..d0a759f600 100644 --- a/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallStateProvider.kt +++ b/features/roomcall/api/src/main/kotlin/io/element/android/features/roomcall/api/RoomCallStateProvider.kt @@ -17,6 +17,7 @@ open class RoomCallStateProvider : PreviewParameterProvider { anOngoingCallState(), anOngoingCallState(canJoinCall = false), anOngoingCallState(canJoinCall = true, isUserInTheCall = true), + anOngoingCallState(canJoinCall = true, isVoiceIntent = true), RoomCallState.Unavailable, ) } @@ -25,10 +26,12 @@ fun anOngoingCallState( canJoinCall: Boolean = true, isUserInTheCall: Boolean = false, isUserLocallyInTheCall: Boolean = isUserInTheCall, + isVoiceIntent: Boolean = false, ) = RoomCallState.OnGoing( canJoinCall = canJoinCall, isUserInTheCall = isUserInTheCall, isUserLocallyInTheCall = isUserLocallyInTheCall, + isVoiceIntent = isVoiceIntent ) fun aStandByCallState( diff --git a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt index b18a2772a3..c431570be8 100644 --- a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt +++ b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt @@ -56,6 +56,7 @@ class RoomCallStatePresenter( canJoinCall = canJoinCall, isUserInTheCall = isUserInTheCall, isUserLocallyInTheCall = isUserLocallyInTheCall, + isVoiceIntent = false // TODO ) else -> RoomCallState.StandBy(canStartCall = canJoinCall) } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index 03adbded1b..c157618a59 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -227,6 +227,8 @@ class RoomDetailsFlowNode( val inputs = CallType.RoomCall( sessionId = room.sessionId, roomId = room.roomId, + // TODO + voiceIntent = false ) analyticsService.captureInteraction(Interaction.Name.MobileRoomCallButton) elementCallEntryPoint.startCall(inputs) @@ -285,7 +287,14 @@ class RoomDetailsFlowNode( } override fun startCall(dmRoomId: RoomId) { - elementCallEntryPoint.startCall(CallType.RoomCall(roomId = dmRoomId, sessionId = room.sessionId)) + elementCallEntryPoint.startCall( + CallType.RoomCall( + roomId = dmRoomId, + sessionId = room.sessionId, + // TODO + voiceIntent = false + ) + ) } override fun startVerifyUserFlow(userId: UserId) { diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt index f95ccce528..b981b68eb8 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/UserProfileFlowNode.kt @@ -84,7 +84,8 @@ class UserProfileFlowNode( } override fun startCall(dmRoomId: RoomId) { - elementCallEntryPoint.startCall(CallType.RoomCall(sessionId = sessionId, roomId = dmRoomId)) + // TODO + elementCallEntryPoint.startCall(CallType.RoomCall(sessionId = sessionId, roomId = dmRoomId, voiceIntent = false)) } override fun startVerifyUserFlow(userId: UserId) { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt index 6c91a90928..dd4fa3eb66 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt @@ -16,6 +16,7 @@ interface CallWidgetSettingsProvider { widgetId: String = UUID.randomUUID().toString(), encrypted: Boolean, direct: Boolean, + voiceOnly: Boolean, hasActiveCall: Boolean, ): MatrixWidgetSettings } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt index 60a0bead33..7cf11d97e0 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt @@ -30,7 +30,14 @@ class DefaultCallWidgetSettingsProvider( private val callAnalyticsCredentialsProvider: CallAnalyticCredentialsProvider, private val analyticsService: AnalyticsService, ) : CallWidgetSettingsProvider { - override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean, hasActiveCall: Boolean): MatrixWidgetSettings { + override suspend fun provide( + baseUrl: String, + widgetId: String, + encrypted: Boolean, + direct: Boolean, + voiceOnly: Boolean, + hasActiveCall: Boolean + ): MatrixWidgetSettings { val isAnalyticsEnabled = analyticsService.userConsentFlow.first() val properties = VirtualElementCallWidgetProperties( elementCallUrl = baseUrl, @@ -47,14 +54,18 @@ class DefaultCallWidgetSettingsProvider( parentUrl = null, ) val config = VirtualElementCallWidgetConfig( - // TODO remove this once we have the next EC version - preload = false, - // TODO remove this once we have the next EC version - skipLobby = null, +// // TODO remove this once we have the next EC version +// preload = false, +// // TODO remove this once we have the next EC version +// skipLobby = null, intent = when { - direct && hasActiveCall -> CallIntent.JOIN_EXISTING_DM + direct && hasActiveCall -> { + if (voiceOnly) CallIntent.JOIN_EXISTING_DM_VOICE else CallIntent.JOIN_EXISTING_DM + } hasActiveCall -> CallIntent.JOIN_EXISTING - direct -> CallIntent.START_CALL_DM + direct -> { + if (voiceOnly) CallIntent.START_CALL_DM_VOICE else CallIntent.START_CALL_DM + } else -> CallIntent.START_CALL }.also { Timber.d("Starting/joining call with intent: $it") diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt index a91868c4b6..e038415eb3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt @@ -12,7 +12,14 @@ import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings class FakeCallWidgetSettingsProvider( - private val provideFn: (String, String, Boolean, Boolean, Boolean) -> MatrixWidgetSettings = { _, _, _, _, _ -> MatrixWidgetSettings("id", true, "url") } + private val provideFn: ( + String, + String, + Boolean, + Boolean, + Boolean, + Boolean + ) -> MatrixWidgetSettings = { _, _, _, _, _, _ -> MatrixWidgetSettings("id", true, "url") } ) : CallWidgetSettingsProvider { val providedBaseUrls = mutableListOf() @@ -21,9 +28,10 @@ class FakeCallWidgetSettingsProvider( widgetId: String, encrypted: Boolean, direct: Boolean, + voiceOnly: Boolean, hasActiveCall: Boolean ): MatrixWidgetSettings { providedBaseUrls += baseUrl - return provideFn(baseUrl, widgetId, encrypted, direct, hasActiveCall) + return provideFn(baseUrl, widgetId, encrypted, direct, voiceOnly, hasActiveCall) } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index 0053a18838..ee50e4cad1 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -300,7 +300,12 @@ class DefaultPushHandler( private suspend fun handleRingingCallEvent(notifiableEvent: NotifiableRingingCallEvent) { Timber.i("## handleInternal() : Incoming call.") elementCallEntryPoint.handleIncomingCall( - callType = CallType.RoomCall(notifiableEvent.sessionId, notifiableEvent.roomId), + callType = CallType.RoomCall( + notifiableEvent.sessionId, + notifiableEvent.roomId, + // TODO + voiceIntent = false + ), eventId = notifiableEvent.eventId, senderId = notifiableEvent.senderId, roomName = notifiableEvent.roomName,