@@ -21,52 +21,40 @@ import android.animation.Animator
2121import android.animation.AnimatorListenerAdapter
2222import android.annotation.SuppressLint
2323import android.content.Context
24+ import android.content.SharedPreferences
2425import android.os.Build
2526import android.os.Handler
2627import android.os.Looper
2728import android.util.AttributeSet
29+ import android.view.MotionEvent
2830import androidx.media3.common.util.Log
2931import android.view.View
3032import android.view.WindowInsets
3133import android.widget.FrameLayout
32- import android.widget.ImageView
33- import android.widget.TextView
3434import androidx.activity.BackEventCompat
3535import androidx.activity.OnBackPressedCallback
36- import androidx.appcompat.content.res.AppCompatResources
3736import androidx.core.graphics.Insets
3837import androidx.core.view.HapticFeedbackConstantsCompat
3938import androidx.core.view.ViewCompat
4039import androidx.core.view.WindowInsetsCompat
4140import androidx.core.view.doOnLayout
4241import androidx.core.view.doOnNextLayout
4342import androidx.core.view.isVisible
44- import androidx.fragment.app.Fragment
45- import androidx.fragment.app.findFragment
4643import androidx.lifecycle.DefaultLifecycleObserver
4744import androidx.lifecycle.LifecycleOwner
4845import androidx.media3.common.MediaItem
4946import androidx.media3.common.Player
5047import androidx.media3.session.MediaController
5148import androidx.preference.PreferenceManager
52- import coil3.asDrawable
53- import coil3.imageLoader
54- import coil3.request.Disposable
55- import coil3.request.ImageRequest
56- import coil3.request.error
57- import coil3.size.Scale
5849import com.google.android.material.bottomsheet.BottomSheetBehavior
5950import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
6051import com.google.android.material.button.MaterialButton
6152import com.google.android.material.motion.MaterialBottomContainerBackHelper
6253import org.akanework.gramophone.BuildConfig
6354import org.akanework.gramophone.R
6455import org.akanework.gramophone.logic.clone
65- import org.akanework.gramophone.logic.fadInAnimation
6656import org.akanework.gramophone.logic.fadOutAnimation
6757import org.akanework.gramophone.logic.getBooleanStrict
68- import org.akanework.gramophone.logic.playOrPause
69- import org.akanework.gramophone.logic.startAnimation
7058import org.akanework.gramophone.logic.ui.MyBottomSheetBehavior
7159import org.akanework.gramophone.ui.MainActivity
7260
@@ -99,6 +87,15 @@ class PlayerBottomSheet private constructor(
9987 get() = activity.getPlayer()
10088 private var lastActuallyVisible: Boolean? = null
10189 private var lastMeasuredHeight: Int? = null
90+ private var x0 = 0f
91+ private var seekSwipeEnabled = false
92+ private val prefsListener =
93+ SharedPreferences .OnSharedPreferenceChangeListener { _, key ->
94+ if (key == " seek_swipe" ) {
95+ seekSwipeEnabled = prefs.getBooleanStrict(" seek_swipe" , false )
96+ findViewById<MaterialButton >(R .id.preview_next).visibility = if (seekSwipeEnabled) View .GONE else View .VISIBLE ;
97+ }
98+ }
10299 var visible = false
103100 set(value) {
104101 if (field != value) {
@@ -125,12 +122,36 @@ class PlayerBottomSheet private constructor(
125122 previewPlayer = findViewById(R .id.preview_player)
126123 fullPlayer = findViewById(R .id.full_player)
127124
125+ seekSwipeEnabled = prefs.getBooleanStrict(" seek_swipe" , false )
126+ findViewById<MaterialButton >(R .id.preview_next).visibility = if (seekSwipeEnabled) View .GONE else View .VISIBLE ;
127+
128128 setOnClickListener {
129129 if (standardBottomSheetBehavior!! .state == BottomSheetBehavior .STATE_COLLAPSED ) {
130130 standardBottomSheetBehavior!! .state = BottomSheetBehavior .STATE_EXPANDED
131131 }
132132 }
133133
134+ setOnTouchListener { v, event ->
135+ when (event.action) {
136+ MotionEvent .ACTION_DOWN -> {
137+ x0 = event.x
138+ false
139+ }
140+ MotionEvent .ACTION_UP -> {
141+ if (! seekSwipeEnabled) return @setOnTouchListener false
142+
143+ val dx = event.x - x0
144+ when {
145+ dx > 100 -> onSwipeRight()
146+ dx < - 100 -> onSwipeLeft()
147+ else -> v.performClick()
148+ }
149+ true
150+ }
151+ else -> false
152+ }
153+ }
154+
134155 activity.controllerViewModel.addControllerCallback(activity.lifecycle) { _, _ ->
135156 instance?.addListener(this @PlayerBottomSheet)
136157 onMediaItemTransition(
@@ -147,6 +168,20 @@ class PlayerBottomSheet private constructor(
147168 }
148169 }
149170
171+ private fun onSwipeLeft () {
172+ if (instance?.hasNextMediaItem() == true ){
173+ ViewCompat .performHapticFeedback(previewPlayer, HapticFeedbackConstantsCompat .CONTEXT_CLICK )
174+ instance?.seekToNext()
175+ }
176+ }
177+
178+ private fun onSwipeRight () {
179+ if (instance?.hasPreviousMediaItem() == true ) {
180+ ViewCompat .performHapticFeedback(previewPlayer, HapticFeedbackConstantsCompat .CONTEXT_CLICK )
181+ instance?.seekToPrevious()
182+ }
183+ }
184+
150185 private val bottomSheetCallback = object : BottomSheetCallback () {
151186 override fun onStateChanged (
152187 bottomSheet : View ,
@@ -159,6 +194,7 @@ class PlayerBottomSheet private constructor(
159194 previewPlayer.alpha = 1f
160195 fullPlayer.alpha = 0f
161196 bottomSheetBackCallback!! .isEnabled = false
197+ seekSwipeEnabled = prefs.getBooleanStrict(" seek_swipe" , false )
162198 }
163199
164200 BottomSheetBehavior .STATE_DRAGGING , BottomSheetBehavior .STATE_SETTLING -> {
@@ -172,6 +208,7 @@ class PlayerBottomSheet private constructor(
172208 previewPlayer.alpha = 0f
173209 fullPlayer.alpha = 1f
174210 bottomSheetBackCallback!! .isEnabled = true
211+ seekSwipeEnabled = false
175212 }
176213
177214 BottomSheetBehavior .STATE_HIDDEN -> {
@@ -203,6 +240,7 @@ class PlayerBottomSheet private constructor(
203240 override fun onAttachedToWindow () {
204241 super .onAttachedToWindow()
205242 doOnLayout { // wait for CoordinatorLayout to finish to allow getting behaviour
243+ prefs.registerOnSharedPreferenceChangeListener(prefsListener)
206244 standardBottomSheetBehavior = MyBottomSheetBehavior .from(this )
207245 fullPlayer.minimize = {
208246 standardBottomSheetBehavior!! .state = BottomSheetBehavior .STATE_COLLAPSED
@@ -282,6 +320,7 @@ class PlayerBottomSheet private constructor(
282320
283321 override fun onDetachedFromWindow () {
284322 super .onDetachedFromWindow()
323+ prefs.unregisterOnSharedPreferenceChangeListener(prefsListener)
285324 lastActuallyVisible = null
286325 lastMeasuredHeight = null
287326 fullPlayer.minimize = null
0 commit comments