diff --git a/ui/components/version_info_modal.py b/ui/components/version_info_modal.py index 9d0ed2b7..281ef6d9 100644 --- a/ui/components/version_info_modal.py +++ b/ui/components/version_info_modal.py @@ -13,7 +13,7 @@ class VersionInfoModal(QDialog): def __init__(self, parent=None): super().__init__(parent) - self.setWindowTitle("What's New in SoulSync v0.5") + self.setWindowTitle("What's New in SoulSync v0.51") self.setModal(True) self.setFixedSize(600, 500) self.setup_ui() @@ -68,7 +68,7 @@ class VersionInfoModal(QDialog): """) # Version subtitle - version_subtitle = QLabel("Version 0.5 - Latest Features & Improvements") + version_subtitle = QLabel("Version 0.51 - Latest Features & Improvements") version_subtitle.setFont(QFont("SF Pro Text", 11, QFont.Weight.Medium)) version_subtitle.setStyleSheet(""" color: rgba(255, 255, 255, 0.7); @@ -112,63 +112,50 @@ class VersionInfoModal(QDialog): content_layout.setContentsMargins(30, 25, 30, 25) content_layout.setSpacing(25) - # New Watchlist Feature - watchlist_section = self.create_feature_section( - "🔍 New Watchlist Feature", - "Track your favorite artists and get notified when they release new music", + # Settings Page Improvements + settings_section = self.create_feature_section( + "⚙️ Settings Page Improvements", + "Enhanced settings interface for better usability and visual consistency", [ - "• Automatically monitors your favorite artists for new releases", - "• Smart scanning that checks only for releases since last scan", - "• Real-time progress tracking with detailed status indicators", - "• Seamless integration with your existing music library", - "• Configurable scan intervals (now every 10 minutes for faster updates)", - "• Search functionality for managing large artist lists (200+ artists)", - "• Visual status icons showing scan recency and completion status" - ], - "How to use: Go to the Artists page, click 'Add to Watchlist' on any artist card, then monitor progress in the new Watchlist Status modal accessible from the Dashboard." + "• Added vertical scrolling support for better usability on small screens", + "• Cleaned up text backgrounds throughout settings for better visual consistency", + "• Applied consistent green monospace styling to log file path display", + "• Added rounded corners to API configuration frames (Spotify, Plex, Soulseek)", + "• Enhanced label styling with transparent backgrounds and proper white text" + ] + ) + content_layout.addWidget(settings_section) + + # Watchlist System Enhancements + watchlist_section = self.create_feature_section( + "👀 Watchlist System Enhancements", + "Improved reliability and user experience for artist monitoring", + [ + "• Enhanced rate limiting with comprehensive multi-layer protection to prevent API bans", + "• Increased delays between artists (2.0s) and albums (0.5s) for safer scanning", + "• Enhanced Spotify API interval timing and error handling", + "• Unified scan implementation - manual and auto scans now use same worker for consistency", + "• Fixed progress bars resetting when reopening modal during active scans", + "• Professional artist cards with improved visual hierarchy and spacing", + "• Modern hover effects and enhanced delete button styling" + ] ) content_layout.addWidget(watchlist_section) - # Enhanced Progress Tracking - progress_section = self.create_feature_section( - "📊 Enhanced Progress Tracking", - "Better visibility into your music scanning and download progress", + # Artist Search Enhancements + artist_section = self.create_feature_section( + "🎵 Artist Search Enhancements", + "Better visual feedback and improved navigation for artist discovery", [ - "• Three-progress-bar system for Singles/EPs, Albums, and Overall progress", - "• Per-artist progress tracking that resets for each new artist", - "• Real-time updates during scanning with detailed completion metrics", - "• Smart release categorization (≤3 tracks = Single/EP, ≥4 tracks = Album)", - "• Improved mathematical accuracy for progress calculations" - ] + "• Added watchlist eye indicators (👁️) to artist search results", + "• Green eye icon appears in top-right corner for artists already in watchlist", + "• Real-time updates when artists are added/removed from watchlist", + "• Enhanced horizontal scrolling with mouse wheel support for artist results", + "• Smooth navigation through search results without manual scrollbar dragging" + ], + "Look for the green eye icon (👁️) in artist search results to instantly see which artists you're already tracking!" ) - content_layout.addWidget(progress_section) - - # Performance Improvements - performance_section = self.create_feature_section( - "⚡ Performance Improvements", - "Faster scanning and better resource management", - [ - "• Reduced scan intervals from 60 minutes to 10 minutes", - "• Removed artificial 25-track processing limits", - "• Optimized database queries for better responsiveness", - "• Improved memory management during large scans" - ] - ) - content_layout.addWidget(performance_section) - - # UI/UX Enhancements - ui_section = self.create_feature_section( - "🎨 UI/UX Enhancements", - "Cleaner interface and better user experience", - [ - "• Replaced confusing colored status circles with intuitive icons", - "• Added search functionality for large artist lists", - "• Smart display logic showing last 5 artists when no search active", - "• Removed unnecessary white borders for cleaner appearance", - "• Improved status indicators with meaningful visual feedback" - ] - ) - content_layout.addWidget(ui_section) + content_layout.addWidget(artist_section) scroll_area.setWidget(content_widget) return scroll_area diff --git a/ui/pages/artists.py b/ui/pages/artists.py index 3de64cb2..b22282cb 100644 --- a/ui/pages/artists.py +++ b/ui/pages/artists.py @@ -1167,6 +1167,7 @@ class ArtistResultCard(QFrame): self.artist = artist_match.artist self.setup_ui() self.load_artist_image() + self.check_watchlist_status() def setup_ui(self): self.setFixedSize(200, 280) @@ -1242,6 +1243,23 @@ class ArtistResultCard(QFrame): followers_label.setStyleSheet("color: #b3b3b3; padding: 2px;") followers_label.setAlignment(Qt.AlignmentFlag.AlignCenter) + # Watchlist eye indicator (positioned absolutely in top-right corner) + self.watchlist_indicator = QLabel(self) + self.watchlist_indicator.setText("👁️") + self.watchlist_indicator.setFont(QFont("Arial", 14)) + self.watchlist_indicator.setFixedSize(24, 24) + self.watchlist_indicator.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.watchlist_indicator.setStyleSheet(""" + QLabel { + background: rgba(29, 185, 84, 0.9); + border-radius: 12px; + border: 1px solid rgba(29, 185, 84, 1); + color: white; + } + """) + self.watchlist_indicator.move(168, 8) # Position in top-right corner + self.watchlist_indicator.hide() # Hidden by default + layout.addWidget(self.image_container, 0, Qt.AlignmentFlag.AlignCenter) layout.addWidget(name_label) layout.addWidget(confidence_label) @@ -1290,6 +1308,25 @@ class ArtistResultCard(QFrame): """Handle image load error""" print(f"Failed to load artist image: {error}") + def check_watchlist_status(self): + """Check if this artist is in the watchlist and show eye indicator""" + try: + database = get_database() + is_watching = database.is_artist_in_watchlist(self.artist.id) + + if is_watching: + self.watchlist_indicator.show() + else: + self.watchlist_indicator.hide() + + except Exception as e: + logger.error(f"Error checking watchlist status for artist {self.artist.name}: {e}") + self.watchlist_indicator.hide() + + def refresh_watchlist_status(self): + """Refresh the watchlist indicator (call this when watchlist changes)""" + self.check_watchlist_status() + def mousePressEvent(self, event): """Handle click to select artist""" try: @@ -3455,6 +3492,21 @@ class ArtistsPage(QWidget): self.artist_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.artist_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.artist_scroll.setFixedHeight(320) # Fixed height to accommodate artist cards + + # Enable horizontal scrolling with mouse wheel + def wheelEvent(event): + # Convert vertical wheel scrolling to horizontal scrolling + if event.angleDelta().y() != 0: + horizontal_scroll = self.artist_scroll.horizontalScrollBar() + current_value = horizontal_scroll.value() + # Scroll by artist card width (200px + spacing) + scroll_amount = -event.angleDelta().y() // 120 * 220 # Each wheel step scrolls ~1 card + horizontal_scroll.setValue(current_value + scroll_amount) + event.accept() + else: + QScrollArea.wheelEvent(self.artist_scroll, event) + + self.artist_scroll.wheelEvent = wheelEvent self.artist_scroll.setStyleSheet(""" QScrollArea { border: none; @@ -5122,6 +5174,8 @@ class ArtistsPage(QWidget): self.update_watchlist_button(False) # Emit signal to update dashboard button count self.database_updated_externally.emit() + # Refresh all artist card watchlist indicators + self.refresh_all_artist_card_watchlist_status() if hasattr(self, 'toast_manager') and self.toast_manager: self.toast_manager.success(f"Removed {artist_name} from watchlist") else: @@ -5134,6 +5188,8 @@ class ArtistsPage(QWidget): self.update_watchlist_button(True) # Emit signal to update dashboard button count self.database_updated_externally.emit() + # Refresh all artist card watchlist indicators + self.refresh_all_artist_card_watchlist_status() if hasattr(self, 'toast_manager') and self.toast_manager: self.toast_manager.success(f"Added {artist_name} to watchlist") else: @@ -5145,6 +5201,19 @@ class ArtistsPage(QWidget): if hasattr(self, 'toast_manager') and self.toast_manager: self.toast_manager.error("Error updating watchlist") + def refresh_all_artist_card_watchlist_status(self): + """Refresh watchlist indicators on all visible artist cards""" + try: + # Find all artist cards in the search results layout + for i in range(self.artist_results_layout.count()): + item = self.artist_results_layout.itemAt(i) + if item and item.widget(): + widget = item.widget() + if isinstance(widget, ArtistResultCard): + widget.refresh_watchlist_status() + except Exception as e: + logger.error(f"Error refreshing artist card watchlist status: {e}") + def update_watchlist_button(self, is_watching): """Update watchlist button appearance based on watching status""" if is_watching: diff --git a/ui/sidebar.py b/ui/sidebar.py index b36e0fae..7f01e4cd 100644 --- a/ui/sidebar.py +++ b/ui/sidebar.py @@ -1240,7 +1240,7 @@ class ModernSidebar(QWidget): layout.setSpacing(0) # Version button (clickable) - self.version_button = QPushButton("v.0.5") + self.version_button = QPushButton("v.0.51") self.version_button.setFont(QFont("SF Pro Text", 10, QFont.Weight.Medium)) self.version_button.setCursor(Qt.CursorShape.PointingHandCursor) self.version_button.setStyleSheet("""