Sorting improvements

This commit is contained in:
Antoine Gersant 2024-08-10 10:57:07 -07:00
parent 39407c6551
commit 4112c7d79d
3 changed files with 75 additions and 14 deletions
src
app/index
server/dto

View file

@ -1,4 +1,5 @@
use std::{
cmp::Ordering,
collections::{BTreeSet, HashMap},
ffi::OsStr,
hash::Hash,
@ -9,6 +10,7 @@ use lasso2::{Rodeo, RodeoReader};
use serde::{Deserialize, Serialize};
use tinyvec::TinyVec;
use trie_rs::{Trie, TrieBuilder};
use unicase::UniCase;
use crate::app::index::{
storage::{self, PathKey},
@ -67,7 +69,17 @@ impl Browser {
})
.collect::<Vec<_>>();
files.sort();
files.sort_by(|a, b| {
let (a, b) = match (a, b) {
(File::Directory(_), File::Song(_)) => return Ordering::Less,
(File::Song(_), File::Directory(_)) => return Ordering::Greater,
(File::Directory(a), File::Directory(b)) => (a, b),
(File::Song(a), File::Song(b)) => (a, b),
};
let a = UniCase::new(a.as_os_str().to_string_lossy());
let b = UniCase::new(b.as_os_str().to_string_lossy());
a.cmp(&b)
});
Ok(files)
}
@ -100,7 +112,11 @@ impl Browser {
})
.collect::<Vec<_>>();
files.sort();
files.sort_by(|a, b| {
let a = UniCase::new(a.as_os_str().to_string_lossy());
let b = UniCase::new(b.as_os_str().to_string_lossy());
a.cmp(&b)
});
Ok(files)
}
@ -234,6 +250,26 @@ mod test {
);
}
#[test]
fn browse_entries_are_sorted() {
let (browser, strings) = setup_test(HashSet::from([
PathBuf::from_iter(["Ott", "Mir.mp3"]),
PathBuf::from("Helios.mp3"),
PathBuf::from("asura.mp3"),
]));
let files = browser.browse(&strings, PathBuf::new()).unwrap();
assert_eq!(
files,
[
File::Directory(PathBuf::from("Ott")),
File::Song(PathBuf::from("asura.mp3")),
File::Song(PathBuf::from("Helios.mp3")),
]
);
}
#[test]
fn can_flatten_root() {
let song_a = PathBuf::from_iter(["Music", "Electronic", "Papua New Guinea.mp3"]);
@ -269,6 +305,26 @@ mod test {
assert_eq!(files, [song_a, song_b]);
}
#[test]
fn flatten_entries_are_sorted() {
let (browser, strings) = setup_test(HashSet::from([
PathBuf::from_iter(["Ott", "Mir.mp3"]),
PathBuf::from("Helios.mp3"),
PathBuf::from("asura.mp3"),
]));
let files = browser.flatten(&strings, PathBuf::new()).unwrap();
assert_eq!(
files,
[
PathBuf::from("asura.mp3"),
PathBuf::from("Helios.mp3"),
PathBuf::from_iter(["Ott", "Mir.mp3"]),
]
);
}
#[test]
fn can_flatten_directory_with_shared_prefix() {
let directory_a = PathBuf::from_iter(["Music", "Therion", "Leviathan II"]);

View file

@ -1,6 +1,5 @@
use std::{
borrow::BorrowMut,
cmp::Ordering,
collections::{HashMap, HashSet},
path::PathBuf,
};
@ -17,7 +16,7 @@ use super::storage::fetch_song;
#[derive(Debug, Default, PartialEq, Eq)]
pub struct ArtistHeader {
pub name: Option<String>,
pub name: Option<UniCase<String>>,
pub num_albums: u32,
}
@ -74,12 +73,7 @@ impl Collection {
.filter(|a| a.albums.len() > 0 || a.featured_on.len() > 1)
.map(|a| make_artist_header(a, strings))
.collect::<Vec<_>>();
artists.sort_by(|a, b| match (&a.name, &b.name) {
(Some(a), Some(b)) => UniCase::new(a).cmp(&UniCase::new(b)),
(None, None) => Ordering::Equal,
(None, Some(_)) => Ordering::Less,
(Some(_), None) => Ordering::Greater,
});
artists.sort_by(|a, b| a.name.cmp(&b.name));
artists
}
@ -175,7 +169,9 @@ impl Collection {
fn make_artist_header(artist: &storage::Artist, strings: &RodeoReader) -> ArtistHeader {
ArtistHeader {
name: artist.name.map(|n| strings.resolve(&n).to_owned()),
name: artist
.name
.map(|n| UniCase::new(strings.resolve(&n).to_owned())),
num_albums: artist.albums.len() as u32 + artist.featured_on.len() as u32,
}
}
@ -326,7 +322,13 @@ mod test {
.map(|a| a.name.unwrap())
.collect::<Vec<_>>();
assert_eq!(artists, vec!["FSOL".to_owned(), "Stratovarius".to_owned()]);
assert_eq!(
artists,
vec![
UniCase::new("FSOL".to_owned()),
UniCase::new("Stratovarius".to_owned())
]
);
}
#[test]
@ -354,7 +356,10 @@ mod test {
assert_eq!(
artists,
vec!["hammerfall".to_owned(), "Heavenly".to_owned()]
vec![
UniCase::new("hammerfall".to_owned()),
UniCase::new("Heavenly".to_owned())
]
);
}

View file

@ -315,7 +315,7 @@ pub struct ArtistHeader {
impl From<index::ArtistHeader> for ArtistHeader {
fn from(a: index::ArtistHeader) -> Self {
Self {
name: a.name,
name: a.name.map(|s| s.into_inner()),
num_albums: a.num_albums,
}
}