M melon/playlist/create.py => melon/playlist/create.py +34 -4
@@ 4,17 4,16 @@ gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio, GLib
from gettext import gettext as _
+import threading
from melon.widgets.iconbutton import IconButton
from melon.widgets.simpledialog import SimpleDialog
from melon.widgets.feeditem import AdaptiveFeedItem
-from melon.models import new_local_playlist
+from melon.models import new_local_playlist, Video
from melon.servers.utils import get_app_settings
class PlaylistCreatorDialog(SimpleDialog):
- def __init__(self, video=None, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.set_title(_("New Playlist"))
+ def display(self, video=None):
page = Adw.PreferencesPage()
self.content = []
if not video is None:
@@ 73,6 72,37 @@ class PlaylistCreatorDialog(SimpleDialog):
self.toolbar_view.add_bottom_bar(bottom_bar)
self.set_widget(page)
+ def background(self, target=None):
+ video = None
+ if isinstance(target, Video):
+ # target is already a video object
+ video = target
+ elif not target is None:
+ # we have to fetch the video ourselves
+ server_id = target[0]
+ video_id = target[1]
+ servers = get_servers_list()
+ if server_id in servers:
+ instance = get_server_instance(servers[server_id])
+ video = instance.get_video_info(video_id)
+ GLib.idle_add(self.display, video)
+ def __init__(self, video=None, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.set_title(_("New Playlist"))
+
+ # show spinner
+ # will be cleared by display
+ spinner = Gtk.Spinner()
+ spinner.set_size_request(50, 50)
+ spinner.start()
+ cb = Gtk.CenterBox()
+ cb.set_center_widget(spinner)
+ self.set_widget(cb)
+
+ # start background thread
+ self.thread = threading.Thread(target=self.background, args=[video])
+ self.thread.daemon = True
+ self.thread.start()
def create_playlist(self, x):
new_local_playlist(
M melon/playlist/pick.py => melon/playlist/pick.py +45 -24
@@ 5,12 5,13 @@ gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio, GLib, Gdk
from unidecode import unidecode
from gettext import gettext as _
+import threading
-from melon.widgets.feeditem import AdaptiveFeedItem
+from melon.widgets.feeditem import AdaptiveFeedItem, AdaptivePlaylistFeedItem
from melon.widgets.iconbutton import IconButton
from melon.widgets.simpledialog import SimpleDialog
from melon.models import get_playlists, PlaylistWrapperType, add_to_local_playlist
-from melon.servers.utils import get_app_settings, pixbuf_from_url
+from melon.servers.utils import get_app_settings, pixbuf_from_url, get_servers_list, get_server_instance
from melon.playlist.create import PlaylistCreatorDialog
class PlaylistPickerDialog(SimpleDialog):
@@ 18,9 19,8 @@ class PlaylistPickerDialog(SimpleDialog):
diag = PlaylistCreatorDialog(video)
self.hide()
diag.show()
- def __init__(self, video, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.set_title(_("Add to Playlist"))
+
+ def display(self, video):
page = Adw.PreferencesPage()
# use preference group as preview for video element
@@ 58,25 58,9 @@ class PlaylistPickerDialog(SimpleDialog):
for playlist in get_playlists():
if playlist.type == PlaylistWrapperType.EXTERNAL:
continue
- row = Adw.ActionRow()
- row.set_title(unidecode(playlist.inner.title).replace("&","&"))
- row.set_subtitle(unidecode(playlist.inner.description).replace("&","&"))
- pixbuf = None
- if app_conf["show_images_in_feed"]:
- pixbuf = pixbuf_from_url(playlist.inner.thumbnail)
- avatar = Adw.Avatar()
- avatar.set_size(48)
- if not pixbuf is None:
- texture = Gdk.Texture.new_for_pixbuf(pixbuf)
- avatar.set_custom_image(texture)
- else:
- avatar.set_show_initials(True)
- avatar.set_text(playlist.inner.title)
- row.add_prefix(avatar)
- row.set_activatable(True)
- row.connect(
- "activated",
- pass_me(
+ row = AdaptivePlaylistFeedItem(
+ playlist,
+ onClick=pass_me(
lambda _, playlist, video: add_to_local_playlist(playlist.inner.id, video) or self.hide(),
playlist, video)
)
@@ 98,5 82,42 @@ class PlaylistPickerDialog(SimpleDialog):
self.toolbar_view.add_bottom_bar(bottom_bar)
self.set_widget(page)
+
+ def background(self, target=None):
+ video = None
+
+ if not target is None:
+ server_id = target[0]
+ video_id = target[1]
+ servers = get_servers_list()
+ if server_id in servers:
+ instance = get_server_instance(servers[server_id])
+ video = instance.get_video_info(video_id)
+
+ if not video is None:
+ GLib.idle_add(self.display, video)
+
+ def __init__(self, video, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.set_title(_("Add to Playlist"))
+
+ # should never happen but still
+ if video is None:
+ self.hide()
+
+ # show spinner
+ # will be cleared by display
+ spinner = Gtk.Spinner()
+ spinner.set_size_request(50, 50)
+ spinner.start()
+ cb = Gtk.CenterBox()
+ cb.set_center_widget(spinner)
+ self.set_widget(cb)
+
+ # start background thread
+ self.thread = threading.Thread(target=self.background, args=[video])
+ self.thread.daemon = True
+ self.thread.start()
+
def pass_me(func, *args):
return lambda x: func(x, *args)
M melon/widgets/feeditem.py => melon/widgets/feeditem.py +8 -2
@@ 81,11 81,17 @@ class AdaptiveFeedItem(Adw.ActionRow):
class AdaptivePlaylistFeedItem(Adw.ActionRow):
- def __init__(self, playlist:PlaylistWrapper, show_preview=True, *args, **kwargs):
+ def __init__(self, playlist:PlaylistWrapper, show_preview=True, onClick=None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_title(unidecode(playlist.inner.title).replace("&","&"))
self.set_subtitle(unidecode(playlist.inner.description).replace("&","&"))
- if playlist.type == PlaylistWrapperType.EXTERNAL:
+ if not onClick is None:
+ # use custom click callback
+ self.connect(
+ "activated",
+ onClick
+ )
+ elif playlist.type == PlaylistWrapperType.EXTERNAL:
self.set_action_name("win.browse_playlist")
self.set_action_target_value(
GLib.Variant("as", [playlist.inner.server, playlist.inner.id]))
M melon/window.py => melon/window.py +4 -9
@@ 48,11 48,9 @@ class MainWindow(Adw.ApplicationWindow):
server_id = prefs[0]
video_id = prefs[1]
servers = get_servers_list()
- if server_id in servers:
- instance = get_server_instance(servers[server_id])
- video = instance.get_video_info(video_id)
- diag = PlaylistPickerDialog(video)
- diag.show()
+ video = (server_id, video_id)
+ diag = PlaylistPickerDialog(video)
+ diag.show()
def open_playlist_creator(self, action, prefs):
act = action.get_name()
# video to be automatically added (if available)
@@ 61,10 59,7 @@ class MainWindow(Adw.ApplicationWindow):
# open new playlist dialog & add video to said playlist
server_id = prefs[0]
video_id = prefs[1]
- servers = get_servers_list()
- if server_id in servers:
- instance = get_server_instance(servers[server_id])
- video = instance.get_video_info(video_id)
+ video = (server_id, video_id)
# create basic dialog
diag = PlaylistCreatorDialog(video)
diag.show()