Merge branch 'develop' into feature/bma/removeExternalCallSupport
This commit is contained in:
commit
f4b3ddfa0b
262 changed files with 1644 additions and 825 deletions
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.call.impl.ui
|
||||
internal sealed interface CallScreenBackPressAction {
|
||||
data object DispatchEscapeToWebView : CallScreenBackPressAction
|
||||
data object EnterPictureInPicture : CallScreenBackPressAction
|
||||
}
|
||||
|
||||
internal object CallScreenBackPressPolicy {
|
||||
fun resolve(
|
||||
supportPip: Boolean,
|
||||
hasWebView: Boolean,
|
||||
fromNative: Boolean,
|
||||
): CallScreenBackPressAction? {
|
||||
return when {
|
||||
hasWebView && fromNative -> CallScreenBackPressAction.DispatchEscapeToWebView
|
||||
hasWebView && supportPip -> CallScreenBackPressAction.EnterPictureInPicture
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,11 +64,15 @@ internal fun CallScreenView(
|
|||
requestPermissions: (Array<String>, RequestPermissionCallback) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
fun handleBack() {
|
||||
if (pipState.supportPip) {
|
||||
pipState.eventSink.invoke(PictureInPictureEvent.EnterPictureInPicture)
|
||||
} else {
|
||||
state.eventSink(CallScreenEvent.Hangup)
|
||||
var callWebView by remember { mutableStateOf<WebView?>(null) }
|
||||
|
||||
fun handleBack(fromNative: Boolean = false) {
|
||||
when (CallScreenBackPressPolicy.resolve(supportPip = pipState.supportPip, hasWebView = callWebView != null, fromNative)) {
|
||||
CallScreenBackPressAction.EnterPictureInPicture ->
|
||||
pipState.eventSink(PictureInPictureEvent.EnterPictureInPicture)
|
||||
CallScreenBackPressAction.DispatchEscapeToWebView ->
|
||||
callWebView?.dispatchEscKeyEvent()
|
||||
null -> Timber.d("Back press with unsupported pip is a no-op")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +80,7 @@ internal fun CallScreenView(
|
|||
modifier = modifier,
|
||||
) { padding ->
|
||||
BackHandler {
|
||||
handleBack()
|
||||
handleBack(fromNative = true)
|
||||
}
|
||||
if (state.webViewError != null) {
|
||||
ErrorDialog(
|
||||
|
|
@ -111,6 +115,7 @@ internal fun CallScreenView(
|
|||
},
|
||||
onConsoleMessage = onConsoleMessage,
|
||||
onCreateWebView = { webView ->
|
||||
callWebView = webView
|
||||
webView.addBackHandler(onBackPressed = ::handleBack)
|
||||
val interceptor = WebViewWidgetMessageInterceptor(
|
||||
webView = webView,
|
||||
|
|
@ -135,6 +140,7 @@ internal fun CallScreenView(
|
|||
pipState.eventSink(PictureInPictureEvent.SetPipController(pipController))
|
||||
},
|
||||
onDestroyWebView = {
|
||||
callWebView = null
|
||||
// Reset audio mode
|
||||
webViewAudioManager?.onCallStopped()
|
||||
}
|
||||
|
|
@ -143,6 +149,7 @@ internal fun CallScreenView(
|
|||
AsyncData.Uninitialized,
|
||||
is AsyncData.Loading ->
|
||||
ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait))
|
||||
|
||||
is AsyncData.Failure -> {
|
||||
Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}")
|
||||
ErrorDialog(
|
||||
|
|
@ -150,6 +157,7 @@ internal fun CallScreenView(
|
|||
onSubmit = { state.eventSink(CallScreenEvent.Hangup) },
|
||||
)
|
||||
}
|
||||
|
||||
is AsyncData.Success -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -248,15 +256,18 @@ private fun WebView.setup(
|
|||
|
||||
private fun WebView.addBackHandler(onBackPressed: () -> Unit) {
|
||||
addJavascriptInterface(
|
||||
object {
|
||||
@Suppress("unused")
|
||||
@JavascriptInterface
|
||||
fun onBackPressed() = onBackPressed()
|
||||
JavascriptBackHandler {
|
||||
onBackPressed()
|
||||
},
|
||||
"backHandler"
|
||||
)
|
||||
}
|
||||
|
||||
private fun WebView.dispatchEscKeyEvent() {
|
||||
dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_ESCAPE))
|
||||
dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_ESCAPE))
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun CallScreenViewPreview(
|
||||
|
|
@ -275,3 +286,8 @@ internal fun CallScreenViewPreview(
|
|||
internal fun InvalidAudioDeviceDialogPreview() = ElementPreview {
|
||||
InvalidAudioDeviceDialog(invalidAudioDeviceReason = InvalidAudioDeviceReason.BT_AUDIO_DEVICE_DISABLED) {}
|
||||
}
|
||||
|
||||
internal fun interface JavascriptBackHandler {
|
||||
@JavascriptInterface
|
||||
fun onBackPressed()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue