Make Element Call screen work edge-to-edge (#6634)

* Update dependency io.element.android:element-call-embedded to v0.19.3

* Remove `Scaffold` component from CallScreenView

* Add immersive mode to calls in landscape orientation

* Add `consumeWindowInsets`, which fixes the webview not displaying any insets for the bottom nav bar

* Update screenshots

* Ignore compact height in PiP mode

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa
2026-05-12 19:33:02 +02:00
committed by GitHub
parent 9eac27515e
commit e8f1bf0085
4 changed files with 100 additions and 82 deletions
@@ -17,9 +17,10 @@ import android.webkit.WebChromeClient
import android.webkit.WebView import android.webkit.WebView
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBars
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -45,7 +46,6 @@ import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import timber.log.Timber import timber.log.Timber
@@ -72,9 +72,6 @@ internal fun CallScreenView(
} }
} }
Scaffold(
modifier = modifier,
) { padding ->
BackHandler { BackHandler {
handleBack() handleBack()
} }
@@ -98,10 +95,7 @@ internal fun CallScreenView(
} }
CallWebView( CallWebView(
modifier = Modifier modifier = modifier.consumeWindowInsets(WindowInsets.systemBars).fillMaxSize(),
.padding(padding)
.consumeWindowInsets(padding)
.fillMaxSize(),
url = state.urlState, url = state.urlState,
userAgent = state.userAgent, userAgent = state.userAgent,
onPermissionsRequest = { request -> onPermissionsRequest = { request ->
@@ -153,7 +147,6 @@ internal fun CallScreenView(
is AsyncData.Success -> Unit is AsyncData.Success -> Unit
} }
} }
}
} }
@Composable @Composable
@@ -32,6 +32,9 @@ import androidx.compose.runtime.rememberUpdatedState
import androidx.core.app.PictureInPictureModeChangedInfo import androidx.core.app.PictureInPictureModeChangedInfo
import androidx.core.content.IntentCompat import androidx.core.content.IntentCompat
import androidx.core.util.Consumer import androidx.core.util.Consumer
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Inject
import io.element.android.compound.colors.SemanticColorsLightDark import io.element.android.compound.colors.SemanticColorsLightDark
@@ -52,6 +55,7 @@ import io.element.android.libraries.audio.api.AudioFocusRequester
import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.designsystem.theme.ElementThemeApp import io.element.android.libraries.designsystem.theme.ElementThemeApp
import io.element.android.libraries.designsystem.utils.hasCompactHeightWindowSize
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import timber.log.Timber import timber.log.Timber
@@ -111,6 +115,27 @@ class ElementCallActivity :
val colors by remember(webViewTarget.value?.sessionId) { val colors by remember(webViewTarget.value?.sessionId) {
enterpriseService.semanticColorsFlow(sessionId = webViewTarget.value?.sessionId) enterpriseService.semanticColorsFlow(sessionId = webViewTarget.value?.sessionId)
}.collectAsState(SemanticColorsLightDark.default) }.collectAsState(SemanticColorsLightDark.default)
// When the height is compact, hide the system bars by default to maximize the space for the call, using immersive mode
val hasCompactHeight = hasCompactHeightWindowSize()
DisposableEffect(hasCompactHeight, pipState.isInPictureInPicture) {
if (hasCompactHeight && !pipState.isInPictureInPicture) {
val window = this@ElementCallActivity.window ?: return@DisposableEffect onDispose {}
val insetsController = WindowCompat.getInsetsController(window, window.decorView)
val systemBarInsets = WindowInsetsCompat.Type.systemBars()
insetsController.hide(systemBarInsets)
insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
onDispose {
insetsController.show(systemBarInsets)
insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
}
} else {
onDispose {}
}
}
ElementThemeApp( ElementThemeApp(
appPreferencesStore = appPreferencesStore, appPreferencesStore = appPreferencesStore,
featureFlagService = featureFlagService, featureFlagService = featureFlagService,