mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-15 07:28:30 +00:00
Add proper picture in picture support to compose CallScreen component.
This commit is contained in:
committed by
Jeffrey Starke
parent
affe97a060
commit
515f3dd43f
@@ -80,6 +80,7 @@ fun CallScreen(
|
||||
callRecipient: Recipient,
|
||||
webRtcCallState: WebRtcViewModel.State,
|
||||
isRemoteVideoOffer: Boolean,
|
||||
isInPipMode: Boolean,
|
||||
callScreenState: CallScreenState,
|
||||
callControlsState: CallControlsState,
|
||||
callScreenController: CallScreenController = CallScreenController.rememberCallScreenController(
|
||||
@@ -110,6 +111,16 @@ fun CallScreen(
|
||||
callStatus = callScreenState.callStatus,
|
||||
callScreenControlsListener = callScreenControlsListener
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (isInPipMode) {
|
||||
PictureInPictureCallScreen(
|
||||
callParticipantsPagerState = callParticipantsPagerState,
|
||||
callScreenController = callScreenController
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -532,6 +543,7 @@ private fun CallScreenPreview() {
|
||||
callRecipient = Recipient(systemContactName = "Test User"),
|
||||
webRtcCallState = WebRtcViewModel.State.CALL_CONNECTED,
|
||||
isRemoteVideoOffer = false,
|
||||
isInPipMode = false,
|
||||
callScreenState = CallScreenState(),
|
||||
callControlsState = CallControlsState(
|
||||
displayMicToggle = true,
|
||||
|
||||
@@ -24,6 +24,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.ui.compose.rememberIsInPipMode
|
||||
import org.signal.core.ui.compose.theme.SignalTheme
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.components.webrtc.CallParticipantListUpdate
|
||||
@@ -122,6 +123,7 @@ class ComposeCallScreenMediator(private val activity: WebRtcCallActivity, viewMo
|
||||
callRecipient = recipient,
|
||||
webRtcCallState = webRtcCallState,
|
||||
isRemoteVideoOffer = viewModel.isAnswerWithVideoAvailable(),
|
||||
isInPipMode = rememberIsInPipMode(),
|
||||
callScreenState = callScreenState,
|
||||
callControlsState = callControlsState,
|
||||
callScreenController = callScreenController,
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.webrtc.v2
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Displayed when the user minimizes the call screen while a call is ongoing.
|
||||
*/
|
||||
@Composable
|
||||
fun PictureInPictureCallScreen(
|
||||
callParticipantsPagerState: CallParticipantsPagerState,
|
||||
callScreenController: CallScreenController
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
CallParticipantsPager(
|
||||
callParticipantsPagerState = callParticipantsPagerState,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clickable(
|
||||
onClick = {
|
||||
scope.launch {
|
||||
callScreenController.handleEvent(CallScreenController.Event.TOGGLE_CONTROLS)
|
||||
}
|
||||
},
|
||||
enabled = false
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.signal.core.ui.compose
|
||||
|
||||
import android.os.Build
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.core.app.PictureInPictureModeChangedInfo
|
||||
import androidx.core.util.Consumer
|
||||
|
||||
/**
|
||||
* Returns whether the screen is currently in the system picture-in-picture mode.
|
||||
*
|
||||
* This requires an AppCompatActivity context, so it cannot be utilized in Composables
|
||||
* that require a preview.
|
||||
*/
|
||||
@Composable
|
||||
fun rememberIsInPipMode(): Boolean {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val activity = LocalContext.current as AppCompatActivity
|
||||
var pipMode: Boolean by remember { mutableStateOf(activity.isInPictureInPictureMode) }
|
||||
DisposableEffect(activity) {
|
||||
val observer = Consumer<PictureInPictureModeChangedInfo> { info ->
|
||||
pipMode = info.isInPictureInPictureMode
|
||||
}
|
||||
activity.addOnPictureInPictureModeChangedListener(
|
||||
observer
|
||||
)
|
||||
onDispose { activity.removeOnPictureInPictureModeChangedListener(observer) }
|
||||
}
|
||||
return pipMode
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user