diff --git a/ui/pages/__pycache__/artists.cpython-312.pyc b/ui/pages/__pycache__/artists.cpython-312.pyc index 31ff59e8..a9b924f2 100644 Binary files a/ui/pages/__pycache__/artists.cpython-312.pyc and b/ui/pages/__pycache__/artists.cpython-312.pyc differ diff --git a/ui/pages/__pycache__/sync.cpython-312.pyc b/ui/pages/__pycache__/sync.cpython-312.pyc index 67f3a472..b961424d 100644 Binary files a/ui/pages/__pycache__/sync.cpython-312.pyc and b/ui/pages/__pycache__/sync.cpython-312.pyc differ diff --git a/ui/pages/artists.py b/ui/pages/artists.py index 3ea8e8dc..e20706b9 100644 --- a/ui/pages/artists.py +++ b/ui/pages/artists.py @@ -2779,16 +2779,24 @@ class ArtistsPage(QWidget): if not query: self.search_status.setText("Please enter an artist name") self.search_status.setStyleSheet("color: #ff6b6b; padding: 10px;") + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.warning("Please enter an artist name to search") return if not self.spotify_client or not self.spotify_client.is_authenticated(): self.search_status.setText("Spotify not connected") self.search_status.setStyleSheet("color: #ff6b6b; padding: 10px;") + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.error("Spotify authentication required") return self.search_status.setText("🔍 Searching for artists...") self.search_status.setStyleSheet("color: #1db954; padding: 10px;") + # Show toast for search start + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.info(f"Searching for artists: '{query}'") + # Clear previous results self.clear_artist_results() @@ -2815,11 +2823,18 @@ class ArtistsPage(QWidget): if not artist_matches: self.search_status.setText("No artists found") self.search_status.setStyleSheet("color: #ff6b6b; padding: 10px;") + if hasattr(self, 'toast_manager') and self.toast_manager: + query = self.search_input.text().strip() + self.toast_manager.warning(f"No artists found for '{query}'") return self.search_status.setText(f"Found {len(artist_matches)} artists") self.search_status.setStyleSheet("color: #1db954; padding: 10px;") + # Show success toast + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.success(f"Found {len(artist_matches)} artists matching your search") + # Display artist results for artist_match in artist_matches[:10]: # Show top 10 results card = ArtistResultCard(artist_match) @@ -2833,6 +2848,10 @@ class ArtistsPage(QWidget): """Handle artist search failure""" self.search_status.setText(f"Search failed: {error}") self.search_status.setStyleSheet("color: #ff6b6b; padding: 10px;") + + # Show error toast + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.error(f"Artist search failed: {error}") def on_artist_selected(self, artist): """Handle artist selection""" @@ -2853,6 +2872,10 @@ class ArtistsPage(QWidget): """Fetch albums for selected artist""" self.albums_status.setText("Loading albums...") + # Show toast for album loading + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.info(f"Loading albums for {artist.name}") + # Clear previous albums self.clear_albums() @@ -2910,6 +2933,10 @@ class ArtistsPage(QWidget): def start_plex_library_check(self, albums): """Start Plex library check in background""" + # Show toast for Plex check start + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.info("Checking your Plex library for owned albums...") + # Stop any existing Plex worker if self.plex_library_worker: self.plex_library_worker.stop() @@ -2938,6 +2965,13 @@ class ArtistsPage(QWidget): self.albums_status.setText(f"Found {total_count} albums • {owned_count} owned • {missing_count} available for download") + # Show toast with Plex check results + if hasattr(self, 'toast_manager') and self.toast_manager: + if owned_count == 0: + self.toast_manager.info(f"No albums found in your Plex library ({total_count} available for download)") + else: + self.toast_manager.success(f"Found {owned_count} of {total_count} albums in your Plex library") + print(f"✅ Plex check complete: {owned_count}/{total_count} albums owned") def on_album_matched(self, album_name): @@ -2966,6 +3000,11 @@ class ArtistsPage(QWidget): def on_plex_library_check_failed(self, error): """Handle Plex library check failure""" print(f"Plex library check failed: {error}") + + # Show error toast + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.error("Plex connection failed - cannot check owned albums") + if self.current_albums: self.albums_status.setText(f"Found {len(self.current_albums)} albums • Plex check failed") # Display albums without ownership info diff --git a/ui/pages/sync.py b/ui/pages/sync.py index a1abd0f8..2403e17a 100644 --- a/ui/pages/sync.py +++ b/ui/pages/sync.py @@ -14,6 +14,7 @@ from core.soulseek_client import TrackResult import re import asyncio from core.matching_engine import MusicMatchingEngine +from ui.components.toast_manager import ToastType # Define constants for storage STORAGE_DIR = "storage" @@ -2042,6 +2043,12 @@ class SyncPage(QWidget): # Emit activity signal for sync start self.sync_activity.emit("🔄", "Sync Started", f"Syncing playlist '{playlist.name}'", "Now") + # Show toast notification for sync start + if hasattr(self, 'toast_manager') and self.toast_manager: + track_count = len(playlist.tracks) if hasattr(playlist, 'tracks') else 0 + if track_count > 0: + self.toast_manager.show_toast(f"Starting sync for '{playlist.name}' ({track_count} tracks)", ToastType.INFO) + # Start the worker self.thread_pool.start(sync_worker) @@ -2098,6 +2105,12 @@ class SyncPage(QWidget): if hasattr(self, 'log_area'): self.log_area.append(f"🔄 Starting sequential sync for playlist: {playlist.name}") + # Show toast notification for sequential sync start + if hasattr(self, 'toast_manager') and self.toast_manager: + track_count = len(playlist.tracks) if hasattr(playlist, 'tracks') else 0 + if track_count > 0: + self.toast_manager.show_toast(f"Starting sequential sync for '{playlist.name}' ({track_count} tracks)", ToastType.INFO) + return True def toggle_playlist_selection(self, playlist_id): @@ -2235,6 +2248,15 @@ class SyncPage(QWidget): if result.failed_tracks > 0: msg += f", {result.failed_tracks} failed" self.log_area.append(msg) + + # Show toast notification for sequential sync completion + if hasattr(self, 'toast_manager') and self.toast_manager: + playlist_item = self.find_playlist_item_widget(playlist_id) + playlist_name = playlist_item.name if playlist_item else "Unknown Playlist" + if result.failed_tracks > 0: + self.toast_manager.show_toast(f"'{playlist_name}' sync completed: {result.matched_tracks}/{result.total_tracks} tracks, {result.failed_tracks} failed", ToastType.WARNING) + else: + self.toast_manager.show_toast(f"'{playlist_name}' sync completed: {result.matched_tracks} tracks added", ToastType.SUCCESS) # **THE FIX**: Defer processing the next item to allow the event loop to catch up. # This ensures UI updates (like the status label) are processed before moving on. @@ -2262,6 +2284,12 @@ class SyncPage(QWidget): # Log error if hasattr(self, 'log_area'): self.log_area.append(f"❌ Sequential sync failed: {error_msg}") + + # Show toast notification for sequential sync error + if hasattr(self, 'toast_manager') and self.toast_manager: + playlist_item = self.find_playlist_item_widget(playlist_id) + playlist_name = playlist_item.name if playlist_id else "Unknown Playlist" + self.toast_manager.show_toast(f"Sequential sync failed for '{playlist_name}': {error_msg}", ToastType.ERROR) # **THE FIX**: Defer processing the next item to allow the event loop to catch up. if self.is_sequential_syncing: @@ -2344,6 +2372,13 @@ class SyncPage(QWidget): playlist_name = playlist_item.name if playlist_item else "Unknown Playlist" success_msg = f"Completed: {result.matched_tracks}/{result.total_tracks} tracks" self.sync_activity.emit("✅", "Sync Complete", f"'{playlist_name}' - {success_msg}", "Now") + + # Show toast notification for sync completion + if hasattr(self, 'toast_manager') and self.toast_manager: + if result.failed_tracks > 0: + self.toast_manager.show_toast(f"Sync completed: {result.matched_tracks}/{result.total_tracks} tracks added, {result.failed_tracks} failed", ToastType.WARNING) + else: + self.toast_manager.show_toast(f"Sync completed: {result.matched_tracks} tracks added to queue", ToastType.SUCCESS) # Continue sequential sync if in progress if self.is_sequential_syncing: @@ -2383,6 +2418,10 @@ class SyncPage(QWidget): playlist_name = playlist_item.name if playlist_item else "Unknown Playlist" self.sync_activity.emit("❌", "Sync Failed", f"'{playlist_name}' - {error_msg}", "Now") + # Show toast notification for sync error + if hasattr(self, 'toast_manager') and self.toast_manager: + self.toast_manager.show_toast(f"Sync failed for '{playlist_name}': {error_msg}", ToastType.ERROR) + # Continue sequential sync if in progress (even on error) if self.is_sequential_syncing: self.process_next_in_sync_queue()