feat: support for shuffling downloaded audio content

This commit is contained in:
Bnyro 2024-10-15 12:11:06 +02:00
parent 84eea3df56
commit c16764fbfb
5 changed files with 65 additions and 14 deletions

View File

@ -50,4 +50,5 @@ object IntentData {
const val videoInfo = "videoInfo"
const val offlinePlayer = "offlinePlayer"
const val downloadTab = "downloadTab"
const val shuffle = "shuffle"
}

View File

@ -77,11 +77,12 @@ object BackgroundHelper {
* @param context the current context
* @param videoId the videoId of the video or null if all available downloads should be shuffled
*/
fun playOnBackgroundOffline(context: Context, videoId: String?, downloadTab: DownloadTab) {
fun playOnBackgroundOffline(context: Context, videoId: String?, downloadTab: DownloadTab, shuffle: Boolean = false) {
stopBackgroundPlay(context)
val playerIntent = Intent(context, OfflinePlayerService::class.java)
.putExtra(IntentData.videoId, videoId)
.putExtra(IntentData.shuffle, shuffle)
.putExtra(IntentData.downloadTab, downloadTab)
ContextCompat.startForegroundService(context, playerIntent)

View File

@ -21,6 +21,7 @@ import com.github.libretube.ui.fragments.DownloadTab
import com.github.libretube.util.PlayingQueue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import kotlin.io.path.exists
@ -31,10 +32,20 @@ import kotlin.io.path.exists
class OfflinePlayerService : AbstractPlayerService() {
private var downloadWithItems: DownloadWithItems? = null
private lateinit var downloadTab: DownloadTab
private var shuffle: Boolean = false
override suspend fun onServiceCreated(intent: Intent) {
videoId = intent.getStringExtra(IntentData.videoId) ?: return
downloadTab = intent.serializableExtra(IntentData.downloadTab)!!
shuffle = intent.getBooleanExtra(IntentData.shuffle, false)
videoId = if (shuffle) {
runBlocking(Dispatchers.IO) {
Database.downloadDao().getAll().filterByTab(downloadTab)
.randomOrNull()?.download?.videoId
}
} else {
intent.getStringExtra(IntentData.videoId)
} ?: return
PlayingQueue.clear()
@ -92,7 +103,11 @@ class OfflinePlayerService : AbstractPlayerService() {
private suspend fun fillQueue() {
val downloads = withContext(Dispatchers.IO) {
Database.downloadDao().getAll()
}.filterByTab(downloadTab)
}
.filterByTab(downloadTab)
.toMutableList()
if (shuffle) downloads.shuffle()
PlayingQueue.insertRelatedStreams(downloads.map { it.download.toStreamItem() })
}

View File

@ -31,7 +31,9 @@ import com.github.libretube.db.obj.filterByTab
import com.github.libretube.extensions.ceilHalf
import com.github.libretube.extensions.formatAsFileSize
import com.github.libretube.extensions.serializable
import com.github.libretube.helpers.BackgroundHelper
import com.github.libretube.helpers.DownloadHelper
import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.obj.DownloadStatus
import com.github.libretube.receivers.DownloadReceiver
@ -253,6 +255,17 @@ class DownloadsFragmentPage : DynamicLayoutManagerFragment() {
binding.deleteAll.setOnClickListener {
showDeleteAllDialog(binding.root.context, adapter)
}
binding.shuffleAll.setOnClickListener {
BackgroundHelper.playOnBackgroundOffline(
requireContext(),
null,
downloadTab,
shuffle = true
)
NavigationHelper.startAudioPlayer(requireContext(), offlinePlayer = true)
}
}
private fun toggleVisibilities() {
@ -262,6 +275,7 @@ class DownloadsFragmentPage : DynamicLayoutManagerFragment() {
binding.downloadsEmpty.isVisible = isEmpty
binding.downloadsContainer.isGone = isEmpty
binding.deleteAll.isGone = isEmpty
binding.shuffleAll.isGone = isEmpty || downloadTab != DownloadTab.AUDIO
}
private fun sortDownloadList(sortType: Int, previousSortType: Int? = null) {

View File

@ -60,20 +60,40 @@
android:textStyle="bold" />
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/delete_all"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="18dp"
android:layout_marginBottom="18dp"
android:contentDescription="@string/delete_all"
android:src="@drawable/ic_delete"
android:tooltipText="@string/delete"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:targetApi="o"
tools:visibility="visible" />
android:layout_marginEnd="18dp"
android:layout_marginBottom="18dp"
android:orientation="vertical">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/delete_all"
style="?attr/floatingActionButtonSmallSecondaryStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:contentDescription="@string/delete_all"
android:src="@drawable/ic_delete"
android:tooltipText="@string/delete"
android:visibility="gone"
tools:targetApi="o"
tools:visibility="visible" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/shuffle_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/shuffle"
android:src="@drawable/ic_shuffle"
android:layout_marginTop="8dp"
android:tooltipText="@string/shuffle"
android:visibility="gone"
tools:targetApi="o"
tools:visibility="visible" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>