Twelve: Add play all button on albums and playlists
Change-Id: Iccfbed51f937ed24d166542a1433a88d412a10e9
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt
index f242671..b6880a9 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt
@@ -27,6 +27,7 @@
import coil3.load
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.card.MaterialCardView
+import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.collectLatest
@@ -35,6 +36,7 @@
import org.lineageos.twelve.ext.getParcelable
import org.lineageos.twelve.ext.getViewProperty
import org.lineageos.twelve.ext.setProgressCompat
+import org.lineageos.twelve.ext.updateMargin
import org.lineageos.twelve.ext.updatePadding
import org.lineageos.twelve.models.RequestStatus
import org.lineageos.twelve.ui.recyclerview.SimpleListAdapter
@@ -60,6 +62,7 @@
private val infoNestedScrollView by getViewProperty<NestedScrollView?>(R.id.infoNestedScrollView)
private val linearProgressIndicator by getViewProperty<LinearProgressIndicator>(R.id.linearProgressIndicator)
private val noElementsNestedScrollView by getViewProperty<NestedScrollView>(R.id.noElementsNestedScrollView)
+ private val playAllFloatingActionButton by getViewProperty<FloatingActionButton>(R.id.playAllFloatingActionButton)
private val recyclerView by getViewProperty<RecyclerView>(R.id.recyclerView)
private val thumbnailImageView by getViewProperty<ImageView>(R.id.thumbnailImageView)
private val toolbar by getViewProperty<MaterialToolbar>(R.id.toolbar)
@@ -81,11 +84,7 @@
view.setOnClickListener {
when (val item = item) {
is AlbumViewModel.AlbumContent.AudioItem -> {
- val audios = currentList.mapNotNull {
- (it as? AlbumViewModel.AlbumContent.AudioItem)?.audio
- }
-
- viewModel.playAudio(audios, audios.indexOf(item.audio))
+ viewModel.playAlbum(item.audio)
findNavController().navigate(
R.id.action_albumFragment_to_fragment_now_playing
@@ -216,10 +215,27 @@
windowInsets
}
+ ViewCompat.setOnApplyWindowInsetsListener(playAllFloatingActionButton) { v, windowInsets ->
+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+
+ v.updateMargin(
+ insets,
+ bottom = true,
+ )
+
+ windowInsets
+ }
+
toolbar.setupWithNavController(findNavController())
recyclerView.adapter = adapter
+ playAllFloatingActionButton.setOnClickListener {
+ viewModel.playAlbum()
+
+ findNavController().navigate(R.id.action_albumFragment_to_fragment_now_playing)
+ }
+
viewModel.loadAlbum(albumUri)
viewLifecycleOwner.lifecycleScope.launch {
@@ -318,6 +334,10 @@
val isEmpty = it.isEmpty()
recyclerView.isVisible = !isEmpty
noElementsNestedScrollView.isVisible = isEmpty
+ when (isEmpty) {
+ true -> playAllFloatingActionButton.hide()
+ false -> playAllFloatingActionButton.show()
+ }
}
}
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt
index 5c9d8f4..28ff7db 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt
@@ -25,6 +25,7 @@
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
@@ -32,6 +33,7 @@
import org.lineageos.twelve.ext.getParcelable
import org.lineageos.twelve.ext.getViewProperty
import org.lineageos.twelve.ext.setProgressCompat
+import org.lineageos.twelve.ext.updateMargin
import org.lineageos.twelve.ext.updatePadding
import org.lineageos.twelve.models.Audio
import org.lineageos.twelve.models.RequestStatus
@@ -55,6 +57,7 @@
private val infoNestedScrollView by getViewProperty<NestedScrollView?>(R.id.infoNestedScrollView)
private val linearProgressIndicator by getViewProperty<LinearProgressIndicator>(R.id.linearProgressIndicator)
private val noElementsNestedScrollView by getViewProperty<NestedScrollView>(R.id.noElementsNestedScrollView)
+ private val playAllFloatingActionButton by getViewProperty<FloatingActionButton>(R.id.playAllFloatingActionButton)
private val playlistNameTextView by getViewProperty<TextView>(R.id.playlistNameTextView)
private val recyclerView by getViewProperty<RecyclerView>(R.id.recyclerView)
private val toolbar by getViewProperty<MaterialToolbar>(R.id.toolbar)
@@ -70,7 +73,7 @@
view.setLeadingIconImage(R.drawable.ic_music_note)
view.setOnClickListener {
item?.let {
- viewModel.playAudio(currentList, bindingAdapterPosition)
+ viewModel.playPlaylist(bindingAdapterPosition)
findNavController().navigate(
R.id.action_playlistFragment_to_fragment_now_playing
@@ -162,6 +165,17 @@
windowInsets
}
+ ViewCompat.setOnApplyWindowInsetsListener(playAllFloatingActionButton) { v, windowInsets ->
+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+
+ v.updateMargin(
+ insets,
+ bottom = true,
+ )
+
+ windowInsets
+ }
+
toolbar.setupWithNavController(findNavController())
toolbar.inflateMenu(R.menu.fragment_podcast_toolbar)
toolbar.setOnMenuItemClickListener {
@@ -182,6 +196,12 @@
recyclerView.adapter = adapter
+ playAllFloatingActionButton.setOnClickListener {
+ viewModel.playPlaylist()
+
+ findNavController().navigate(R.id.action_playlistFragment_to_fragment_now_playing)
+ }
+
viewModel.loadPlaylist(playlistUri)
viewLifecycleOwner.lifecycleScope.launch {
@@ -239,6 +259,10 @@
val isEmpty = audios.isEmpty()
recyclerView.isVisible = !isEmpty
noElementsNestedScrollView.isVisible = isEmpty
+ when (isEmpty) {
+ true -> playAllFloatingActionButton.hide()
+ false -> playAllFloatingActionButton.show()
+ }
}
is RequestStatus.Error -> {
@@ -251,6 +275,7 @@
recyclerView.isVisible = false
noElementsNestedScrollView.isVisible = true
+ playAllFloatingActionButton.isVisible = false
if (it.type == RequestStatus.Error.Type.NOT_FOUND) {
// Get out of here
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt
index 18010e6..9faabb0 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt
@@ -139,4 +139,12 @@
fun loadAlbum(albumUri: Uri) {
this.albumUri.value = albumUri
}
+
+ fun playAlbum(startFrom: Audio? = null) {
+ albumContent.value.mapNotNull {
+ (it as? AlbumContent.AudioItem)?.audio
+ }.takeUnless { it.isEmpty() }?.let { audios ->
+ playAudio(audios, startFrom?.let { audios.indexOf(it) } ?: 0)
+ }
+ }
}
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt
index 31e8563..3a4269e 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt
@@ -50,4 +50,12 @@
mediaRepository.deletePlaylist(playlistUri)
}
}
+
+ fun playPlaylist(position: Int = 0) {
+ (playlist.value as? RequestStatus.Success)?.data?.second?.takeUnless {
+ it.isEmpty()
+ }?.mapNotNull { it }?.let {
+ playAudio(it, position)
+ }
+ }
}
diff --git a/app/src/main/res/layout-land/fragment_album.xml b/app/src/main/res/layout-land/fragment_album.xml
index ce15464..9bfa55a 100644
--- a/app/src/main/res/layout-land/fragment_album.xml
+++ b/app/src/main/res/layout-land/fragment_album.xml
@@ -95,4 +95,23 @@
android:indeterminate="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:paddingBottom="16dp"
+ app:layout_anchor="@+id/recyclerView"
+ app:layout_anchorGravity="bottom|end"
+ app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior">
+
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/playAllFloatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ app:srcCompat="@drawable/ic_play_arrow"
+ tools:visibility="visible" />
+
+ </FrameLayout>
+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout-land/fragment_playlist.xml b/app/src/main/res/layout-land/fragment_playlist.xml
index 82291f6..fb3ec0e 100644
--- a/app/src/main/res/layout-land/fragment_playlist.xml
+++ b/app/src/main/res/layout-land/fragment_playlist.xml
@@ -95,4 +95,23 @@
android:indeterminate="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:paddingBottom="16dp"
+ app:layout_anchor="@+id/recyclerView"
+ app:layout_anchorGravity="bottom|end"
+ app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior">
+
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/playAllFloatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ app:srcCompat="@drawable/ic_play_arrow"
+ tools:visibility="visible" />
+
+ </FrameLayout>
+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/fragment_album.xml b/app/src/main/res/layout/fragment_album.xml
index 540f4f9..2aa8c9a 100644
--- a/app/src/main/res/layout/fragment_album.xml
+++ b/app/src/main/res/layout/fragment_album.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
SPDX-FileCopyrightText: 2024 The LineageOS Project
SPDX-License-Identifier: Apache-2.0
-->
@@ -96,4 +95,23 @@
android:indeterminate="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:paddingBottom="16dp"
+ app:layout_anchor="@+id/recyclerView"
+ app:layout_anchorGravity="bottom|end"
+ app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior">
+
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/playAllFloatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ app:srcCompat="@drawable/ic_play_arrow"
+ tools:visibility="visible" />
+
+ </FrameLayout>
+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/fragment_playlist.xml b/app/src/main/res/layout/fragment_playlist.xml
index b222084..d2a124b 100644
--- a/app/src/main/res/layout/fragment_playlist.xml
+++ b/app/src/main/res/layout/fragment_playlist.xml
@@ -97,4 +97,23 @@
android:indeterminate="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:paddingBottom="16dp"
+ app:layout_anchor="@+id/recyclerView"
+ app:layout_anchorGravity="bottom|end"
+ app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior">
+
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/playAllFloatingActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ app:srcCompat="@drawable/ic_play_arrow"
+ tools:visibility="visible" />
+
+ </FrameLayout>
+
</androidx.coordinatorlayout.widget.CoordinatorLayout>