Fix playlist track ordering to respect insertion order
- Add PlaylistLocalTrack struct with playlist_position field - Add playlist_get_local_tracks_with_position command - Update PlaylistDetailView to merge tracks by position instead of appending local tracks at the end - Update PlaylistModal to calculate correct position when adding local tracks (total count = qobuz + existing local) - Local tracks now appear in the order they were added, interleaved with Qobuz tracks
This commit is contained in:
1 parent
24c9df3bce
commit
16486e4591
6 files changed
+136
-14
No files matched your search
@@ -387,6 +387,7 @@ pub fn run() {
|
||||
library::commands::playlist_add_local_track,
|
||||
library::commands::playlist_remove_local_track,
|
||||
library::commands::playlist_get_local_tracks,
|
||||
library::commands::playlist_get_local_tracks_with_position,
|
||||
library::commands::playlist_get_all_local_track_counts,
|
||||
library::commands::playlist_clear_local_tracks,
|
||||
// Playlist management commands
|
||||
|
||||
@@ -1031,6 +1031,19 @@ pub async fn playlist_get_local_tracks(
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get all local tracks in a playlist with their positions (for mixed ordering)
|
||||
#[tauri::command]
|
||||
pub async fn playlist_get_local_tracks_with_position(
|
||||
playlist_id: u64,
|
||||
state: State<'_, LibraryState>,
|
||||
) -> Result<Vec<crate::library::PlaylistLocalTrack>, String> {
|
||||
log::info!("Command: playlist_get_local_tracks_with_position {}", playlist_id);
|
||||
|
||||
let db = state.db.lock().await;
|
||||
db.get_playlist_local_tracks_with_position(playlist_id)
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get local track counts for all playlists
|
||||
#[tauri::command]
|
||||
pub async fn playlist_get_all_local_track_counts(
|
||||
|
||||
@@ -1550,6 +1550,56 @@ impl LibraryDatabase {
|
||||
.map_err(|e| LibraryError::Database(format!("Failed to collect playlist local tracks: {}", e)))
|
||||
}
|
||||
|
||||
/// Get all local tracks in a playlist with their positions (for mixed ordering)
|
||||
pub fn get_playlist_local_tracks_with_position(&self, qobuz_playlist_id: u64) -> Result<Vec<crate::library::PlaylistLocalTrack>, LibraryError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
"SELECT t.id, t.file_path, t.title, t.artist, t.album, t.album_artist,
|
||||
t.album_group_key, t.album_group_title, t.track_number, t.disc_number,
|
||||
t.year, t.genre, t.duration_secs, t.format, t.bit_depth, t.sample_rate,
|
||||
t.channels, t.file_size_bytes, t.cue_file_path, t.cue_start_secs,
|
||||
t.cue_end_secs, t.artwork_path, t.last_modified, t.indexed_at, plt.position
|
||||
FROM playlist_local_tracks plt
|
||||
JOIN local_tracks t ON plt.local_track_id = t.id
|
||||
WHERE plt.qobuz_playlist_id = ?1
|
||||
ORDER BY plt.position ASC"
|
||||
).map_err(|e| LibraryError::Database(format!("Failed to prepare statement: {}", e)))?;
|
||||
|
||||
let tracks = stmt.query_map(params![qobuz_playlist_id as i64], |row| {
|
||||
Ok(crate::library::PlaylistLocalTrack {
|
||||
track: LocalTrack {
|
||||
id: row.get(0)?,
|
||||
file_path: row.get(1)?,
|
||||
title: row.get(2)?,
|
||||
artist: row.get(3)?,
|
||||
album: row.get(4)?,
|
||||
album_artist: row.get(5)?,
|
||||
album_group_key: row.get::<_, Option<String>>(6)?.unwrap_or_default(),
|
||||
album_group_title: row.get::<_, Option<String>>(7)?.unwrap_or_default(),
|
||||
track_number: row.get(8)?,
|
||||
disc_number: row.get(9)?,
|
||||
year: row.get(10)?,
|
||||
genre: row.get(11)?,
|
||||
duration_secs: row.get(12)?,
|
||||
format: Self::parse_format(&row.get::<_, String>(13)?),
|
||||
bit_depth: row.get(14)?,
|
||||
sample_rate: row.get(15)?,
|
||||
channels: row.get(16)?,
|
||||
file_size_bytes: row.get(17)?,
|
||||
cue_file_path: row.get(18)?,
|
||||
cue_start_secs: row.get(19)?,
|
||||
cue_end_secs: row.get(20)?,
|
||||
artwork_path: row.get(21)?,
|
||||
last_modified: row.get(22)?,
|
||||
indexed_at: row.get(23)?,
|
||||
},
|
||||
playlist_position: row.get(24)?,
|
||||
})
|
||||
}).map_err(|e| LibraryError::Database(format!("Failed to query playlist local tracks with position: {}", e)))?;
|
||||
|
||||
tracks.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| LibraryError::Database(format!("Failed to collect playlist local tracks with position: {}", e)))
|
||||
}
|
||||
|
||||
/// Get count of local tracks in a playlist
|
||||
pub fn get_playlist_local_track_count(&self, qobuz_playlist_id: u64) -> Result<u32, LibraryError> {
|
||||
let count: u32 = self.conn.query_row(
|
||||
|
||||
@@ -104,6 +104,15 @@ impl Default for LocalTrack {
|
||||
}
|
||||
}
|
||||
|
||||
/// A local track within a playlist, including its position
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PlaylistLocalTrack {
|
||||
#[serde(flatten)]
|
||||
pub track: LocalTrack,
|
||||
/// Position in the combined playlist (Qobuz + local tracks)
|
||||
pub playlist_position: i32,
|
||||
}
|
||||
|
||||
/// An album aggregated from local tracks
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LocalAlbum {
|
||||
|
||||
Reference in new issue
Block a user