diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ea6f3e5b..c5c20aec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -153,30 +153,30 @@ + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem"> @@ -189,54 +189,54 @@ + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> + android:theme="@style/Theme.FutoVideo.NoActionBarFitsSystem" /> diff --git a/app/src/main/java/com/futo/platformplayer/RootInsetsController.kt b/app/src/main/java/com/futo/platformplayer/RootInsetsController.kt new file mode 100644 index 00000000..bf1d45ff --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/RootInsetsController.kt @@ -0,0 +1,118 @@ +package com.futo.platformplayer + +import android.app.Activity +import android.graphics.Color +import android.os.Build +import android.view.ViewGroup +import android.view.Window +import android.view.WindowManager +import androidx.core.graphics.Insets +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsCompat.Type +import androidx.core.view.WindowInsetsControllerCompat +import androidx.core.view.doOnAttach +import androidx.core.view.updatePadding +import kotlin.math.max + +class RootInsetsController private constructor( + private val activity: Activity, + private val window: Window, + private val root: ViewGroup +) { + private val controller by lazy { WindowInsetsControllerCompat(window, root) } + + private val basePaddingLeft = root.paddingLeft + private val basePaddingTop = root.paddingTop + private val basePaddingRight = root.paddingRight + private val basePaddingBottom = root.paddingBottom + + private var currentInsets: WindowInsetsCompat = WindowInsetsCompat.CONSUMED + private var fullscreen = false + + init { + WindowCompat.setDecorFitsSystemWindows(window, false) + window.statusBarColor = Color.TRANSPARENT + window.navigationBarColor = Color.TRANSPARENT + controller.systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + + ViewCompat.setOnApplyWindowInsetsListener(root) { _, insets -> + currentInsets = insets + applyPadding() + insets + } + + root.doOnAttach { ViewCompat.requestApplyInsets(root) } + } + + private fun effectiveInsets(): Insets { + if (fullscreen) return Insets.NONE + + val sys = currentInsets.getInsets(Type.systemBars()) + val cut = currentInsets.getInsetsIgnoringVisibility(Type.displayCutout()) + val portrait = activity.resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT + + val top = if (portrait) max(sys.top, cut.top) else sys.top + return Insets.of(sys.left, top, sys.right, sys.bottom) + } + + + private fun applyPadding() { + val e = effectiveInsets() + root.updatePadding( + left = basePaddingLeft + e.left, + top = basePaddingTop + e.top, + right = basePaddingRight + e.right, + bottom = basePaddingBottom + e.bottom + ) + } + + private fun forceRelayoutAndInsets() { + root.post { + ViewCompat.requestApplyInsets(root) + applyPadding() + root.post { + ViewCompat.requestApplyInsets(root) + applyPadding() + } + } + } + + fun enterFullscreen(allowCutoutShortEdges: Boolean = true) { + fullscreen = true + if (allowCutoutShortEdges) { + window.attributes = window.attributes.apply { + layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES + } + } + controller.hide(Type.systemBars()) + forceRelayoutAndInsets() + } + + fun exitFullscreen() { + fullscreen = false + window.attributes = window.attributes.apply { + layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT + } + controller.show(Type.systemBars()) + forceRelayoutAndInsets() + } + + fun onConfigurationChanged() { + forceRelayoutAndInsets() + } + + fun setLightSystemBarAppearance(lightStatus: Boolean, lightNav: Boolean) { + controller.isAppearanceLightStatusBars = lightStatus + controller.isAppearanceLightNavigationBars = lightNav + } + + companion object { + fun attach(activity: Activity, root: ViewGroup): RootInsetsController { + return RootInsetsController(activity, activity.window, root) + } + } +} diff --git a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt index d824d18c..2d56cb35 100644 --- a/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt +++ b/app/src/main/java/com/futo/platformplayer/activities/MainActivity.kt @@ -16,7 +16,6 @@ import android.os.StrictMode.VmPolicy import android.util.Log import android.util.TypedValue import android.view.View -import android.view.WindowManager import android.widget.FrameLayout import android.widget.ImageView import androidx.activity.result.ActivityResult @@ -36,6 +35,7 @@ import androidx.lifecycle.withStateAtLeast import androidx.media3.common.util.UnstableApi import com.futo.platformplayer.BuildConfig import com.futo.platformplayer.R +import com.futo.platformplayer.RootInsetsController import com.futo.platformplayer.Settings import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.api.http.ManagedHttpClient @@ -199,6 +199,7 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { private var _privateModeEnabled = false private var _pictureInPictureEnabled = false private var _isFullscreen = false + private lateinit var _rootInsetsController: RootInsetsController private val _urlQrCodeResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> val scanResult = IntentIntegrator.parseActivityResult(result.resultCode, result.data) @@ -284,9 +285,6 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { } setContentView(R.layout.activity_main); setNavigationBarColorAndIcons(); - if (Settings.instance.playback.allowVideoToGoUnderCutout) - window.attributes.layoutInDisplayCutoutMode = - WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES runBlocking { try { @@ -301,6 +299,9 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { FragmentedStorage.get(); rootView = findViewById(R.id.rootView); + _rootInsetsController = RootInsetsController.attach(this, rootView) + _rootInsetsController.setLightSystemBarAppearance(lightStatus = false, lightNav = false) + _fragContainerTopBar = findViewById(R.id.fragment_top_bar); _fragContainerMain = findViewById(R.id.fragment_main); _fragContainerBotBar = findViewById(R.id.fragment_bottom_bar); @@ -411,6 +412,11 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { Logger.i(TAG, "onFullscreenChanged ${it}"); _isFullscreen = it updatePrivateModeVisibility() + if (it) { + _rootInsetsController.enterFullscreen(allowCutoutShortEdges = Settings.instance.playback.allowVideoToGoUnderCutout) + } else { + _rootInsetsController.exitFullscreen() + } } _fragVideoDetail.onMinimize.subscribe { @@ -639,6 +645,11 @@ class MainActivity : AppCompatActivity, IWithResultLauncher { private var _qrCodeLoadingDialog: AlertDialog? = null + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + _rootInsetsController.onConfigurationChanged() + } + fun showUrlQrCodeScanner() { try { _qrCodeLoadingDialog = UIDialogs.showDialog(this, R.drawable.ic_loader_animated, true, diff --git a/app/src/main/res/layout/activity_add_source.xml b/app/src/main/res/layout/activity_add_source.xml index 469a4508..3b12e6c6 100644 --- a/app/src/main/res/layout/activity_add_source.xml +++ b/app/src/main/res/layout/activity_add_source.xml @@ -15,7 +15,6 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" - android:paddingTop="20dp" android:paddingBottom="15dp"> diff --git a/app/src/main/res/layout/activity_manage_tabs.xml b/app/src/main/res/layout/activity_manage_tabs.xml index 986dfa11..77c8e90c 100644 --- a/app/src/main/res/layout/activity_manage_tabs.xml +++ b/app/src/main/res/layout/activity_manage_tabs.xml @@ -14,7 +14,6 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" - android:paddingTop="20dp" android:paddingBottom="15dp"> diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 0c815387..a29ac552 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -17,7 +17,6 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" - android:paddingTop="20dp" android:paddingBottom="15dp"> diff --git a/app/src/main/res/layout/fragview_post_detail.xml b/app/src/main/res/layout/fragview_post_detail.xml index eb800c5a..0748c17e 100644 --- a/app/src/main/res/layout/fragview_post_detail.xml +++ b/app/src/main/res/layout/fragview_post_detail.xml @@ -5,7 +5,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:fitsSystemWindows="false" android:background="@drawable/bottom_menu_border" android:id="@+id/root" android:clickable="true"> diff --git a/app/src/main/res/layout/fragview_video_detail.xml b/app/src/main/res/layout/fragview_video_detail.xml index 7b8c1dc2..bf287eb9 100644 --- a/app/src/main/res/layout/fragview_video_detail.xml +++ b/app/src/main/res/layout/fragview_video_detail.xml @@ -5,7 +5,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:fitsSystemWindows="false" android:background="@drawable/bottom_menu_border" android:id="@+id/videodetail_root" android:clickable="true"> diff --git a/app/src/main/res/layout/fragview_web_detail.xml b/app/src/main/res/layout/fragview_web_detail.xml index 1bf5d38a..2194126a 100644 --- a/app/src/main/res/layout/fragview_web_detail.xml +++ b/app/src/main/res/layout/fragview_web_detail.xml @@ -5,7 +5,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:fitsSystemWindows="false" android:background="@drawable/bottom_menu_border" android:id="@+id/root" android:clickable="true"> diff --git a/app/src/main/res/values-v29/themes.xml b/app/src/main/res/values-v29/themes.xml new file mode 100644 index 00000000..735f2a4a --- /dev/null +++ b/app/src/main/res/values-v29/themes.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 3f2b80c5..fe77ab0b 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -42,7 +42,8 @@ @color/gray_30 @color/black - @color/black + @android:color/transparent + @android:color/transparent @style/Theme.FutoVideo.ImageButton @style/Theme.FutoVideo.EditText @@ -91,6 +92,16 @@ false true true + @color/black + @color/black + @color/black + @color/transparent + false + false + + +