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 // All the UI Logic for the player
open class FullScreenPlayer : AbstractPlayerFragment() { open class FullScreenPlayer : AbstractPlayerFragment() {
private var isVerticalOrientation: Boolean = false
protected open var lockRotation = true protected open var lockRotation = true
protected open var isFullScreenPlayer = true protected open var isFullScreenPlayer = true
protected open var isTv = false protected open var isTv = false
@ -111,6 +112,8 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
protected var playerResizeEnabled = false protected var playerResizeEnabled = false
protected var doubleTapEnabled = false protected var doubleTapEnabled = false
protected var doubleTapPauseEnabled = true protected var doubleTapPauseEnabled = true
protected var playerRotateEnabled = false
protected var autoPlayerRotateEnabled = false
protected var subtitleDelay protected var subtitleDelay
set(value) = try { set(value) = try {
@ -286,6 +289,38 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
player.getCurrentPreferredSubtitle() == null 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) { open fun lockOrientation(activity: Activity) {
val display = val display =
(activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay (activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
@ -293,24 +328,39 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
val currentOrientation = activity.resources.configuration.orientation val currentOrientation = activity.resources.configuration.orientation
var orientation = 0 var orientation = 0
when (currentOrientation) { when (currentOrientation) {
Configuration.ORIENTATION_LANDSCAPE -> orientation = Configuration.ORIENTATION_LANDSCAPE ->
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_REVERSE_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_SQUARE, Configuration.ORIENTATION_UNDEFINED ->
//Configuration.ORIENTATION_PORTRAIT -> orientation = orientation = dynamicOrientation()
// if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
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 activity.requestedOrientation = orientation
} }
private fun updateOrientation() { private fun updateOrientation(ignoreDynamicOrientation: Boolean = false) {
activity?.apply { activity?.apply {
if(lockRotation) { if(lockRotation) {
if(isLocked) { if(isLocked) {
lockOrientation(this) lockOrientation(this)
} }
else { 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 isLocked = !isLocked
updateOrientation() updateOrientation(true) // set true to ignore auto rotate to stay in current orientation
if (isLocked && isShowing) { if (isLocked && isShowing) {
playerBinding?.playerHolder?.postDelayed({ playerBinding?.playerHolder?.postDelayed({
@ -1326,6 +1376,14 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
ctx.getString(R.string.playback_speed_enabled_key), ctx.getString(R.string.playback_speed_enabled_key),
false 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 = playerResizeEnabled =
settingsManager.getBoolean( settingsManager.getBoolean(
ctx.getString(R.string.player_resize_enabled_key), ctx.getString(R.string.player_resize_enabled_key),
@ -1362,6 +1420,7 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
playerBinding?.apply { playerBinding?.apply {
playerSpeedBtt.isVisible = playBackSpeedEnabled playerSpeedBtt.isVisible = playBackSpeedEnabled
playerResizeBtt.isVisible = playerResizeEnabled playerResizeBtt.isVisible = playerResizeEnabled
playerRotateBtt.isVisible = playerRotateEnabled
} }
} catch (e: Exception) { } catch (e: Exception) {
logError(e) logError(e)
@ -1376,6 +1435,11 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
player.handleEvent(CSPlayerEvent.SkipCurrentChapter) player.handleEvent(CSPlayerEvent.SkipCurrentChapter)
} }
playerRotateBtt.setOnClickListener {
autoHide()
toggleRotate()
}
// init clicks // init clicks
playerResizeBtt.setOnClickListener { playerResizeBtt.setOnClickListener {
autoHide() autoHide()
@ -1481,4 +1545,28 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
logError(e) 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) { override fun playerDimensionsLoaded(width: Int, height: Int) {
super.playerDimensionsLoaded(width, height)
setPlayerDimen(width to 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"> android:orientation="horizontal">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/player_resize_btt" android:id="@+id/player_rotate_btt"
style="@style/VideoButton" style="@style/VideoButton"
android:nextFocusLeft="@id/player_lock" 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:nextFocusRight="@id/player_speed_btt"
android:text="@string/video_aspect_ratio_resize" android:text="@string/video_aspect_ratio_resize"
app:icon="@drawable/ic_baseline_aspect_ratio_24" /> app:icon="@drawable/ic_baseline_aspect_ratio_24" />

View file

@ -638,6 +638,11 @@
app:icon="@drawable/video_locked" /> app:icon="@drawable/video_locked" />
</FrameLayout> </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 <com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_op" android:id="@+id/player_skip_op"
style="@style/VideoButtonTV" style="@style/VideoButtonTV"

View file

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

View file

@ -734,4 +734,10 @@
<string name="logged_account" formatted="true">Logged in as %s</string> <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="skip_startup_account_select_pref">Skip account selection at startup</string>
<string name="use_default_account">Use Default Account</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> </resources>

View file

@ -86,6 +86,18 @@
app:defaultValue="true" app:defaultValue="true"
android:summary="@string/enable_skip_op_from_database_des" android:summary="@string/enable_skip_op_from_database_des"
app:key="@string/enable_skip_op_from_database" /> 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>
<PreferenceCategory <PreferenceCategory