···377377378378// These are used to give each playlist entry an ID. This is for example helpful to keep track of a user's selection. These IDs are unique across the entire library, so that it works for folders folders.
379379pub type ItemId = u32;
380380+/// Track IDs indexed by item IDs
380381pub static TRACK_ID_MAP: RwLock<Vec<String>> = RwLock::new(Vec::new());
381382382383pub fn new_item_ids_from_track_ids(track_ids: &[TrackID]) -> Vec<ItemId> {
···400401 .iter()
401402 .map(|playlist_item_id| playlist_track_id_map[*playlist_item_id as usize].clone())
402403 .collect()
404404+}
405405+406406+pub fn get_track_id_from_item_id(playlist_item_id: ItemId) -> TrackID {
407407+ let playlist_track_id_map = TRACK_ID_MAP.read().unwrap();
408408+ playlist_track_id_map[playlist_item_id as usize].clone()
403409}
404410405411#[derive(Serialize, Deserialize, Clone, Debug)]
+12-7
src-native/sort.rs
···33use crate::page::TracksPageOptions;
44use crate::playlists::get_tracklist_item_ids;
55use alphanumeric_sort::compare_str;
66-use anyhow::Result;
66+use anyhow::{Context, Result};
77use std::cmp::Ordering;
88use std::time::Instant;
99···9797 let id_map = TRACK_ID_MAP.read().unwrap();
9898 let tracks = library.get_tracks();
9999100100- let mut items: Vec<_> = get_tracklist_item_ids(library, &options.playlist_id)?
100100+ let items: Result<Vec<SortItem>> = get_tracklist_item_ids(library, &options.playlist_id)?
101101 .into_iter()
102102- .map(|id| SortItem {
103103- item_id: id,
104104- track: tracks
105105- .get(&id_map[id as usize])
106106- .expect("Track ID non-existant"),
102102+ .enumerate()
103103+ .map(|(i, id)| {
104104+ Ok(SortItem {
105105+ item_id: id,
106106+ track: tracks.get(&id_map[id as usize]).context(format!(
107107+ "Track {i} ({}) does not exist",
108108+ id_map[id as usize]
109109+ ))?,
110110+ })
107111 })
108112 .collect();
113113+ let mut items = items?;
109114 let item_count = items.len();
110115111116 if options.sort_key == "index" {