fix full screen pip issues

This commit is contained in:
Fabian Freund
2025-07-09 23:15:16 +02:00
parent 905c7dbc68
commit 8a23f37887
2 changed files with 19 additions and 70 deletions
@@ -10,6 +10,7 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -22,7 +23,6 @@ import androidx.fragment.app.Fragment
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
import eu.weblibre.flutter_mozilla_components.databinding.FragmentBrowserBinding
import eu.weblibre.flutter_mozilla_components.ext.getPreferenceKey
import eu.weblibre.flutter_mozilla_components.pip.PictureInPictureIntegration
import eu.weblibre.flutter_mozilla_components.services.DownloadService
import io.flutter.Log
import mozilla.components.browser.state.selector.selectedTab
@@ -35,6 +35,7 @@ import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature
import mozilla.components.feature.privatemode.feature.SecureWindowFeature
import mozilla.components.feature.prompts.PromptFeature
import mozilla.components.feature.session.FullScreenFeature
import mozilla.components.feature.session.PictureInPictureFeature
import mozilla.components.feature.session.SessionFeature
import mozilla.components.feature.session.SwipeRefreshFeature
import mozilla.components.feature.sitepermissions.SitePermissionsFeature
@@ -61,7 +62,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
private val appLinksFeature = ViewBoundFeatureWrapper<AppLinksFeature>()
private val promptFeature = ViewBoundFeatureWrapper<PromptFeature>()
private val webExtensionPromptFeature = ViewBoundFeatureWrapper<WebExtensionPromptFeature>()
private val pictureInPictureIntegration = ViewBoundFeatureWrapper<PictureInPictureIntegration>()
private val sitePermissionsFeature = ViewBoundFeatureWrapper<SitePermissionsFeature>()
private val swipeRefreshFeature = ViewBoundFeatureWrapper<SwipeRefreshFeature>()
private val secureWindowFeature = ViewBoundFeatureWrapper<SecureWindowFeature>()
@@ -69,6 +69,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
private val mediaSessionFullscreenFeature =
ViewBoundFeatureWrapper<MediaSessionFullscreenFeature>()
private var pictureInPictureFeature: PictureInPictureFeature? = null
private val sessionId: String?
get() = arguments?.getString(SESSION_ID_KEY)
@@ -266,6 +268,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
sessionUseCases = components.useCases.sessionUseCases,
tabId = sessionId,
fullScreenChanged = ::fullScreenChanged,
viewportFitChanged = ::viewportFitChanged
),
owner = this,
view = binding.root,
@@ -281,14 +284,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
view = binding.root,
)
pictureInPictureIntegration.set(
feature = PictureInPictureIntegration(
components.core.store,
requireActivity(),
sessionId,
),
owner = this,
view = view,
pictureInPictureFeature = PictureInPictureFeature(
store = components.core.store,
activity = requireActivity(),
tabId = sessionId,
)
secureWindowFeature.set(
@@ -358,23 +357,23 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
}
}
private fun viewportFitChanged(viewportFit: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
activity?.window?.attributes?.layoutInDisplayCutoutMode = viewportFit
}
}
@CallSuper
override fun onBackPressed(): Boolean {
return backButtonHandler.any { it.onBackPressed() }
}
final override fun onPause() {
pictureInPictureIntegration.get()?.onHomePressed() ?: false
super.onPause()
}
final override fun onHomePressed(): Boolean =pictureInPictureFeature?.onHomePressed() ?: false
final override fun onPictureInPictureModeChanged(enabled: Boolean) {
val session = components.core.store.state.selectedTab
val fullScreenMode = session?.content?.fullScreen ?: false
// If we're exiting PIP mode and we're in fullscreen mode, then we should exit fullscreen mode as well.
if (!enabled && fullScreenMode) {
override fun onPictureInPictureModeChanged(enabled: Boolean) {
pictureInPictureFeature?.onPictureInPictureModeChanged(enabled)
if (lifecycle.currentState == androidx.lifecycle.Lifecycle.State.CREATED) {
onBackPressed()
fullScreenChanged(false)
}
}
@@ -1,50 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package eu.weblibre.flutter_mozilla_components.pip
import android.app.Activity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.mapNotNull
import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.session.PictureInPictureFeature
import mozilla.components.lib.state.ext.flowScoped
import mozilla.components.support.base.feature.LifecycleAwareFeature
class PictureInPictureIntegration(
private val store: BrowserStore,
activity: Activity,
private val customTabId: String?,
private val whiteList: List<String> = listOf("youtube.com/tv"),
) : LifecycleAwareFeature {
private var scope: CoroutineScope? = null
private val pictureFeature = PictureInPictureFeature(store, activity)
private var whiteListed = false
override fun start() {
scope = store.flowScoped { flow ->
flow.mapNotNull { state -> state.findTabOrCustomTabOrSelectedTab(customTabId) }
.distinctUntilChangedBy { it.content.url }
.collect { whiteListed = isWhitelisted(it.content.url) }
}
}
override fun stop() {
scope?.cancel()
}
fun onHomePressed() = if (whiteListed) {
pictureFeature.enterPipModeCompat()
} else {
pictureFeature.onHomePressed()
}
private fun isWhitelisted(url: String): Boolean {
val exists = whiteList.firstOrNull { url.contains(it) }
return exists != null
}
}