Skip to content

Commit 1afc2d1

Browse files
committed
[FR] #341
1 parent 40831d3 commit 1afc2d1

File tree

4 files changed

+67
-16
lines changed

4 files changed

+67
-16
lines changed

app/src/main/java/org/akanework/gramophone/ui/components/PlayerBottomSheet.kt

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,52 +21,40 @@ import android.animation.Animator
2121
import android.animation.AnimatorListenerAdapter
2222
import android.annotation.SuppressLint
2323
import android.content.Context
24+
import android.content.SharedPreferences
2425
import android.os.Build
2526
import android.os.Handler
2627
import android.os.Looper
2728
import android.util.AttributeSet
29+
import android.view.MotionEvent
2830
import androidx.media3.common.util.Log
2931
import android.view.View
3032
import android.view.WindowInsets
3133
import android.widget.FrameLayout
32-
import android.widget.ImageView
33-
import android.widget.TextView
3434
import androidx.activity.BackEventCompat
3535
import androidx.activity.OnBackPressedCallback
36-
import androidx.appcompat.content.res.AppCompatResources
3736
import androidx.core.graphics.Insets
3837
import androidx.core.view.HapticFeedbackConstantsCompat
3938
import androidx.core.view.ViewCompat
4039
import androidx.core.view.WindowInsetsCompat
4140
import androidx.core.view.doOnLayout
4241
import androidx.core.view.doOnNextLayout
4342
import androidx.core.view.isVisible
44-
import androidx.fragment.app.Fragment
45-
import androidx.fragment.app.findFragment
4643
import androidx.lifecycle.DefaultLifecycleObserver
4744
import androidx.lifecycle.LifecycleOwner
4845
import androidx.media3.common.MediaItem
4946
import androidx.media3.common.Player
5047
import androidx.media3.session.MediaController
5148
import 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
5849
import com.google.android.material.bottomsheet.BottomSheetBehavior
5950
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
6051
import com.google.android.material.button.MaterialButton
6152
import com.google.android.material.motion.MaterialBottomContainerBackHelper
6253
import org.akanework.gramophone.BuildConfig
6354
import org.akanework.gramophone.R
6455
import org.akanework.gramophone.logic.clone
65-
import org.akanework.gramophone.logic.fadInAnimation
6656
import org.akanework.gramophone.logic.fadOutAnimation
6757
import org.akanework.gramophone.logic.getBooleanStrict
68-
import org.akanework.gramophone.logic.playOrPause
69-
import org.akanework.gramophone.logic.startAnimation
7058
import org.akanework.gramophone.logic.ui.MyBottomSheetBehavior
7159
import 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

app/src/main/res/values-ru/strings.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,5 +466,7 @@
466466
<string name="sort_by_album_year">Год альбома</string>
467467
<string name="sort_by_album_artist_year"><![CDATA[Исполнитель альбома -> Год]]></string>
468468
<string name="forbidden_symbol_error">Недопустимый символ в названии</string>
469-
<string name="translators">Переводчики</string>
469+
<string name="translators">Переводчики</string>
470+
<string name="seek_swipe_preference_desc">Позволяет переключать треки, проводя пальцем по мини-плееру</string>
471+
<string name="seek_swipe_preference">Свайп для смены трека</string>
470472
</resources>

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,5 +472,6 @@
472472
<string name="sort_by_album_artist_year"><![CDATA[Album artist -> year]]></string>
473473
<string name="forbidden_symbol_error">Invalid character in the name</string>
474474
<string name="translators">Translators</string>
475-
475+
<string name="seek_swipe_preference_desc">Allow skipping to the next or previous track by swiping on the mini player</string>
476+
<string name="seek_swipe_preference">Swipe to change tracks</string>
476477
</resources>

app/src/main/res/xml/settings_behavior.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@
7171
android:widgetLayout="@layout/preference_switch_widget"
7272
app:iconSpaceReserved="false" />
7373

74+
<SwitchPreferenceCompat
75+
android:defaultValue="false"
76+
android:key="seek_swipe"
77+
android:layout="@layout/preference_switch"
78+
android:title="@string/seek_swipe_preference"
79+
android:summary="@string/seek_swipe_preference_desc"
80+
android:widgetLayout="@layout/preference_switch_widget"
81+
app:iconSpaceReserved="false" />
82+
7483
</PreferenceCategory>
7584

7685
</PreferenceScreen>

0 commit comments

Comments
 (0)