mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-15 06:40:30 +05:30
Add functionality for exporting and importing playlists
This commit is contained in:
parent
c1793691ed
commit
5616934817
@ -6,17 +6,21 @@ import com.github.libretube.R
|
||||
import com.github.libretube.api.obj.Playlist
|
||||
import com.github.libretube.api.obj.PlaylistId
|
||||
import com.github.libretube.api.obj.Playlists
|
||||
import com.github.libretube.constants.YOUTUBE_FRONTEND_URL
|
||||
import com.github.libretube.db.DatabaseHolder
|
||||
import com.github.libretube.db.obj.LocalPlaylist
|
||||
import com.github.libretube.enums.PlaylistType
|
||||
import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.extensions.awaitQuery
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.extensions.toLocalPlaylistItem
|
||||
import com.github.libretube.extensions.toStreamItem
|
||||
import com.github.libretube.extensions.toastFromMainThread
|
||||
import com.github.libretube.obj.ImportPlaylist
|
||||
import com.github.libretube.util.PreferenceHelper
|
||||
import com.github.libretube.util.ProxyHelper
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
@ -47,9 +51,9 @@ object PlaylistsHelper {
|
||||
return playlists
|
||||
}
|
||||
|
||||
suspend fun getPlaylist(playlistType: PlaylistType, playlistId: String): Playlist {
|
||||
suspend fun getPlaylist(playlistId: String): Playlist {
|
||||
// load locally stored playlists with the auth api
|
||||
return when (playlistType) {
|
||||
return when (getPlaylistType()) {
|
||||
PlaylistType.PRIVATE -> RetrofitInstance.authApi.getPlaylist(playlistId)
|
||||
PlaylistType.PUBLIC -> RetrofitInstance.api.getPlaylist(playlistId)
|
||||
PlaylistType.LOCAL -> {
|
||||
@ -66,7 +70,10 @@ object PlaylistsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun createPlaylist(playlistName: String, appContext: Context, onSuccess: () -> Unit) {
|
||||
suspend fun createPlaylist(
|
||||
playlistName: String,
|
||||
appContext: Context
|
||||
): String? {
|
||||
if (!loggedIn()) {
|
||||
awaitQuery {
|
||||
DatabaseHolder.Database.localPlaylistsDao().createPlaylist(
|
||||
@ -76,8 +83,9 @@ object PlaylistsHelper {
|
||||
)
|
||||
)
|
||||
}
|
||||
onSuccess.invoke()
|
||||
return
|
||||
return awaitQuery {
|
||||
DatabaseHolder.Database.localPlaylistsDao().getAll()
|
||||
}.last().playlist.id.toString()
|
||||
}
|
||||
val response = try {
|
||||
RetrofitInstance.authApi.createPlaylist(
|
||||
@ -86,18 +94,17 @@ object PlaylistsHelper {
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
appContext.toastFromMainThread(R.string.unknown_error)
|
||||
return
|
||||
return null
|
||||
} catch (e: HttpException) {
|
||||
Log.e(TAG(), e.toString())
|
||||
appContext.toastFromMainThread(R.string.server_error)
|
||||
return
|
||||
return null
|
||||
}
|
||||
if (response.playlistId != null) {
|
||||
appContext.toastFromMainThread(R.string.playlistCreated)
|
||||
onSuccess.invoke()
|
||||
} else {
|
||||
appContext.toastFromMainThread(R.string.unknown_error)
|
||||
return response.playlistId!!
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun addToPlaylist(playlistId: String, videoId: String): Boolean {
|
||||
@ -176,19 +183,51 @@ object PlaylistsHelper {
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun importPlaylists(playlist: List<ImportPlaylist>) {
|
||||
|
||||
suspend fun importPlaylists(appContext: Context, playlists: List<ImportPlaylist>) {
|
||||
for (playlist in playlists) {
|
||||
val playlistId = createPlaylist(playlist.name!!, appContext) ?: continue
|
||||
runBlocking {
|
||||
val tasks = playlist.videos.map { videoId ->
|
||||
async { addToPlaylist(playlistId, videoId.substringAfter("=")) }
|
||||
}
|
||||
tasks.forEach {
|
||||
it.await()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun exportPlaylists(): List<ImportPlaylist> {
|
||||
|
||||
val playlists = getPlaylists()
|
||||
val importLists = mutableListOf<ImportPlaylist>()
|
||||
runBlocking {
|
||||
val tasks = playlists.map {
|
||||
async {
|
||||
val list = getPlaylist(it.id!!)
|
||||
importLists.add(
|
||||
ImportPlaylist(
|
||||
name = list.name,
|
||||
type = "playlist",
|
||||
visibility = "private",
|
||||
videos = list.relatedStreams.orEmpty().map {
|
||||
YOUTUBE_FRONTEND_URL + it.url!!.toID()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
tasks.forEach {
|
||||
it.await()
|
||||
}
|
||||
}
|
||||
return importLists
|
||||
}
|
||||
|
||||
fun getPrivateType(): PlaylistType {
|
||||
fun getPlaylistType(): PlaylistType {
|
||||
return if (loggedIn()) PlaylistType.PRIVATE else PlaylistType.LOCAL
|
||||
}
|
||||
|
||||
fun getPrivateType(playlistId: String): PlaylistType {
|
||||
fun getPlaylistType(playlistId: String): PlaylistType {
|
||||
if (playlistId.all { it.isDigit() }) return PlaylistType.LOCAL
|
||||
if (playlistId.matches(pipedPlaylistRegex)) return PlaylistType.PRIVATE
|
||||
return PlaylistType.PUBLIC
|
||||
|
@ -108,7 +108,7 @@ class HomeFragment : BaseFragment() {
|
||||
runOnUiThread {
|
||||
makeVisible(binding.playlistsRV, binding.playlistsTV)
|
||||
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
|
||||
binding.playlistsRV.adapter = PlaylistsAdapter(playlists.toMutableList(), PlaylistsHelper.getPrivateType())
|
||||
binding.playlistsRV.adapter = PlaylistsAdapter(playlists.toMutableList(), PlaylistsHelper.getPlaylistType())
|
||||
binding.playlistsRV.adapter?.registerAdapterDataObserver(object :
|
||||
RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
|
@ -123,7 +123,7 @@ class LibraryFragment : BaseFragment() {
|
||||
|
||||
val playlistsAdapter = PlaylistsAdapter(
|
||||
playlists.toMutableList(),
|
||||
PlaylistsHelper.getPrivateType()
|
||||
PlaylistsHelper.getPlaylistType()
|
||||
)
|
||||
|
||||
// listen for playlists to become deleted
|
||||
|
@ -99,7 +99,7 @@ class PlaylistFragment : BaseFragment() {
|
||||
binding.playlistScrollview.visibility = View.GONE
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val response = try {
|
||||
PlaylistsHelper.getPlaylist(playlistType, playlistId!!)
|
||||
PlaylistsHelper.getPlaylist(playlistId!!)
|
||||
} catch (e: IOException) {
|
||||
println(e)
|
||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||
|
@ -110,8 +110,8 @@ object PlayingQueue {
|
||||
fun insertPlaylist(playlistId: String, newCurrentStream: StreamItem) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val playlistType = PlaylistsHelper.getPrivateType(playlistId)
|
||||
val playlist = PlaylistsHelper.getPlaylist(playlistType, playlistId)
|
||||
val playlistType = PlaylistsHelper.getPlaylistType(playlistId)
|
||||
val playlist = PlaylistsHelper.getPlaylist(playlistId)
|
||||
add(
|
||||
*playlist.relatedStreams
|
||||
.orEmpty()
|
||||
|
@ -82,12 +82,9 @@ class NotificationWorker(appContext: Context, parameters: WorkerParameters) :
|
||||
var success = true
|
||||
|
||||
runBlocking {
|
||||
val task = async {
|
||||
SubscriptionHelper.getFeed()
|
||||
}
|
||||
// fetch the users feed
|
||||
val videoFeed = try {
|
||||
task.await()
|
||||
SubscriptionHelper.getFeed()
|
||||
} catch (e: Exception) {
|
||||
success = false
|
||||
return@runBlocking
|
||||
|
Loading…
Reference in New Issue
Block a user