feat (player): optional rotate button in player and setting to enable auto rotate based on video orientation (#813)

Co-authored-by: coxju <coxju>
This commit is contained in:
coxju 2023-12-19 19:50:58 +05:30 committed by GitHub
parent db91552f39
commit a5f7920bca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 144 additions and 9 deletions

View File

@ -75,6 +75,7 @@ private const val SUBTITLE_DELAY_BUNDLE_KEY = "subtitle_delay"
// All the UI Logic for the player
open class FullScreenPlayer : AbstractPlayerFragment() {
private var isVerticalOrientation: Boolean = false
protected open var lockRotation = true
protected open var isFullScreenPlayer = true
protected open var isTv = false
@ -111,6 +112,8 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
protected var playerResizeEnabled = false
protected var doubleTapEnabled = false
protected var doubleTapPauseEnabled = true
protected var playerRotateEnabled = false
protected var autoPlayerRotateEnabled = false
protected var subtitleDelay
set(value) = try {
@ -286,6 +289,38 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
player.getCurrentPreferredSubtitle() == null
}
private fun restoreOrientationWithSensor(activity: Activity){
val currentOrientation = activity.resources.configuration.orientation
var orientation = 0
when (currentOrientation) {
Configuration.ORIENTATION_LANDSCAPE ->
orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
Configuration.ORIENTATION_SQUARE, Configuration.ORIENTATION_UNDEFINED ->
orientation = dynamicOrientation()
Configuration.ORIENTATION_PORTRAIT ->
orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
}
activity.requestedOrientation = orientation
}
private fun toggleOrientationWithSensor(activity: Activity){
val currentOrientation = activity.resources.configuration.orientation
var orientation = 0
when (currentOrientation) {
Configuration.ORIENTATION_LANDSCAPE ->
orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
Configuration.ORIENTATION_SQUARE, Configuration.ORIENTATION_UNDEFINED ->
orientation = dynamicOrientation()
Configuration.ORIENTATION_PORTRAIT ->
orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
}
activity.requestedOrientation = orientation
}
open fun lockOrientation(activity: Activity) {
val display =
(activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
@ -293,24 +328,39 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
val currentOrientation = activity.resources.configuration.orientation
var orientation = 0
when (currentOrientation) {
Configuration.ORIENTATION_LANDSCAPE -> orientation =
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
Configuration.ORIENTATION_LANDSCAPE ->
orientation =
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90)
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
else
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
Configuration.ORIENTATION_SQUARE, Configuration.ORIENTATION_UNDEFINED, Configuration.ORIENTATION_PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
//Configuration.ORIENTATION_PORTRAIT -> orientation =
// if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
Configuration.ORIENTATION_SQUARE, Configuration.ORIENTATION_UNDEFINED ->
orientation = dynamicOrientation()
Configuration.ORIENTATION_PORTRAIT ->
orientation =
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
else
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
}
activity.requestedOrientation = orientation
}
private fun updateOrientation() {
private fun updateOrientation(ignoreDynamicOrientation: Boolean = false) {
activity?.apply {
if(lockRotation) {
if(isLocked) {
lockOrientation(this)
}
else {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
if(ignoreDynamicOrientation){
// restore when lock is disabled
restoreOrientationWithSensor(this)
} else {
this.requestedOrientation = dynamicOrientation()
}
}
}
}
@ -584,7 +634,7 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
}
isLocked = !isLocked
updateOrientation()
updateOrientation(true) // set true to ignore auto rotate to stay in current orientation
if (isLocked && isShowing) {
playerBinding?.playerHolder?.postDelayed({
@ -1326,6 +1376,14 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
ctx.getString(R.string.playback_speed_enabled_key),
false
)
playerRotateEnabled = settingsManager.getBoolean(
ctx.getString(R.string.rotate_video_key),
false
)
autoPlayerRotateEnabled = settingsManager.getBoolean(
ctx.getString(R.string.auto_rotate_video_key),
false
)
playerResizeEnabled =
settingsManager.getBoolean(
ctx.getString(R.string.player_resize_enabled_key),
@ -1362,6 +1420,7 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
playerBinding?.apply {
playerSpeedBtt.isVisible = playBackSpeedEnabled
playerResizeBtt.isVisible = playerResizeEnabled
playerRotateBtt.isVisible = playerRotateEnabled
}
} catch (e: Exception) {
logError(e)
@ -1376,6 +1435,11 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
player.handleEvent(CSPlayerEvent.SkipCurrentChapter)
}
playerRotateBtt.setOnClickListener {
autoHide()
toggleRotate()
}
// init clicks
playerResizeBtt.setOnClickListener {
autoHide()
@ -1481,4 +1545,28 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
logError(e)
}
}
@SuppressLint("SourceLockedOrientationActivity")
private fun toggleRotate() {
activity?.let {
toggleOrientationWithSensor(it)
}
}
override fun playerDimensionsLoaded(width: Int, height: Int) {
isVerticalOrientation = height > width
updateOrientation()
}
private fun dynamicOrientation(): Int {
return if (autoPlayerRotateEnabled) {
if (isVerticalOrientation) {
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
} else {
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
}
} else {
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE // default orientation
}
}
}

View File

@ -1237,6 +1237,7 @@ class GeneratorPlayer : FullScreenPlayer() {
}
override fun playerDimensionsLoaded(width: Int, height: Int) {
super.playerDimensionsLoaded(width, height)
setPlayerDimen(width to height)
}

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/white">
<path
android:fillColor="@android:color/white"
android:pathData="M496,778L182,464Q159,441 159,410Q159,379 182,356L356,182Q379,159 410,159Q441,159 464,182L778,496Q801,519 801,550Q801,581 778,604L604,778Q581,801 550,801Q519,801 496,778ZM550,720Q550,720 550,720Q550,720 550,720L720,550Q720,550 720,550Q720,550 720,550L410,240Q410,240 410,240Q410,240 410,240L240,410Q240,410 240,410Q240,410 240,410L550,720ZM480,960Q381,960 293.5,922.5Q206,885 140.5,819.5Q75,754 37.5,666.5Q0,579 0,480L80,480Q80,551 104,616Q128,681 170.5,733Q213,785 272,821.5Q331,858 401,873L296,768L352,712L588,948Q562,954 534.5,957Q507,960 480,960ZM880,480Q880,409 856,344Q832,279 789.5,227Q747,175 688,138.5Q629,102 559,87L664,192L608,248L372,12Q398,6 425.5,3Q453,0 480,0Q579,0 666.5,37.5Q754,75 819.5,140.5Q885,206 922.5,293.5Q960,381 960,480L880,480ZM480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Q480,480 480,480Q480,480 480,480Z"/>
</vector>

View File

@ -550,10 +550,19 @@
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/player_resize_btt"
android:id="@+id/player_rotate_btt"
style="@style/VideoButton"
android:nextFocusLeft="@id/player_lock"
android:nextFocusRight="@id/player_resize_btt"
android:text="@string/rotate_video"
app:icon="@drawable/screen_rotation" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_resize_btt"
style="@style/VideoButton"
android:nextFocusLeft="@id/player_rotate_btt"
android:nextFocusRight="@id/player_speed_btt"
android:text="@string/video_aspect_ratio_resize"
app:icon="@drawable/ic_baseline_aspect_ratio_24" />

View File

@ -638,6 +638,11 @@
app:icon="@drawable/video_locked" />
</FrameLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/player_rotate_btt"
style="@style/VideoButton"
android:visibility="gone"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_op"
style="@style/VideoButtonTV"

View File

@ -534,6 +534,10 @@
android:paddingTop="10dp"
android:paddingBottom="10dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/player_rotate_btt"
style="@style/VideoButton"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/player_lock"
style="@style/VideoButton"

View File

@ -734,4 +734,10 @@
<string name="logged_account" formatted="true">Logged in as %s</string>
<string name="skip_startup_account_select_pref">Skip account selection at startup</string>
<string name="use_default_account">Use Default Account</string>
<string name="rotate_video">Rotate</string>
<string name="rotate_video_key">rotate_video_key</string>
<string name="rotate_video_desc">Display a toggle button for screen orientation</string>
<string name="auto_rotate_video_key">auto_rotate_video_key</string>
<string name="auto_rotate_video_desc">Enable automatic switching of screen orientation based on video orientation</string>
<string name="auto_rotate_video">Auto rotate</string>
</resources>

View File

@ -86,6 +86,18 @@
app:defaultValue="true"
android:summary="@string/enable_skip_op_from_database_des"
app:key="@string/enable_skip_op_from_database" />
<SwitchPreference
android:icon="@drawable/screen_rotation"
android:title="@string/rotate_video"
app:defaultValue="false"
android:summary="@string/rotate_video_desc"
app:key="@string/rotate_video_key" />
<SwitchPreference
android:icon="@drawable/screen_rotation"
android:title="@string/auto_rotate_video"
app:defaultValue="false"
android:summary="@string/auto_rotate_video_desc"
app:key="@string/auto_rotate_video_key" />
</PreferenceCategory>
<PreferenceCategory