Allow playing local playlists directly

This commit is contained in:
Stypox 2026-02-03 16:29:43 +01:00
parent ec75ddabda
commit 5e0b307c5e
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
2 changed files with 60 additions and 11 deletions

View File

@ -0,0 +1,49 @@
package org.schabi.newpipe.player.playqueue
import android.util.Log
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.schabi.newpipe.App
import org.schabi.newpipe.NewPipeDatabase
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry
import org.schabi.newpipe.local.playlist.LocalPlaylistManager
class LocalPlaylistPlayQueue(info: PlaylistMetadataEntry) : PlayQueue(0, listOf()) {
private val playlistId: Long = info.uid
private var fetchDisposable: Disposable? = null
override var isComplete: Boolean = false
private set
override fun fetch() {
if (isComplete) {
return
}
isComplete = true
fetchDisposable = LocalPlaylistManager(NewPipeDatabase.getInstance(App.instance))
.getPlaylistStreams(playlistId)
.firstOrError()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ streamEntries ->
append(streamEntries.map { PlayQueueItem(it.toStreamInfoItem()) })
},
{ e ->
Log.e(TAG, "Error fetching local playlist", e)
notifyChange()
}
)
}
override fun dispose() {
super.dispose()
fetchDisposable?.dispose()
fetchDisposable = null
}
companion object {
private val TAG: String = LocalPlaylistPlayQueue::class.java.getSimpleName()
}
}

View File

@ -25,6 +25,7 @@ import androidx.compose.material.icons.filled.Share
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.core.net.toUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.reactive.awaitFirst
import kotlinx.coroutines.rx3.await
import kotlinx.coroutines.rx3.awaitSingle
import kotlinx.coroutines.withContext
@ -47,6 +48,7 @@ import org.schabi.newpipe.local.history.HistoryRecordManager
import org.schabi.newpipe.local.playlist.LocalPlaylistManager
import org.schabi.newpipe.player.helper.PlayerHolder
import org.schabi.newpipe.player.playqueue.ChannelTabPlayQueue
import org.schabi.newpipe.player.playqueue.LocalPlaylistPlayQueue
import org.schabi.newpipe.player.playqueue.PlayQueue
import org.schabi.newpipe.player.playqueue.PlayQueueItem
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue
@ -93,10 +95,7 @@ data class LongPressAction(
UnsetPlaylistThumbnail(18, R.string.unset_playlist_thumbnail, Icons.Default.HideImage),
Unsubscribe(19, R.string.unsubscribe, Icons.Default.Delete),
ShowDetails(20, R.string.play_queue_stream_detail, Icons.Default.Info),
Remove(21, R.string.play_queue_remove, Icons.Default.Delete)
;
// TODO add actions that use the whole list the item belongs to (see wholeListQueue)
Remove(21, R.string.play_queue_remove, Icons.Default.Delete);
fun buildAction(
enabled: () -> Boolean = { true },
@ -338,13 +337,14 @@ data class LongPressAction(
onDelete: Runnable,
unsetPlaylistThumbnail: Runnable?
): List<LongPressAction> {
return listOf(
Type.Rename.buildAction { onRename.run() },
Type.Delete.buildAction { onDelete.run() },
Type.UnsetPlaylistThumbnail.buildAction(
enabled = { unsetPlaylistThumbnail != null }
) { unsetPlaylistThumbnail?.run() }
)
return buildPlayerActionList { LocalPlaylistPlayQueue(item) } +
listOf(
Type.Rename.buildAction { onRename.run() },
Type.Delete.buildAction { onDelete.run() },
Type.UnsetPlaylistThumbnail.buildAction(
enabled = { unsetPlaylistThumbnail != null }
) { unsetPlaylistThumbnail?.run() }
)
}
@JvmStatic