Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: call participants tiles UI [WPB-10149] #3202

Merged
merged 9 commits into from
Jul 19, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import com.wire.android.ui.common.topappbar.NavigationIconType
import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
import com.wire.android.ui.common.visbility.rememberVisibilityState
import com.wire.android.ui.home.conversations.PermissionPermanentlyDeniedDialogState
import com.wire.android.ui.home.conversationslist.model.Membership
import com.wire.android.ui.theme.WireTheme
import com.wire.android.ui.theme.wireColorScheme
import com.wire.android.ui.theme.wireDimensions
Expand All @@ -90,6 +91,7 @@ import com.wire.android.util.ui.PreviewMultipleThemes
import com.wire.kalium.logic.data.call.CallStatus
import com.wire.kalium.logic.data.conversation.Conversation
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.QualifiedID
import java.util.Locale

@Suppress("ParameterWrapping")
Expand Down Expand Up @@ -119,42 +121,30 @@ fun OngoingCallScreen(
}
}

with(sharedCallingViewModel.callState) {
OngoingCallContent(
conversationId = conversationId,
conversationName = conversationName,
participants = participants,
isMuted = isMuted ?: true,
isCameraOn = isCameraOn,
isSpeakerOn = isSpeakerOn,
isCbrEnabled = isCbrEnabled,
isOnFrontCamera = isOnFrontCamera,
protocolInfo = protocolInfo,
mlsVerificationStatus = mlsVerificationStatus,
proteusVerificationStatus = proteusVerificationStatus,
shouldShowDoubleTapToast = ongoingCallViewModel.shouldShowDoubleTapToast,
toggleSpeaker = sharedCallingViewModel::toggleSpeaker,
toggleMute = sharedCallingViewModel::toggleMute,
hangUpCall = { sharedCallingViewModel.hangUpCall { activity.finishAndRemoveTask() } },
toggleVideo = sharedCallingViewModel::toggleVideo,
flipCamera = sharedCallingViewModel::flipCamera,
setVideoPreview = sharedCallingViewModel::setVideoPreview,
clearVideoPreview = sharedCallingViewModel::clearVideoPreview,
onCollapse = { activity.moveTaskToBack(true) },
requestVideoStreams = ongoingCallViewModel::requestVideoStreams,
hideDoubleTapToast = ongoingCallViewModel::hideDoubleTapToast,
onCameraPermissionPermanentlyDenied = {
permissionPermanentlyDeniedDialogState.show(
PermissionPermanentlyDeniedDialogState.Visible(
title = R.string.app_permission_dialog_title,
description = R.string.camera_permission_dialog_description
)
OngoingCallContent(
callState = sharedCallingViewModel.callState,
shouldShowDoubleTapToast = ongoingCallViewModel.shouldShowDoubleTapToast,
toggleSpeaker = sharedCallingViewModel::toggleSpeaker,
toggleMute = sharedCallingViewModel::toggleMute,
hangUpCall = { sharedCallingViewModel.hangUpCall { activity.finishAndRemoveTask() } },
toggleVideo = sharedCallingViewModel::toggleVideo,
flipCamera = sharedCallingViewModel::flipCamera,
setVideoPreview = sharedCallingViewModel::setVideoPreview,
clearVideoPreview = sharedCallingViewModel::clearVideoPreview,
onCollapse = { activity.moveTaskToBack(true) },
requestVideoStreams = ongoingCallViewModel::requestVideoStreams,
hideDoubleTapToast = ongoingCallViewModel::hideDoubleTapToast,
onCameraPermissionPermanentlyDenied = {
permissionPermanentlyDeniedDialogState.show(
PermissionPermanentlyDeniedDialogState.Visible(
title = R.string.app_permission_dialog_title,
description = R.string.camera_permission_dialog_description
)
}
)
BackHandler {
activity.moveTaskToBack(true)
)
}
)
BackHandler {
activity.moveTaskToBack(true)
}

PermissionPermanentlyDeniedDialog(
Expand Down Expand Up @@ -216,18 +206,8 @@ private fun HandleSendingVideoFeed(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun OngoingCallContent(
conversationId: ConversationId,
conversationName: ConversationName?,
participants: List<UICallParticipant>,
isMuted: Boolean,
isCameraOn: Boolean,
isOnFrontCamera: Boolean,
isSpeakerOn: Boolean,
isCbrEnabled: Boolean,
callState: CallState,
shouldShowDoubleTapToast: Boolean,
protocolInfo: Conversation.ProtocolInfo?,
mlsVerificationStatus: Conversation.VerificationStatus?,
proteusVerificationStatus: Conversation.VerificationStatus?,
toggleSpeaker: () -> Unit,
toggleMute: () -> Unit,
hangUpCall: () -> Unit,
Expand All @@ -239,7 +219,7 @@ private fun OngoingCallContent(
hideDoubleTapToast: () -> Unit,
onCameraPermissionPermanentlyDenied: () -> Unit,
requestVideoStreams: (participants: List<UICallParticipant>) -> Unit
) {
) = with(callState) {

val sheetInitialValue = SheetValue.PartiallyExpanded
val sheetState = rememberStandardBottomSheetState(
Expand Down Expand Up @@ -274,7 +254,7 @@ private fun OngoingCallContent(
sheetContent = {
CallingControls(
conversationId = conversationId,
isMuted = isMuted,
isMuted = isMuted ?: true,
isCameraOn = isCameraOn,
isOnFrontCamera = isOnFrontCamera,
isSpeakerOn = isSpeakerOn,
Expand Down Expand Up @@ -329,20 +309,23 @@ private fun OngoingCallContent(
if (shouldOpenFullScreen) {
hideDoubleTapToast()
FullScreenTile(
callState = callState,
selectedParticipant = selectedParticipantForFullScreen,
height = [email protected] - dimensions().spacing4x,
closeFullScreen = {
shouldOpenFullScreen = !shouldOpenFullScreen
},
onBackButtonClicked = {
shouldOpenFullScreen = !shouldOpenFullScreen
}
},
setVideoPreview = setVideoPreview,
clearVideoPreview = clearVideoPreview,
)
} else {
VerticalCallingPager(
participants = participants,
isSelfUserCameraOn = isCameraOn,
isSelfUserMuted = isMuted,
isSelfUserMuted = isMuted ?: true,
contentHeight = [email protected],
onSelfVideoPreviewCreated = setVideoPreview,
onSelfClearVideoPreview = clearVideoPreview,
Expand Down Expand Up @@ -469,22 +452,23 @@ private fun CallingControls(
}
}

@PreviewMultipleThemes
@Composable
fun PreviewOngoingCallScreen() = WireTheme {
fun PreviewOngoingCallContent(participants: List<UICallParticipant>) {
OngoingCallContent(
conversationId = ConversationId("conversationId", "domain"),
conversationName = ConversationName.Known("Conversation Name"),
participants = emptyList(),
isMuted = false,
isCameraOn = false,
isOnFrontCamera = false,
isSpeakerOn = false,
isCbrEnabled = false,
callState = CallState(
conversationId = ConversationId("conversationId", "domain"),
conversationName = ConversationName.Known("Conversation Name"),
participants = participants,
isMuted = false,
isCameraOn = false,
isOnFrontCamera = false,
isSpeakerOn = false,
isCbrEnabled = false,
protocolInfo = null,
mlsVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED,
proteusVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED,
),
shouldShowDoubleTapToast = false,
protocolInfo = null,
mlsVerificationStatus = null,
proteusVerificationStatus = null,
toggleSpeaker = {},
toggleMute = {},
hangUpCall = {},
Expand All @@ -499,8 +483,45 @@ fun PreviewOngoingCallScreen() = WireTheme {
)
}

@PreviewMultipleThemes
@Composable
fun PreviewOngoingCallScreenConnecting() = WireTheme {
PreviewOngoingCallContent(participants = emptyList())
}

@PreviewMultipleThemes
@Composable
fun PreviewOngoingCallScreen_2Participants() = WireTheme {
PreviewOngoingCallContent(participants = buildPreviewParticipantsList(2))
}

@PreviewMultipleThemes
@Composable
fun PreviewOngoingCallScreen_8Participants() = WireTheme {
PreviewOngoingCallContent(participants = buildPreviewParticipantsList(8))
}

@PreviewMultipleThemes
@Composable
fun PreviewOngoingCallTopBar() = WireTheme {
OngoingCallTopBar("Default", true, null, null, null) { }
}

fun buildPreviewParticipantsList(count: Int = 10) = buildList {
repeat(count) { index ->
add(
UICallParticipant(
id = QualifiedID("id_$index", ""),
clientId = "client_id_$index",
name = "Participant $index",
isSpeaking = index % 3 == 1,
isMuted = index % 3 == 2,
hasEstablishedAudio = index % 3 != 2,
isCameraOn = false,
isSharingScreen = false,
avatar = null,
membership = Membership.Admin,
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.wire.android.ui.calling.ongoing.fullscreen

import android.view.View
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
Expand All @@ -37,33 +38,39 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.wire.android.R
import com.wire.android.ui.calling.SharedCallingViewModel
import com.wire.android.ui.calling.CallState
import com.wire.android.ui.calling.ongoing.OngoingCallViewModel.Companion.DOUBLE_TAP_TOAST_DISPLAY_TIME
import com.wire.android.ui.calling.ongoing.buildPreviewParticipantsList
import com.wire.android.ui.calling.ongoing.participantsview.ParticipantTile
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.theme.WireTheme
import com.wire.android.util.ui.PreviewMultipleThemes
import com.wire.kalium.logic.data.id.ConversationId
import kotlinx.coroutines.delay

@Composable
fun FullScreenTile(
sharedCallingViewModel: SharedCallingViewModel = hiltViewModel(),
callState: CallState,
selectedParticipant: SelectedParticipant,
height: Dp,
closeFullScreen: (offset: Offset) -> Unit,
onBackButtonClicked: () -> Unit
onBackButtonClicked: () -> Unit,
setVideoPreview: (View) -> Unit,
clearVideoPreview: () -> Unit,
modifier: Modifier = Modifier,
contentPadding: Dp = dimensions().spacing4x,
) {
var shouldShowDoubleTapToast by remember { mutableStateOf(false) }

BackHandler {
onBackButtonClicked()
}

sharedCallingViewModel.callState.participants.find {
callState.participants.find {
it.id == selectedParticipant.userId && it.clientId == selectedParticipant.clientId
}?.let {
Box {
Box(modifier = modifier) {
ParticipantTile(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -74,26 +81,23 @@ fun FullScreenTile(
)
}
.height(height)
.padding(
start = dimensions().spacing4x,
end = dimensions().spacing4x
),
.padding(contentPadding),
participantTitleState = it,
isSelfUser = selectedParticipant.isSelfUser,
isSelfUserCameraOn = if (selectedParticipant.isSelfUser) {
sharedCallingViewModel.callState.isCameraOn
callState.isCameraOn
} else {
it.isCameraOn
},
isSelfUserMuted = if (selectedParticipant.isSelfUser) {
sharedCallingViewModel.callState.isMuted!!
callState.isMuted!!
} else {
it.isMuted
},
shouldFill = false,
isZoomingEnabled = true,
onSelfUserVideoPreviewCreated = sharedCallingViewModel::setVideoPreview,
onClearSelfUserVideoPreview = sharedCallingViewModel::clearVideoPreview
onSelfUserVideoPreviewCreated = setVideoPreview,
onClearSelfUserVideoPreview = clearVideoPreview
)
LaunchedEffect(Unit) {
delay(200)
Expand All @@ -116,11 +120,22 @@ fun FullScreenTile(

@PreviewMultipleThemes
@Composable
fun PreviewFullScreenVideoCall() {
fun PreviewFullScreenTile() = WireTheme {
val participants = buildPreviewParticipantsList(1)
FullScreenTile(
selectedParticipant = SelectedParticipant(),
height = 100.dp,
callState = CallState(
conversationId = ConversationId("id", "domain"),
participants = participants,
),
selectedParticipant = SelectedParticipant(
userId = participants.first().id,
clientId = participants.first().clientId,
isSelfUser = false,
),
height = 800.dp,
closeFullScreen = {},
onBackButtonClicked = {}
onBackButtonClicked = {},
setVideoPreview = {},
clearVideoPreview = {},
)
}
Loading
Loading