Improved playlist import support

This commit is contained in:
Kelvin K 2024-06-13 13:45:31 +02:00
commit aad50e7b50
5 changed files with 42 additions and 15 deletions

View file

@ -12,16 +12,21 @@ import android.widget.TextView
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.futo.platformplayer.* import com.futo.platformplayer.*
import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylistDetails
import com.futo.platformplayer.constructs.TaskHandler import com.futo.platformplayer.constructs.TaskHandler
import com.futo.platformplayer.fragment.mainactivity.topbar.ImportTopBarFragment import com.futo.platformplayer.fragment.mainactivity.topbar.ImportTopBarFragment
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.models.Playlist import com.futo.platformplayer.models.Playlist
import com.futo.platformplayer.states.StatePlatform import com.futo.platformplayer.states.StatePlatform
import com.futo.platformplayer.states.StatePlaylists import com.futo.platformplayer.states.StatePlaylists
import com.futo.platformplayer.states.StateSubscriptions
import com.futo.platformplayer.views.AnyAdapterView import com.futo.platformplayer.views.AnyAdapterView
import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny
import com.futo.platformplayer.views.adapters.viewholders.ImportPlaylistsViewHolder import com.futo.platformplayer.views.adapters.viewholders.ImportPlaylistsViewHolder
import com.futo.platformplayer.views.adapters.viewholders.SelectablePlaylist import com.futo.platformplayer.views.adapters.viewholders.SelectablePlaylist
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ImportPlaylistsFragment : MainFragment() { class ImportPlaylistsFragment : MainFragment() {
override val isMainView : Boolean = true; override val isMainView : Boolean = true;
@ -67,7 +72,7 @@ class ImportPlaylistsFragment : MainFragment() {
private val _items: ArrayList<SelectablePlaylist> = arrayListOf(); private val _items: ArrayList<SelectablePlaylist> = arrayListOf();
private var _currentLoadIndex = 0; private var _currentLoadIndex = 0;
private var _taskLoadPlaylist: TaskHandler<String, Playlist?>; private var _taskLoadPlaylist: TaskHandler<String, IPlatformPlaylistDetails?>;
constructor(fragment: ImportPlaylistsFragment, inflater: LayoutInflater) : super(inflater.context) { constructor(fragment: ImportPlaylistsFragment, inflater: LayoutInflater) : super(inflater.context) {
_fragment = fragment; _fragment = fragment;
@ -102,7 +107,7 @@ class ImportPlaylistsFragment : MainFragment() {
setLoading(false); setLoading(false);
_taskLoadPlaylist = TaskHandler<String, Playlist?>({fragment.lifecycleScope}, { link -> StatePlatform.instance.getPlaylist(link).toPlaylist(); }) _taskLoadPlaylist = TaskHandler<String, IPlatformPlaylistDetails?>({fragment.lifecycleScope}, { link -> StatePlatform.instance.getPlaylist(link); })
.success { .success {
if (it != null) { if (it != null) {
_items.add(SelectablePlaylist(it)); _items.add(SelectablePlaylist(it));
@ -113,7 +118,7 @@ class ImportPlaylistsFragment : MainFragment() {
}.exceptionWithParameter<Throwable> { ex, para -> }.exceptionWithParameter<Throwable> { ex, para ->
//setLoading(false); //setLoading(false);
Logger.w(ChannelFragment.TAG, "Failed to load results.", ex); Logger.w(ChannelFragment.TAG, "Failed to load results.", ex);
UIDialogs.toast(context, context.getString(R.string.failed_to_fetch) + "\n${para}", false) UIDialogs.appToast(context.getString(R.string.failed_to_fetch) + "\n${para}\n" + ex.message, false)
//UIDialogs.showDataRetryDialog(layoutInflater, { load(); }); //UIDialogs.showDataRetryDialog(layoutInflater, { load(); });
loadNext(); loadNext();
}; };
@ -147,12 +152,32 @@ class ImportPlaylistsFragment : MainFragment() {
it.title = context.getString(R.string.import_playlists); it.title = context.getString(R.string.import_playlists);
it.onImport.subscribe(this) { it.onImport.subscribe(this) {
val playlistsToImport = _items.filter { i -> i.selected }.toList(); val playlistsToImport = _items.filter { i -> i.selected }.toList();
for (playlistToImport in playlistsToImport) {
StatePlaylists.instance.createOrUpdatePlaylist(playlistToImport.playlist);
}
UIDialogs.toast("${playlistsToImport.size} " + context.getString(R.string.playlists_imported)); UIDialogs.showDialogProgress(context) {
_fragment.closeSegment(); it.setText("Importing playlists..");
it.setProgress(0f);
_fragment.lifecycleScope.launch(Dispatchers.IO) {
for ((i, playlistToImport) in playlistsToImport.withIndex()) {
withContext(Dispatchers.Main) {
it.setText("Importing playlists..\n[${playlistToImport.playlist.name}]");
}
try {
StatePlaylists.instance.createOrUpdatePlaylist(playlistToImport.playlist.toPlaylist());
}
catch(ex: Throwable) {
UIDialogs.appToast("Failed to import [${playlistToImport.playlist.name}]\n" + ex.message);
}
withContext(Dispatchers.Main) {
it.setProgress(i.toDouble() / playlistsToImport.size);
}
}
withContext(Dispatchers.Main) {
UIDialogs.toast("${playlistsToImport.size} " + context.getString(R.string.playlists_imported));
_fragment.closeSegment();
it.dismiss();
}
}
}
}; };
} }
} }

View file

@ -136,12 +136,12 @@ class PlaylistFragment : MainFragment() {
return@TaskHandler StatePlatform.instance.getPlaylist(it); return@TaskHandler StatePlatform.instance.getPlaylist(it);
}) })
.success { .success {
setLoading(false);
_remotePlaylist = it; _remotePlaylist = it;
setName(it.name); setName(it.name);
setVideos(it.contents.getResults(), false);
setVideoCount(it.videoCount);
//TODO: Implement support for pagination //TODO: Implement support for pagination
setVideos(it.toPlaylist().videos, false);
setVideoCount(it.videoCount);
setLoading(false);
} }
.exception<Throwable> { .exception<Throwable> {
Logger.w(TAG, "Failed to load playlist.", it); Logger.w(TAG, "Failed to load playlist.", it);

View file

@ -7,6 +7,7 @@ import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.futo.platformplayer.R import com.futo.platformplayer.R
import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylistDetails
import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.models.Playlist import com.futo.platformplayer.models.Playlist
import com.futo.platformplayer.views.adapters.AnyAdapter import com.futo.platformplayer.views.adapters.AnyAdapter
@ -45,10 +46,10 @@ class ImportPlaylistsViewHolder(private val _viewGroup: ViewGroup) : AnyAdapter.
override fun bind(value: SelectablePlaylist) { override fun bind(value: SelectablePlaylist) {
_textName.text = value.playlist.name; _textName.text = value.playlist.name;
_textMetadata.text = "${value.playlist.videos.size} " + _view.context.getString(R.string.videos); _textMetadata.text = "${value.playlist.videoCount} " + _view.context.getString(R.string.videos);
_checkbox.value = value.selected; _checkbox.value = value.selected;
val thumbnail = value.playlist.videos.firstOrNull()?.thumbnails?.getHQThumbnail(); val thumbnail = value.playlist.thumbnail;
if (thumbnail != null) if (thumbnail != null)
Glide.with(_imageThumbnail) Glide.with(_imageThumbnail)
.load(thumbnail) .load(thumbnail)
@ -62,6 +63,6 @@ class ImportPlaylistsViewHolder(private val _viewGroup: ViewGroup) : AnyAdapter.
} }
class SelectablePlaylist( class SelectablePlaylist(
val playlist: Playlist, val playlist: IPlatformPlaylistDetails,
var selected: Boolean = false var selected: Boolean = false
) { } ) { }

View file

@ -45,6 +45,7 @@
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="14dp" android:textSize="14dp"
android:fontFamily="@font/inter_regular" android:fontFamily="@font/inter_regular"
android:textAlignment="center"
android:layout_marginTop="30dp" android:layout_marginTop="30dp"
android:layout_marginStart="30dp" android:layout_marginStart="30dp"
android:layout_marginEnd="30dp" /> android:layout_marginEnd="30dp" />

@ -1 +1 @@
Subproject commit c23302da76fc706faf02f7d9331ed28baed04607 Subproject commit 2a38e0cecc635df2122b142f2d0c9e13ac894772