Skip to content

Queue Enhancement Features#97

Merged
sozercan merged 14 commits intosozercan:mainfrom
cacuscacus:cacus-new-features
Feb 21, 2026
Merged

Queue Enhancement Features#97
sozercan merged 14 commits intosozercan:mainfrom
cacuscacus:cacus-new-features

Conversation

@cacuscacus
Copy link
Contributor

Pull Request: Queue Enhancement Features

Description

This PR introduces a comprehensive queue enhancement system for Kaset, transforming the basic queue popup into a full-featured playlist management interface with drag-and-drop, undo/redo, persistence, and intelligent metadata enrichment.

Type of Change

  • New feature (non-breaking change that adds functionality)
  • UI/UX improvement

Changes Made

Core Queue Features

  • Added QueueDisplayMode enum with popup/sidepanel modes
  • Created QueueSidePanelView with header, scrollable queue, and footer actions
  • Implemented DraggableTableView for drag-and-drop reordering
  • Added two-finger swipe gesture for removing songs
  • Built queue undo/redo system with history tracking (10 states)
  • Integrated queue persistence using UserDefaults

Queue Metadata Enrichment

  • Implemented background enrichment service that runs every 30 seconds
  • Added playback-time enrichment via fetchSongMetadata() hook
  • Automatically detects and fixes songs with missing artists, titles, or thumbnails
  • Updates queue entries in-place without disrupting playback
  • Persists enriched data to avoid re-fetching on app restart
  • Uses gentle API throttling (100ms between requests)

UI Enhancements

  • Added toggle button in QueueView to switch display modes
  • Created Shuffle, Clear, and Save as Playlist footer actions
  • Enhanced context menus with Play Next, Add to Bottom, Start Radio
  • Added album playback controls (Play, Play Next, Add to Queue) to list views

Technical Improvements

  • Extended PlayerService+Queue.swift with queue management methods
  • Added enrichQueueMetadata() for background metadata updates
  • Extended PlayerService+Library.swift to update queue during playback
  • Added comprehensive unit tests for queue operations
  • Improved song metadata handling with fallback support
  • Enhanced SongActionsHelper with queue management utilities
  • Added undo history limit to 10 states back/forth

Testing

  • Unit tests pass (xcodebuild test -only-testing:KasetTests)
  • Manual testing performed on macOS 26+
  • Drag-and-drop tested with 50+ songs
  • Undo/redo tested across multiple scenarios (up to 10 states)
  • Queue persistence verified across app restarts
  • Metadata enrichment verified with albums that have incomplete data
  • Background enrichment service tested with various queue sizes

Checklist

  • My code follows the project's style guidelines
  • I have run swiftlint --strict && swiftformat .
  • I have added tests that prove my fix/feature works
  • New and existing unit tests pass locally
  • I have updated documentation (new_features_queue_enhancement.md)
  • I have checked for any performance implications
  • My changes generate no new warnings

Additional Notes

  • Queue history is stored in-memory (up to 10 states) - allows extensive undo/redo
  • Side panel width set to 400pt for optimal readability
  • Swipe gesture uses two-finger horizontal swipe (trackpad) to avoid conflicts
  • All queue operations are @MainActor-isolated for thread safety
  • Metadata enrichment prioritizes playback-time updates (immediate) over background checks
  • Enriched data persists across app launches

Summary of Features Implemented

1. Queue Display Mode Toggle

  • Added QueueDisplayMode enum (popup vs edit/side panel)
  • Toggle between compact popup and full edit side panel
  • Persists user preference in UserDefaults

2. Queue Side Panel View (QueueSidePanelView.swift)

  • Full-width side panel with material background
  • Header with song count and collapse button
  • Footer with Undo, Redo, Shuffle, Clear actions
  • Integrated with MainWindow overlay system

3. Drag & Drop Reordering

  • Custom DraggableTableView implementation
  • Two-finger drag to reorder songs
  • Visual feedback during drag operations
  • Smart index handling with reorderQueue(from:to:)

4. Swipe to Remove

  • Two-finger horizontal swipe gesture
  • Real-time sliding feedback
  • Threshold-based commit/cancel logic
  • Smooth removal animations

5. Queue Undo/Redo System

  • In-memory history tracking (up to 10 states)
  • Record states before queue modifications
  • Restore previous queue functionality
  • Works across play, clear, and shuffle operations

6. Queue Metadata Enrichment

  • Background service checks queue every 30 seconds
  • Playback-time enrichment when songs are played
  • Detects missing artists, titles, or thumbnails
  • Updates queue in-place and persists changes
  • API-friendly throttling (100ms between requests)

7. Enhanced Context Menus (SongActionsHelper.swift)

  • "Play Next" - Insert song after current track
  • "Add to Bottom of Queue" - Append to queue end
  • "Start Radio" from queue context menu
  • Integrated across all song list views

8. Queue Persistence

  • Save/restore queue across app launches
  • UserDefaults-based storage
  • Maintains current index and queue order
  • Persists enriched metadata

9. Album Playback Controls

  • Play album button
  • Play album next (insert after current)
  • Add album to queue (append)
  • Added to HomeView, SearchView, PlaylistDetailView

10. Additional Improvements

  • Enhanced PlayerService+Queue.swift with queue management
  • Added metadata enrichment methods
  • Increased undo history from 3 to 10 states
  • Improved song metadata handling with fallbacks

Statistics

  • Branch: cacus-new-features
  • Commits ahead of main: 9 commits
  • Files changed: 21 files
  • Lines added: +3,400
  • Lines removed: -150

Key Files Added/Modified

  • Core/Models/QueueDisplayMode.swift (NEW)
  • Core/Services/Player/PlayerService+Queue.swift (+200 lines)
  • Core/Services/Player/PlayerService.swift (+15 lines)
  • Core/Services/Player/PlayerService+Library.swift (+20 lines)
  • Views/macOS/QueueSidePanelView.swift (NEW)
  • Views/macOS/SharedViews/SongActionsHelper.swift (+500 lines)
  • Views/macOS/QueueView.swift (+13 lines)
  • Views/macOS/HomeView.swift (+39 lines)
  • Views/macOS/SearchView.swift (+39 lines)
  • Views/macOS/PlaylistDetailView.swift (+137 lines)
  • docs/new_features_queue_enhancement.md (NEW)

- Added `QueueDisplayMode` enum to manage queue display modes (popup and side panel).
- Integrated queue display mode into `PlayerService` with persistence in UserDefaults.
- Implemented toggle functionality for switching between display modes.
- Enhanced `QueueView` and `QueueSidePanelView` to support the new display modes.
- Added `reorderQueue(from:to:)` method in `PlayerService` for drag-and-drop reordering of queue items.
- Updated tests to cover new reordering functionality and queue display mode changes.
…anelView

- Updated the logic for determining the destination row during drag-and-drop operations to use the row directly, as the move API handles index adjustments.
- Removed unnecessary calculations for moving items up or down in the queue.
- Replaced GlassEffectContainer with a regular material background to improve drag-and-drop performance.
- Increased the width of the QueueSidePanelView and its table column to accommodate layout changes.
- Introduced a custom DraggableTableView to provide visual feedback during drag-and-drop operations.
- Updated QueueTableCellView to refine layout and improve accessibility features.
…o queue

- Added functionality to save and restore the current song queue using UserDefaults, allowing for persistence across application launches.
- Implemented `AddToQueueContextMenu` for adding songs to the queue from various views, enhancing user experience.
- Updated multiple views (ArtistDetailView, HomeView, LikedMusicView, PlaylistDetailView, SearchView, TopSongsView, FavoritesSection) to include the new context menu for queue management.
- Integrated new buttons in HomeView and PlaylistDetailView for playing albums and adding songs to the queue (Play, Play Next, Add to Queue).
- Updated tracksView and trackRow methods to support fallback album and artist information for better handling of song metadata.
- Improved queue clearing functionality in QueueSidePanelView to ensure playback stops before clearing the queue.
- Enhanced SongActionsHelper to include fallback options for artists and albums when adding songs to the queue.
- Implemented new buttons for playing albums, adding albums to the queue next, and adding albums to the end of the queue.
- Enhanced user interaction with album management through the SongActionsHelper for improved playback control.
…ement

- Added in-memory undo/redo history for the song queue, allowing users to revert and reapply changes to the queue state.
- Introduced methods for recording queue states before modifications, enabling better management of queue actions.
- Enhanced queue management methods to support undo/redo operations, improving user experience during playback adjustments.
- Updated context menu in QueueSidePanelView to include a "Start Radio" option for enhanced song playback options.
- Reset row view properties after removal animation to prevent misalignment issues.
- Simplified swipe removal logic by removing unnecessary logging and checks.
- Enhanced layout consistency in QueueTableCellView by ensuring row views fill their frames and adjusting content hugging/compression priorities.
- Implemented real-time row sliding feedback during two-finger horizontal swipes for improved user interaction.
- Introduced thresholds for swipe commit and removal to refine the swipe-to-remove experience.
- Added logic to animate row return on cancellation and handle removal with visual feedback.
- Updated swipe handling to ensure smoother transitions and prevent misalignment after removal.
- Added a background service to periodically enrich song metadata in the queue, ensuring complete information is displayed without additional API calls.
- Enhanced queue management by updating songs with missing metadata and persisting changes.
- Increased the undo/redo history capacity from 3 to 10 states for improved user experience in queue management.
…hensive tests for PlayerService queue operations

- Changed the visibility of the identifySongsNeedingEnrichment method from private to public to allow external access for metadata enrichment.
- Introduced a new test suite for PlayerService queue operations, covering reordering, undo/redo functionality, and queue persistence.
- Enhanced MockYTMusicClient to track song retrieval calls, improving test reliability and coverage.
@paranoidPhantom
Copy link

Was just going to submit a similar PR for "Play next" context menu option, but found this

- Split SearchView contextMenuItems into per-type helper methods (function_body_length)
- Extract scrollWheel phases into helper methods (cyclomatic_complexity, function_body_length)
- Move QueueTableCellView and WaveformView to separate file (file_length)
- Remove unused favoritesManager param, reduce param count (function_parameter_count)
- Extract PlaylistDetailView header buttons into helper (function_body_length)
- Use Data(_:) initializer in tests (non_optional_string_data_conversion)
- Apply swiftformat auto-formatting
Copy link
Owner

@sozercan sozercan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! lgtm

@sozercan sozercan merged commit d8ff82e into sozercan:main Feb 21, 2026
6 checks passed
sozercan added a commit that referenced this pull request Feb 23, 2026
NotificationService was stored as @State in KasetApp but never
referenced in the view body. After the WindowGroup → Window change
in v0.7.0 (#97), SwiftUI stopped retaining the unused @State,
causing the observation task to be cancelled on dealloc.

Fix: reference notificationService in the body so SwiftUI tracks it.
Add NotificationServiceTests with 8 tests for observation lifecycle,
track change detection, and deduplication.
@sozercan sozercan added this to the v0.7.0 milestone Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants