feat(slint): add-to-playlist duplicate modal + playlist importer port

Add-to-playlist (Slices 0-3):
- qbz-core: check_playlist_duplicates + pure compute_playlist_duplicates
  (reuses qbz_models::PlaylistDuplicateResult) + unit tests.
- PlaylistDuplicateConfirmModal (Add all / Add new only / Cancel); the
  duplicate check runs on the Qobuz->Qobuz picker branch only (local/Plex
  add directly, mirroring Tauri); the track-id Vec lives Rust-side in a
  stash, never in Slint.
- Inline create-and-add in the picker (online create_playlist, offline ->
  local playlist per D8) + client-side filter (Slint 1.16 has no string
  contains, routed through a Rust callback) + success toasts.

Playlist importer (1:1 Tauri port):
- New headless crate qbz-playlist-import (Spotify/Apple/Tidal/Deezer
  scrapers, Qobuz matcher, importer, progress sink, shared http client;
  copy-not-move from src-tauri, zero tauri deps; 40 unit tests green).
- PlaylistImportModal (two-step fetch-preview -> import with live progress
  bar / log / summary) + controller + sidebar PLAYLISTS menu entry point.

Reco logging staged behind TODO(reco-v1) markers (golden rule: playlist
recommendations ship in Slint v1 once the reco engine is extracted to a
shared crate).

cc
This commit is contained in:
vicrodh committed 2026-06-11 22:03:46 -06:00
1 parent 999ded11ff
commit 3689a5fda8
33 files changed
+5664 -129

No files matched your search

+16
View File
@@ -5421,6 +5421,21 @@ dependencies = [
"tokio-stream",
]
[[package]]
name = "qbz-playlist-import"
version = "0.1.0"
dependencies = [
"futures-util",
"log",
"qbz-models",
"qbz-qobuz",
"reqwest",
"serde",
"serde_json",
"thiserror 2.0.18",
"tokio",
]
[[package]]
name = "qbz-plex"
version = "0.1.0"
@@ -5513,6 +5528,7 @@ dependencies = [
"qbz-models",
"qbz-offline-cache",
"qbz-player",
"qbz-playlist-import",
"qbz-plex",
"qbz-qobuz",
"qconnect-app",