refactor: Restructure GUI components into separate modules for improved maintainability
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
"""Track extras mixin for MainWindow.
|
||||
|
||||
Handles track extras caching and retrieval.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
from collections.abc import Callable
|
||||
|
||||
from PySide6 import QtCore
|
||||
|
||||
from tidal_dl_ng.helper.tidal import extract_contributor_names, fetch_raw_track_and_album, parse_track_and_album_extras
|
||||
from tidal_dl_ng.worker import Worker
|
||||
|
||||
|
||||
class TrackExtrasMixin:
|
||||
"""Mixin containing track extras management methods."""
|
||||
|
||||
def get_track_extras(self, track_id: str, callback: Callable[[str, dict | None], None]) -> dict | None:
|
||||
"""Return cached extras for a track or start async fetch."""
|
||||
cached = self.track_extras_cache.get(track_id)
|
||||
if cached is not None:
|
||||
return cached
|
||||
|
||||
if track_id in self._pending_extras_workers:
|
||||
return None
|
||||
|
||||
if callback:
|
||||
self._track_extras_callbacks[track_id] = callback
|
||||
|
||||
def worker() -> None:
|
||||
extras = None
|
||||
try:
|
||||
track_json, album_json = fetch_raw_track_and_album(self.tidal.session, track_id)
|
||||
extras = parse_track_and_album_extras(track_json, album_json)
|
||||
extras = self._decorate_extras(extras)
|
||||
self.track_extras_cache.set(track_id, extras)
|
||||
except Exception:
|
||||
extras = None
|
||||
finally:
|
||||
self._pending_extras_workers.pop(track_id, None)
|
||||
self.s_track_extras_ready.emit(track_id, extras)
|
||||
self.s_invoke_callback.emit(track_id, extras)
|
||||
|
||||
worker_obj = Worker(worker)
|
||||
self._pending_extras_workers[track_id] = worker_obj
|
||||
self.threadpool.start(worker_obj)
|
||||
return None
|
||||
|
||||
@QtCore.Slot(str, object)
|
||||
def _on_invoke_callback(self, track_id: str, extras: dict | None) -> None:
|
||||
"""Invoke the stored callback for a track in the main thread."""
|
||||
callback = self._track_extras_callbacks.pop(track_id, None)
|
||||
if callback:
|
||||
with contextlib.suppress(Exception):
|
||||
callback(track_id, extras)
|
||||
|
||||
def _decorate_extras(self, extras: dict | None) -> dict:
|
||||
"""Add formatted string fields to extras dict."""
|
||||
if not extras:
|
||||
return {}
|
||||
result = dict(extras)
|
||||
result["genres_text"] = ", ".join(result.get("genres", []))
|
||||
for role, key in [
|
||||
("producer", "producers_text"),
|
||||
("composer", "composers_text"),
|
||||
("lyricist", "lyricists_text"),
|
||||
]:
|
||||
result[key] = extract_contributor_names(result.get("contributors_by_role"), role)
|
||||
return result
|
||||
|
||||
def preload_covers_for_playlist(self, items: list) -> None:
|
||||
"""Preload cover pixmaps for a list of tracks in background."""
|
||||
if self.cover_manager:
|
||||
self.cover_manager.preload_covers_for_playlist(items)
|
||||
Reference in New Issue
Block a user