Add functionality for exporting and importing playlists

This commit is contained in:
Bnyro 2022-12-01 14:37:44 +01:00
parent c1793691ed
commit 5616934817
6 changed files with 60 additions and 24 deletions

View File

@ -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

View File

@ -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) {

View File

@ -123,7 +123,7 @@ class LibraryFragment : BaseFragment() {
val playlistsAdapter = PlaylistsAdapter(
playlists.toMutableList(),
PlaylistsHelper.getPrivateType()
PlaylistsHelper.getPlaylistType()
)
// listen for playlists to become deleted

View File

@ -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")

View File

@ -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()

View File

@ -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