WIP: Support using Element Call for voice calls in DMs

This commit is contained in:
Valere 2026-01-12 10:48:20 +01:00 committed by Benoit Marty
parent 66c3bf267a
commit ec420332c3
26 changed files with 122 additions and 42 deletions

View file

@ -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)

View file

@ -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 = {

View file

@ -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,

View file

@ -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 = {},

View file

@ -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,

View file

@ -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))

View file

@ -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(

View file

@ -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 =

View file

@ -66,7 +66,7 @@ internal fun MessagesViewTopBar(
dmUserIdentityState: IdentityState?,
sharedHistoryIcon: SharedHistoryIcon,
onRoomDetailsClick: () -> Unit,
onJoinCallClick: () -> Unit,
onJoinCallClick: (voiceIntent: Boolean) -> Unit,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {