diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt
index 2007e0828..23f5d46c9 100644
--- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt
+++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt
@@ -34,7 +34,6 @@ import org.oxycblt.auxio.databinding.FragmentMainBinding
import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.music.MusicViewModel
-import org.oxycblt.auxio.playback.PlaybackLayout
import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.util.logD
@@ -43,7 +42,7 @@ import org.oxycblt.auxio.util.logD
* the more high-level navigation features.
* @author OxygenCobalt
*/
-class MainFragment : Fragment(), PlaybackLayout.ActionCallback {
+class MainFragment : Fragment() {
private val playbackModel: PlaybackViewModel by activityViewModels()
private val detailModel: DetailViewModel by activityViewModels()
private val musicModel: MusicViewModel by activityViewModels()
@@ -78,23 +77,7 @@ class MainFragment : Fragment(), PlaybackLayout.ActionCallback {
// We have to control the bar view from here since using a Fragment in PlaybackLayout
// would result in annoying UI issues.
- binding.playbackLayout.setActionCallback(this)
-
- binding.playbackLayout.setSong(playbackModel.song.value)
- binding.playbackLayout.setPlaying(playbackModel.isPlaying.value!!)
- binding.playbackLayout.setPosition(playbackModel.position.value!!)
-
- playbackModel.song.observe(viewLifecycleOwner) { song ->
- binding.playbackLayout.setSong(song)
- }
-
- playbackModel.isPlaying.observe(viewLifecycleOwner) { isPlaying ->
- binding.playbackLayout.setPlaying(isPlaying)
- }
-
- playbackModel.position.observe(viewLifecycleOwner) { pos ->
- binding.playbackLayout.setPosition(pos)
- }
+ binding.playbackLayout.setup(playbackModel, detailModel, viewLifecycleOwner)
// Initialize music loading. Do it here so that it shows on every fragment that this
// one contains.
@@ -156,29 +139,6 @@ class MainFragment : Fragment(), PlaybackLayout.ActionCallback {
callback?.isEnabled = false
}
- override fun onDestroyView() {
- super.onDestroyView()
-
- // This callback has access to the binding, so make sure we clear it when we're done.
- callback = null
- }
-
- override fun onNavToItem() {
- detailModel.navToItem(playbackModel.song.value ?: return)
- }
-
- override fun onPrev() {
- playbackModel.skipPrev()
- }
-
- override fun onPlayPauseClick() {
- playbackModel.invertPlayingStatus()
- }
-
- override fun onNext() {
- playbackModel.skipNext()
- }
-
/**
* A back press callback that handles how to respond to backwards navigation in the detail
* fragments and the playback panel.
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt
index a3e041421..350cb61ef 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt
@@ -23,9 +23,11 @@ import android.util.AttributeSet
import android.view.WindowInsets
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.updatePadding
+import androidx.lifecycle.LifecycleOwner
import com.google.android.material.color.MaterialColors
import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.ViewPlaybackBarBinding
+import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.resolveAttr
@@ -41,16 +43,10 @@ class PlaybackBarView @JvmOverloads constructor(
defStyleAttr: Int = -1
) : ConstraintLayout(context, attrs, defStyleAttr) {
private val binding = ViewPlaybackBarBinding.inflate(context.inflater, this, true)
- private var mCallback: PlaybackLayout.ActionCallback? = null
init {
id = R.id.playback_bar
- setOnLongClickListener {
- mCallback?.onNavToItem()
- true
- }
-
// Deliberately override the progress bar color [in a Lollipop-friendly way] so that
// we use colorSecondary instead of colorSurfaceVariant. This is for two reasons:
// 1. colorSurfaceVariant is used with the assumption that the view that is using it
@@ -66,28 +62,45 @@ class PlaybackBarView @JvmOverloads constructor(
return insets
}
+ fun setup(
+ playbackModel: PlaybackViewModel,
+ detailModel: DetailViewModel,
+ viewLifecycleOwner: LifecycleOwner
+ ) {
+ setOnLongClickListener {
+ playbackModel.song.value?.let { song ->
+ detailModel.navToItem(song)
+ }
+ true
+ }
+
+ binding.playbackSkipPrev?.setOnClickListener {
+ playbackModel.skipPrev()
+ }
+
+ binding.playbackPlayPause.setOnClickListener {
+ playbackModel.invertPlayingStatus()
+ }
+
+ binding.playbackSkipNext?.setOnClickListener {
+ playbackModel.skipNext()
+ }
+
+ binding.playbackPlayPause.isActivated = playbackModel.isPlaying.value!!
+
+ playbackModel.isPlaying.observe(viewLifecycleOwner) { isPlaying ->
+ binding.playbackPlayPause.isActivated = isPlaying
+ }
+
+ binding.playbackProgressBar.progress = playbackModel.position.value!!.toInt()
+
+ playbackModel.position.observe(viewLifecycleOwner) { position ->
+ binding.playbackProgressBar.progress = position.toInt()
+ }
+ }
+
fun setSong(song: Song) {
binding.song = song
binding.executePendingBindings()
}
-
- fun setPlaying(isPlaying: Boolean) {
- binding.playbackPlayPause.isActivated = isPlaying
- }
-
- fun setPosition(position: Long) {
- binding.playbackProgressBar.progress = position.toInt()
- }
-
- fun setCallback(callback: PlaybackLayout.ActionCallback) {
- mCallback = callback
- binding.callback = callback
- binding.executePendingBindings()
- }
-
- fun clearCallback() {
- mCallback = null
- binding.callback = null
- binding.executePendingBindings()
- }
}
diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt
index 081f5c965..5afb8eca1 100644
--- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt
+++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt
@@ -20,11 +20,12 @@ import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isInvisible
import androidx.customview.widget.ViewDragHelper
+import androidx.lifecycle.LifecycleOwner
import com.google.android.material.shape.MaterialShapeDrawable
import org.oxycblt.auxio.BuildConfig
import org.oxycblt.auxio.R
+import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.Song
-import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.resolveAttr
import org.oxycblt.auxio.util.resolveDrawable
import org.oxycblt.auxio.util.systemBarsCompat
@@ -56,13 +57,6 @@ class PlaybackLayout @JvmOverloads constructor(
EXPANDED, COLLAPSED, HIDDEN, DRAGGING
}
- interface ActionCallback {
- fun onNavToItem()
- fun onPrev()
- fun onPlayPauseClick()
- fun onNext()
- }
-
private lateinit var contentView: View
private val playbackContainerView: FrameLayout
private val playbackBarView: PlaybackBarView
@@ -182,7 +176,21 @@ class PlaybackLayout @JvmOverloads constructor(
* Update the song that this layout is showing. This will be reflected in the compact view
* at the bottom of the screen.
*/
- fun setSong(song: Song?) {
+ fun setup(
+ playbackModel: PlaybackViewModel,
+ detailModel: DetailViewModel,
+ viewLifecycleOwner: LifecycleOwner
+ ) {
+ setSong(playbackModel.song.value)
+
+ playbackModel.song.observe(viewLifecycleOwner) { song ->
+ setSong(song)
+ }
+
+ playbackBarView.setup(playbackModel, detailModel, viewLifecycleOwner)
+ }
+
+ private fun setSong(song: Song?) {
if (song != null) {
playbackBarView.setSong(song)
@@ -195,35 +203,11 @@ class PlaybackLayout @JvmOverloads constructor(
}
}
- /**
- * Update the playing status on this layout. This will be reflected in the compact view
- * at the bottom of the screen.
- */
- fun setPlaying(isPlaying: Boolean) {
- playbackBarView.setPlaying(isPlaying)
- }
-
- /**
- * Update the playback position on this layout. This will be reflected in the compact view
- * at the bottom of the screen.
- */
- fun setPosition(position: Long) {
- playbackBarView.setPosition(position)
- }
-
- /**
- * Add a callback for actions from the compact playback view in this layout.
- */
- fun setActionCallback(callback: ActionCallback) {
- playbackBarView.setCallback(callback)
- }
-
/**
* Collapse the panel if it is currently expanded.
* @return If the panel was collapsed or not.
*/
fun collapse(): Boolean {
- logD(panelState)
if (panelState == PanelState.EXPANDED) {
applyState(PanelState.COLLAPSED)
return true
@@ -416,11 +400,6 @@ class PlaybackLayout @JvmOverloads constructor(
}
}
- override fun onDetachedFromWindow() {
- super.onDetachedFromWindow()
- playbackBarView.clearCallback()
- }
-
override fun onSaveInstanceState(): Parcelable = Bundle().apply {
putParcelable("superState", super.onSaveInstanceState())
putSerializable(
diff --git a/app/src/main/res/layout-w600dp/view_playback_bar.xml b/app/src/main/res/layout-w600dp/view_playback_bar.xml
index c6f0dd9d9..c22ad6151 100644
--- a/app/src/main/res/layout-w600dp/view_playback_bar.xml
+++ b/app/src/main/res/layout-w600dp/view_playback_bar.xml
@@ -10,10 +10,6 @@
name="song"
type="org.oxycblt.auxio.music.Song" />
-
-
-
-
diff --git a/info/ARCHITECTURE.md b/info/ARCHITECTURE.md
index e5df7f348..44fb18174 100644
--- a/info/ARCHITECTURE.md
+++ b/info/ARCHITECTURE.md
@@ -275,8 +275,7 @@ This module not only contains the playback system described above, but also mult
- `system` contains the system-facing playback system
The most important part of this module is `PlaybackLayout`, which is a custom `ViewGroup` that implements the playback bar and it's ability to
-slide up into the full playback view. `MainFragment` controls this `ViewGroup`, more specifically the bar view, as it can't be an independent
-fragment due to a couple of annoying reasons.
+slide up into the full playback view. `MainFragment` controls this `ViewGroup`.
#### `.search`