Merge pull request #3199 from element-hq/feature/bma/improvePip

Improve pip and add feature flag.
This commit is contained in:
Benoit Marty
2024-07-16 10:18:13 +02:00
committed by GitHub
11 changed files with 66 additions and 3 deletions

View File

@@ -43,6 +43,7 @@ dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.core)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.featureflag.api)
implementation(projects.libraries.matrix.impl)
implementation(projects.libraries.matrixui)
implementation(projects.libraries.network)

View File

@@ -16,6 +16,16 @@
package io.element.android.features.call.impl.pip
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
open class PictureInPictureStateProvider : PreviewParameterProvider<PictureInPictureState> {
override val values: Sequence<PictureInPictureState>
get() = sequenceOf(
aPictureInPictureState(supportPip = true),
aPictureInPictureState(supportPip = true, isInPictureInPicture = true),
)
}
fun aPictureInPictureState(
supportPip: Boolean = false,
isInPictureInPicture: Boolean = false,

View File

@@ -24,6 +24,9 @@ import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import kotlinx.coroutines.runBlocking
import javax.inject.Inject
interface PipSupportProvider {
@@ -34,9 +37,15 @@ interface PipSupportProvider {
@ContributesBinding(AppScope::class)
class DefaultPipSupportProvider @Inject constructor(
@ApplicationContext private val context: Context,
private val featureFlagService: FeatureFlagService,
) : PipSupportProvider {
override fun isPipSupported(): Boolean {
val hasSystemFeaturePip = context.packageManager?.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE).orFalse()
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasSystemFeaturePip
val isSupportedByTheOs = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
context.packageManager?.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE).orFalse()
return if (isSupportedByTheOs) {
runBlocking { featureFlagService.isFeatureEnabled(FeatureFlags.PictureInPicture) }
} else {
false
}
}
}

View File

@@ -38,6 +38,7 @@ import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.call.impl.R
import io.element.android.features.call.impl.pip.PictureInPictureEvents
import io.element.android.features.call.impl.pip.PictureInPictureState
import io.element.android.features.call.impl.pip.PictureInPictureStateProvider
import io.element.android.features.call.impl.pip.aPictureInPictureState
import io.element.android.features.call.impl.utils.WebViewWidgetMessageInterceptor
import io.element.android.libraries.architecture.AsyncData
@@ -81,7 +82,7 @@ internal fun CallScreenView(
title = { Text(stringResource(R.string.element_call)) },
navigationIcon = {
BackButton(
imageVector = CompoundIcons.Close(),
imageVector = if (pipState.supportPip) CompoundIcons.ArrowLeft() else CompoundIcons.Close(),
onClick = ::handleBack,
)
}
@@ -195,3 +196,15 @@ internal fun CallScreenViewPreview(
requestPermissions = { _, _ -> },
)
}
@PreviewsDayNight
@Composable
internal fun CallScreenPipViewPreview(
@PreviewParameter(PictureInPictureStateProvider::class) state: PictureInPictureState,
) = ElementPreview {
CallScreenView(
state = aCallScreenState(),
pipState = state,
requestPermissions = { _, _ -> },
)
}

View File

@@ -32,6 +32,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.mutableStateOf
import androidx.core.content.IntentCompat
import androidx.lifecycle.Lifecycle
import io.element.android.features.call.api.CallType
import io.element.android.features.call.impl.DefaultElementCallEntryPoint
import io.element.android.features.call.impl.di.CallBindings
@@ -41,6 +42,7 @@ import io.element.android.features.call.impl.utils.CallIntentDataParser
import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.designsystem.theme.ElementThemeApp
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import timber.log.Timber
import javax.inject.Inject
class ElementCallActivity : AppCompatActivity(), CallScreenNavigator {
@@ -63,6 +65,8 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator {
private var isDarkMode = false
private val webViewTarget = mutableStateOf<CallType?>(null)
private var eventSink: ((CallScreenEvents) -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -91,6 +95,7 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator {
val pipState = pictureInPicturePresenter.present()
ElementThemeApp(appPreferencesStore) {
val state = presenter.present()
eventSink = state.eventSink
CallScreenView(
state = state,
pipState = pipState,
@@ -111,6 +116,11 @@ class ElementCallActivity : AppCompatActivity(), CallScreenNavigator {
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
pictureInPicturePresenter.onPictureInPictureModeChanged(isInPictureInPictureMode)
if (!isInPictureInPictureMode && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
Timber.d("Exiting PiP mode: Hangup the call")
eventSink?.invoke(CallScreenEvents.Hangup)
}
}
override fun onNewIntent(intent: Intent) {

View File

@@ -113,4 +113,11 @@ enum class FeatureFlags(
defaultValue = { true },
isFinished = false,
),
PictureInPicture(
key = "feature.pictureInPicture",
title = "Picture in Picture for Calls",
description = "Allow the Call to be rendered in PiP mode",
defaultValue = { it.buildType != BuildType.RELEASE },
isFinished = false,
),
}

View File

@@ -72,6 +72,7 @@ class KonsistPreviewTest {
"AsyncIndicatorLoadingPreview",
"BloomInitialsPreview",
"BloomPreview",
"CallScreenPipViewPreview",
"ColorAliasesPreview",
"DefaultRoomListTopBarWithIndicatorPreview",
"GradientFloatingActionButtonCircleShapePreview",