From 76f1f8041fc5580a8eff6f013e83e0db370c7aa3 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 8 May 2023 16:47:03 +0200 Subject: [PATCH] Fix importing large playlists or CSV playlist from YT --- .../github/libretube/api/PlaylistsHelper.kt | 25 ++++++++++--------- .../github/libretube/helpers/ImportHelper.kt | 8 ++++-- .../libretube/ui/fragments/PlayerFragment.kt | 8 +++--- .../ui/preferences/BackupRestoreSettings.kt | 3 ++- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/github/libretube/api/PlaylistsHelper.kt b/app/src/main/java/com/github/libretube/api/PlaylistsHelper.kt index b8c786160..a999a9cde 100644 --- a/app/src/main/java/com/github/libretube/api/PlaylistsHelper.kt +++ b/app/src/main/java/com/github/libretube/api/PlaylistsHelper.kt @@ -148,19 +148,20 @@ object PlaylistsHelper { ) } else { // if not logged in, all video information needs to become fetched manually - runCatching { - val streamItems = playlist.videos.map { - async { - runCatching { - RetrofitInstance.api.getStreams(it).toStreamItem(it) - }.getOrNull() - } + // Only do so with 20 videos at once to prevent performance issues + playlist.videos.mapIndexed { index, id -> id to index } + .groupBy { it.second % 20 }.forEach { (_, videos) -> + videos.map { + async { + runCatching { + val stream = RetrofitInstance.api.getStreams(it.first).toStreamItem( + it.first + ) + addToPlaylist(playlistId, stream) + } + } + }.awaitAll() } - .awaitAll() - .filterNotNull() - - addToPlaylist(playlistId, *streamItems.toTypedArray()) - } } } }.awaitAll() diff --git a/app/src/main/java/com/github/libretube/helpers/ImportHelper.kt b/app/src/main/java/com/github/libretube/helpers/ImportHelper.kt index bfa54ed85..06e281c8d 100644 --- a/app/src/main/java/com/github/libretube/helpers/ImportHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/ImportHelper.kt @@ -105,10 +105,14 @@ object ImportHelper { activity.contentResolver.openInputStream(uri)?.use { val lines = it.bufferedReader().use { reader -> reader.lines().toList() } playlist.name = lines[1].split(",").reversed()[2] - val splitIndex = lines.indexOfFirst { line -> line.isBlank() } + var splitIndex = lines.indexOfFirst { line -> line.isBlank() } + // seek until playlist items table + while (lines.getOrNull(splitIndex + 1).orEmpty().isBlank()) { + splitIndex++ + } lines.subList(splitIndex + 2, lines.size).forEach { line -> line.split(",").firstOrNull()?.let { videoId -> - if (videoId.isNotBlank()) playlist.videos = playlist.videos + videoId + if (videoId.isNotBlank()) playlist.videos += videoId.trim() } } importPlaylists.add(playlist) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 885ca734d..08b59651d 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -110,6 +110,10 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import com.google.android.exoplayer2.upstream.DefaultDataSource import com.google.android.exoplayer2.util.MimeTypes import com.google.android.material.dialog.MaterialAlertDialogBuilder +import java.io.IOException +import java.util.* +import java.util.concurrent.Executors +import kotlin.math.abs import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -118,10 +122,6 @@ import kotlinx.coroutines.withContext import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import retrofit2.HttpException -import java.io.IOException -import java.util.* -import java.util.concurrent.Executors -import kotlin.math.abs class PlayerFragment : Fragment(), OnlinePlayerOptions { private var _binding: FragmentPlayerBinding? = null diff --git a/app/src/main/java/com/github/libretube/ui/preferences/BackupRestoreSettings.kt b/app/src/main/java/com/github/libretube/ui/preferences/BackupRestoreSettings.kt index 119c71ced..a946a575b 100644 --- a/app/src/main/java/com/github/libretube/ui/preferences/BackupRestoreSettings.kt +++ b/app/src/main/java/com/github/libretube/ui/preferences/BackupRestoreSettings.kt @@ -13,6 +13,7 @@ import com.github.libretube.ui.base.BasePreferenceFragment import com.github.libretube.ui.dialogs.BackupDialog import java.time.LocalDateTime import java.time.format.DateTimeFormatter +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -63,7 +64,7 @@ class BackupRestoreSettings : BasePreferenceFragment() { */ private val getPlaylistsFile = registerForActivityResult(ActivityResultContracts.GetContent()) { it?.let { - lifecycleScope.launch(Dispatchers.IO) { + CoroutineScope(Dispatchers.IO).launch { ImportHelper.importPlaylists(requireActivity(), it) } }