mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-05-29 13:00:21 +02:00
Merge branch 'playlist-fixes' into 'master'
Playlist Fixes See merge request videostreaming/grayjay!21
This commit is contained in:
commit
c76ef7f19b
@ -14,6 +14,7 @@ import com.futo.platformplayer.api.media.models.video.IPlatformVideo
|
|||||||
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
|
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
|
||||||
import com.futo.platformplayer.constructs.TaskHandler
|
import com.futo.platformplayer.constructs.TaskHandler
|
||||||
import com.futo.platformplayer.downloads.VideoDownload
|
import com.futo.platformplayer.downloads.VideoDownload
|
||||||
|
import com.futo.platformplayer.fragment.mainactivity.topbar.NavigationTopBarFragment
|
||||||
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.StateApp
|
import com.futo.platformplayer.states.StateApp
|
||||||
@ -144,53 +145,59 @@ class PlaylistFragment : MainFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onShown(parameter: Any?) {
|
fun onShown(parameter: Any?) {
|
||||||
_taskLoadPlaylist.cancel();
|
_taskLoadPlaylist.cancel()
|
||||||
|
|
||||||
if (parameter is Playlist?) {
|
if (parameter is Playlist?) {
|
||||||
_playlist = parameter;
|
_playlist = parameter
|
||||||
_url = null;
|
_url = null
|
||||||
|
|
||||||
if(parameter != null) {
|
if (parameter != null) {
|
||||||
setName(parameter.name);
|
setName(parameter.name)
|
||||||
setVideos(parameter.videos, true);
|
setVideos(parameter.videos, true)
|
||||||
setVideoCount(parameter.videos.size);
|
setVideoCount(parameter.videos.size)
|
||||||
setButtonDownloadVisible(true);
|
setButtonDownloadVisible(true)
|
||||||
setButtonEditVisible(true);
|
setButtonEditVisible(true)
|
||||||
|
|
||||||
|
if (!StatePlaylists.instance.playlistStore.getItems().contains(parameter)) {
|
||||||
|
_fragment.topBar?.assume<NavigationTopBarFragment>()
|
||||||
|
?.setMenuItems(arrayListOf(Pair(R.drawable.ic_copy) {
|
||||||
|
StatePlaylists.instance.playlistStore.save(parameter)
|
||||||
|
UIDialogs.toast("Playlist saved")
|
||||||
|
}))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setName(null);
|
setName(null)
|
||||||
setVideos(null, false);
|
setVideos(null, false)
|
||||||
setVideoCount(-1);
|
setVideoCount(-1)
|
||||||
setButtonDownloadVisible(false);
|
setButtonDownloadVisible(false)
|
||||||
setButtonEditVisible(false);
|
setButtonEditVisible(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Do I have to remove the showConvertPlaylistButton(); button here?
|
|
||||||
} else if (parameter is IPlatformPlaylist) {
|
} else if (parameter is IPlatformPlaylist) {
|
||||||
_playlist = null;
|
_playlist = null
|
||||||
_url = parameter.url;
|
_url = parameter.url
|
||||||
|
|
||||||
setVideoCount(parameter.videoCount);
|
setVideoCount(parameter.videoCount)
|
||||||
setName(parameter.name);
|
setName(parameter.name)
|
||||||
setVideos(null, false);
|
setVideos(null, false)
|
||||||
setButtonDownloadVisible(false);
|
setButtonDownloadVisible(false)
|
||||||
setButtonEditVisible(false);
|
setButtonEditVisible(false)
|
||||||
|
|
||||||
fetchPlaylist();
|
fetchPlaylist()
|
||||||
} else if (parameter is String) {
|
} else if (parameter is String) {
|
||||||
_playlist = null;
|
_playlist = null
|
||||||
_url = parameter;
|
_url = parameter
|
||||||
|
|
||||||
setName(null);
|
setName(null)
|
||||||
setVideos(null, false);
|
setVideos(null, false)
|
||||||
setVideoCount(-1);
|
setVideoCount(-1)
|
||||||
setButtonDownloadVisible(false);
|
setButtonDownloadVisible(false)
|
||||||
setButtonEditVisible(false);
|
setButtonEditVisible(false)
|
||||||
|
|
||||||
fetchPlaylist();
|
fetchPlaylist()
|
||||||
}
|
}
|
||||||
|
|
||||||
_playlist?.let {
|
_playlist?.let {
|
||||||
updateDownloadState(VideoDownload.GROUP_PLAYLIST, it.id, this::download);
|
updateDownloadState(VideoDownload.GROUP_PLAYLIST, it.id, this::download)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,12 +31,16 @@ import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
|||||||
import com.futo.platformplayer.logging.Logger
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.states.StateApp
|
import com.futo.platformplayer.states.StateApp
|
||||||
import com.futo.platformplayer.states.StatePlatform
|
import com.futo.platformplayer.states.StatePlatform
|
||||||
|
import com.futo.platformplayer.states.StatePlayer
|
||||||
import com.futo.platformplayer.states.StatePlaylists
|
import com.futo.platformplayer.states.StatePlaylists
|
||||||
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
import com.futo.platformplayer.views.adapters.InsertedViewAdapterWithLoader
|
||||||
import com.futo.platformplayer.views.adapters.VideoListEditorViewHolder
|
import com.futo.platformplayer.views.adapters.VideoListEditorViewHolder
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
enum class Action {
|
||||||
|
PLAY_ALL, SHUFFLE, PLAY, NONE
|
||||||
|
}
|
||||||
|
|
||||||
class RemotePlaylistFragment : MainFragment() {
|
class RemotePlaylistFragment : MainFragment() {
|
||||||
override val isMainView : Boolean = true;
|
override val isMainView : Boolean = true;
|
||||||
@ -85,6 +89,8 @@ class RemotePlaylistFragment : MainFragment() {
|
|||||||
private val _adapterVideos: InsertedViewAdapterWithLoader<VideoListEditorViewHolder>;
|
private val _adapterVideos: InsertedViewAdapterWithLoader<VideoListEditorViewHolder>;
|
||||||
private val _scrollListener: RecyclerView.OnScrollListener
|
private val _scrollListener: RecyclerView.OnScrollListener
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
constructor(fragment: RemotePlaylistFragment, inflater: LayoutInflater) : super(inflater.context) {
|
constructor(fragment: RemotePlaylistFragment, inflater: LayoutInflater) : super(inflater.context) {
|
||||||
inflater.inflate(R.layout.fragment_remote_playlist, this);
|
inflater.inflate(R.layout.fragment_remote_playlist, this);
|
||||||
|
|
||||||
@ -97,18 +103,25 @@ class RemotePlaylistFragment : MainFragment() {
|
|||||||
_imageLoader = findViewById(R.id.image_loader);
|
_imageLoader = findViewById(R.id.image_loader);
|
||||||
_recyclerPlaylist = findViewById(R.id.recycler_playlist);
|
_recyclerPlaylist = findViewById(R.id.recycler_playlist);
|
||||||
_llmPlaylist = LinearLayoutManager(context);
|
_llmPlaylist = LinearLayoutManager(context);
|
||||||
_adapterVideos = InsertedViewAdapterWithLoader(context, arrayListOf(), arrayListOf(),
|
_adapterVideos = InsertedViewAdapterWithLoader(context,
|
||||||
|
arrayListOf(),
|
||||||
|
arrayListOf(),
|
||||||
childCountGetter = { _videos.size },
|
childCountGetter = { _videos.size },
|
||||||
childViewHolderBinder = { viewHolder, position -> viewHolder.bind(_videos[position], false); },
|
childViewHolderBinder = { viewHolder, position ->
|
||||||
|
viewHolder.bind(
|
||||||
|
_videos[position],
|
||||||
|
false
|
||||||
|
)
|
||||||
|
},
|
||||||
childViewHolderFactory = { viewGroup, _ ->
|
childViewHolderFactory = { viewGroup, _ ->
|
||||||
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.list_playlist, viewGroup, false);
|
val view = LayoutInflater.from(viewGroup.context)
|
||||||
val holder = VideoListEditorViewHolder(view, null);
|
.inflate(R.layout.list_playlist, viewGroup, false)
|
||||||
|
val holder = VideoListEditorViewHolder(view, null)
|
||||||
holder.onClick.subscribe {
|
holder.onClick.subscribe {
|
||||||
showConvertConfirmationModal();
|
convertPlaylist(false, Action.PLAY, holder.video)
|
||||||
};
|
}
|
||||||
return@InsertedViewAdapterWithLoader holder;
|
return@InsertedViewAdapterWithLoader holder
|
||||||
}
|
})
|
||||||
);
|
|
||||||
|
|
||||||
_recyclerPlaylist.adapter = _adapterVideos;
|
_recyclerPlaylist.adapter = _adapterVideos;
|
||||||
_recyclerPlaylist.layoutManager = _llmPlaylist;
|
_recyclerPlaylist.layoutManager = _llmPlaylist;
|
||||||
@ -128,10 +141,10 @@ class RemotePlaylistFragment : MainFragment() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
buttonPlayAll.setOnClickListener {
|
buttonPlayAll.setOnClickListener {
|
||||||
showConvertConfirmationModal();
|
convertPlaylist(false, Action.PLAY_ALL);
|
||||||
};
|
};
|
||||||
buttonShuffle.setOnClickListener {
|
buttonShuffle.setOnClickListener {
|
||||||
showConvertConfirmationModal();
|
convertPlaylist(false, Action.SHUFFLE);
|
||||||
};
|
};
|
||||||
|
|
||||||
_taskLoadPlaylist = TaskHandler<String, IPlatformPlaylistDetails>(
|
_taskLoadPlaylist = TaskHandler<String, IPlatformPlaylistDetails>(
|
||||||
@ -253,48 +266,76 @@ class RemotePlaylistFragment : MainFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showConvertConfirmationModal() {
|
private fun convertPlaylist(
|
||||||
val remotePlaylist = _remotePlaylist;
|
savePlaylist: Boolean, action: Action, video: IPlatformVideo? = null
|
||||||
|
) {
|
||||||
|
val remotePlaylist = _remotePlaylist
|
||||||
if (remotePlaylist == null) {
|
if (remotePlaylist == null) {
|
||||||
UIDialogs.toast(context.getString(R.string.please_wait_for_playlist_to_finish_loading));
|
UIDialogs.toast(context.getString(R.string.please_wait_for_playlist_to_finish_loading))
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val c = context ?: return;
|
val convert = {
|
||||||
UIDialogs.showConfirmationDialog(c, "Conversion to local playlist is required for this action", {
|
setLoading(true)
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
UIDialogs.showDialogProgress(context) {
|
UIDialogs.showDialogProgress(context) {
|
||||||
it.setText("Converting playlist..");
|
it.setText("Converting playlist..")
|
||||||
it.setProgress(0f);
|
it.setProgress(0f)
|
||||||
|
|
||||||
_fragment.lifecycleScope.launch(Dispatchers.IO) {
|
_fragment.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val playlist = remotePlaylist.toPlaylist() { progress ->
|
val playlist = remotePlaylist.toPlaylist { progress ->
|
||||||
_fragment.lifecycleScope.launch(Dispatchers.Main) {
|
_fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
it.setProgress(progress.toDouble() / remotePlaylist.videoCount);
|
it.setProgress(progress.toDouble() / remotePlaylist.videoCount)
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
StatePlaylists.instance.playlistStore.save(playlist);
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
UIDialogs.toast("Playlist converted");
|
|
||||||
it.dismiss();
|
|
||||||
_fragment.navigate<PlaylistFragment>(playlist);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch(ex: Throwable) {
|
if (savePlaylist) {
|
||||||
UIDialogs.appToast("Failed to convert playlist.\n" + ex.message);
|
StatePlaylists.instance.playlistStore.save(playlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
_fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
|
UIDialogs.toast("Playlist converted")
|
||||||
|
it.dismiss()
|
||||||
|
_fragment.navigate<PlaylistFragment>(playlist)
|
||||||
|
when (action) {
|
||||||
|
Action.SHUFFLE -> StatePlayer.instance.setPlaylist(
|
||||||
|
playlist, focus = true, shuffle = true
|
||||||
|
)
|
||||||
|
|
||||||
|
Action.PLAY_ALL -> StatePlayer.instance.setPlaylist(
|
||||||
|
playlist, focus = true
|
||||||
|
)
|
||||||
|
|
||||||
|
Action.PLAY -> {
|
||||||
|
StatePlayer.instance.setPlaylist(
|
||||||
|
playlist, _videos.indexOf(video), true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Action.NONE -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
UIDialogs.appToast("Failed to convert playlist.\n" + ex.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (remotePlaylist.videoCount > 100) {
|
||||||
|
val c = context ?: return
|
||||||
|
UIDialogs.showConfirmationDialog(
|
||||||
|
c, "Conversion to local playlist is required for this action", convert
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
convert()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showConvertPlaylistButton() {
|
private fun showConvertPlaylistButton() {
|
||||||
_fragment.topBar?.assume<NavigationTopBarFragment>()?.setMenuItems(arrayListOf(Pair(R.drawable.ic_copy) {
|
_fragment.topBar?.assume<NavigationTopBarFragment>()?.setMenuItems(arrayListOf(Pair(R.drawable.ic_copy) {
|
||||||
showConvertConfirmationModal();
|
convertPlaylist(true, Action.NONE);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user