diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 81895a50..905113d7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -21,7 +21,7 @@
+ android:screenOrientation="sensorLandscape" />
(R.id.back_button).setOnClickListener {
onBackPressed()
diff --git a/app/src/main/java/dev/jdtech/jellyfin/utils/AppPreferences.kt b/app/src/main/java/dev/jdtech/jellyfin/utils/AppPreferences.kt
new file mode 100644
index 00000000..46e0dbbd
--- /dev/null
+++ b/app/src/main/java/dev/jdtech/jellyfin/utils/AppPreferences.kt
@@ -0,0 +1,24 @@
+package dev.jdtech.jellyfin.utils
+
+import android.content.SharedPreferences
+import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
+import androidx.core.content.edit
+import javax.inject.Inject
+
+class AppPreferences
+@Inject
+constructor(
+ private val sharedPreferences: SharedPreferences
+) {
+ var playerBrightness: Float
+ get() = sharedPreferences.getFloat(
+ Constants.PREF_PLAYER_BRIGHTNESS,
+ BRIGHTNESS_OVERRIDE_NONE
+ )
+ set(value) {
+ sharedPreferences.edit {
+ putFloat(Constants.PREF_PLAYER_BRIGHTNESS, value)
+ }
+ }
+
+}
diff --git a/app/src/main/java/dev/jdtech/jellyfin/utils/Constants.kt b/app/src/main/java/dev/jdtech/jellyfin/utils/Constants.kt
new file mode 100644
index 00000000..667bdb3f
--- /dev/null
+++ b/app/src/main/java/dev/jdtech/jellyfin/utils/Constants.kt
@@ -0,0 +1,14 @@
+package dev.jdtech.jellyfin.utils
+
+object Constants {
+
+ //player
+ const val GESTURE_EXCLUSION_AREA_TOP = 48
+ const val FULL_SWIPE_RANGE_SCREEN_RATIO = 0.66f
+ const val ZOOM_SCALE_BASE = 1f
+ const val ZOOM_SCALE_THRESHOLD = 0.01f
+
+ //pref
+ const val PREF_PLAYER_BRIGHTNESS = "pref_player_brightness"
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/dev/jdtech/jellyfin/utils/PlayerGestureHelper.kt b/app/src/main/java/dev/jdtech/jellyfin/utils/PlayerGestureHelper.kt
index d769b07f..afcc2f1c 100644
--- a/app/src/main/java/dev/jdtech/jellyfin/utils/PlayerGestureHelper.kt
+++ b/app/src/main/java/dev/jdtech/jellyfin/utils/PlayerGestureHelper.kt
@@ -4,24 +4,36 @@ import android.media.AudioManager
import android.provider.Settings
import android.view.GestureDetector
import android.view.MotionEvent
+import android.view.ScaleGestureDetector
import android.view.View
import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_FULL
import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF
+import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.PlayerView
import dev.jdtech.jellyfin.PlayerActivity
import timber.log.Timber
import kotlin.math.abs
class PlayerGestureHelper(
+ private val appPreferences: AppPreferences,
private val activity: PlayerActivity,
private val playerView: PlayerView,
private val audioManager: AudioManager
-) {
+) {
+
+
+ /**
+ * Tracks whether video content should fill the screen, cutting off unwanted content on the sides.
+ * Useful on wide-screen phones to remove black bars from some movies.
+ */
+ private var isZoomEnabled = false
+
/**
* Tracks a value during a swipe gesture (between multiple onScroll calls).
* When the gesture starts it's reset to an initial value and gets increased or decreased
* (depending on the direction) as the gesture progresses.
*/
+
private var swipeGestureValueTrackerVolume = -1f
private var swipeGestureValueTrackerBrightness = -1f
@@ -42,10 +54,14 @@ class PlayerGestureHelper(
if (abs(distanceY / distanceX) < 2)
return false
+ if (firstEvent.y < playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_TOP))
+ return false
+
+
val viewCenterX = playerView.measuredWidth / 2
// Distance to swipe to go from min to max
- val distanceFull = playerView.measuredHeight
+ val distanceFull = playerView.measuredHeight * Constants.FULL_SWIPE_RANGE_SCREEN_RATIO
val ratioChange = distanceY / distanceFull
if (firstEvent.x.toInt() > viewCenterX) {
@@ -99,14 +115,39 @@ class PlayerGestureHelper(
private val hideGestureBrightnessIndicatorOverlayAction = Runnable {
activity.binding.gestureBrightnessLayout.visibility = View.GONE
+ appPreferences.playerBrightness = activity.window.attributes.screenBrightness
+ }
+
+ /**
+ * Handles scale/zoom gesture
+ */
+ private val zoomGestureDetector = ScaleGestureDetector(playerView.context, object : ScaleGestureDetector.OnScaleGestureListener {
+ override fun onScaleBegin(detector: ScaleGestureDetector): Boolean = true
+
+ override fun onScale(detector: ScaleGestureDetector): Boolean {
+ val scaleFactor = detector.scaleFactor
+ if (abs(scaleFactor - Constants.ZOOM_SCALE_BASE) > Constants.ZOOM_SCALE_THRESHOLD) {
+ isZoomEnabled = scaleFactor > 1
+ updateZoomMode(isZoomEnabled)
+ }
+ return true
+ }
+
+ override fun onScaleEnd(detector: ScaleGestureDetector) = Unit
+ }).apply { isQuickScaleEnabled = false }
+
+ private fun updateZoomMode(enabled: Boolean) {
+ playerView.resizeMode = if (enabled) AspectRatioFrameLayout.RESIZE_MODE_ZOOM else AspectRatioFrameLayout.RESIZE_MODE_FIT
}
init {
+ activity.window.attributes.screenBrightness = appPreferences.playerBrightness
@Suppress("ClickableViewAccessibility")
playerView.setOnTouchListener { _, event ->
if (playerView.useController) {
when (event.pointerCount) {
1 -> gestureDetector.onTouchEvent(event)
+ 2 -> zoomGestureDetector.onTouchEvent(event)
}
}
if(event.action == MotionEvent.ACTION_UP) {
diff --git a/app/src/main/java/dev/jdtech/jellyfin/utils/extensions.kt b/app/src/main/java/dev/jdtech/jellyfin/utils/extensions.kt
index 69d04439..6eb182ba 100644
--- a/app/src/main/java/dev/jdtech/jellyfin/utils/extensions.kt
+++ b/app/src/main/java/dev/jdtech/jellyfin/utils/extensions.kt
@@ -1,6 +1,7 @@
package dev.jdtech.jellyfin.utils
import android.content.Context
+import android.content.res.Resources
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
@@ -35,4 +36,7 @@ fun Fragment.checkIfLoginRequired(error: String) {
inline fun Context.toast(@StringRes text: Int, duration: Int = Toast.LENGTH_SHORT) =
- Toast.makeText(this, text, duration).show()
\ No newline at end of file
+ Toast.makeText(this, text, duration).show()
+
+
+inline fun Resources.dip(px: Int) = (px * displayMetrics.density).toInt()
\ No newline at end of file
diff --git a/app/src/main/res/layout/exo_player_view.xml b/app/src/main/res/layout/exo_player_view.xml
new file mode 100644
index 00000000..3b16637e
--- /dev/null
+++ b/app/src/main/res/layout/exo_player_view.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file