Sorting improvements
This commit is contained in:
parent
39407c6551
commit
4112c7d79d
3 changed files with 75 additions and 14 deletions
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
collections::{BTreeSet, HashMap},
|
collections::{BTreeSet, HashMap},
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
@ -9,6 +10,7 @@ use lasso2::{Rodeo, RodeoReader};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tinyvec::TinyVec;
|
use tinyvec::TinyVec;
|
||||||
use trie_rs::{Trie, TrieBuilder};
|
use trie_rs::{Trie, TrieBuilder};
|
||||||
|
use unicase::UniCase;
|
||||||
|
|
||||||
use crate::app::index::{
|
use crate::app::index::{
|
||||||
storage::{self, PathKey},
|
storage::{self, PathKey},
|
||||||
|
@ -67,7 +69,17 @@ impl Browser {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.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)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +112,11 @@ impl Browser {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.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)
|
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]
|
#[test]
|
||||||
fn can_flatten_root() {
|
fn can_flatten_root() {
|
||||||
let song_a = PathBuf::from_iter(["Music", "Electronic", "Papua New Guinea.mp3"]);
|
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]);
|
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]
|
#[test]
|
||||||
fn can_flatten_directory_with_shared_prefix() {
|
fn can_flatten_directory_with_shared_prefix() {
|
||||||
let directory_a = PathBuf::from_iter(["Music", "Therion", "Leviathan II"]);
|
let directory_a = PathBuf::from_iter(["Music", "Therion", "Leviathan II"]);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
borrow::BorrowMut,
|
borrow::BorrowMut,
|
||||||
cmp::Ordering,
|
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
@ -17,7 +16,7 @@ use super::storage::fetch_song;
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub struct ArtistHeader {
|
pub struct ArtistHeader {
|
||||||
pub name: Option<String>,
|
pub name: Option<UniCase<String>>,
|
||||||
pub num_albums: u32,
|
pub num_albums: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,12 +73,7 @@ impl Collection {
|
||||||
.filter(|a| a.albums.len() > 0 || a.featured_on.len() > 1)
|
.filter(|a| a.albums.len() > 0 || a.featured_on.len() > 1)
|
||||||
.map(|a| make_artist_header(a, strings))
|
.map(|a| make_artist_header(a, strings))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
artists.sort_by(|a, b| match (&a.name, &b.name) {
|
artists.sort_by(|a, b| a.name.cmp(&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
|
artists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +169,9 @@ impl Collection {
|
||||||
|
|
||||||
fn make_artist_header(artist: &storage::Artist, strings: &RodeoReader) -> ArtistHeader {
|
fn make_artist_header(artist: &storage::Artist, strings: &RodeoReader) -> ArtistHeader {
|
||||||
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,
|
num_albums: artist.albums.len() as u32 + artist.featured_on.len() as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,7 +322,13 @@ mod test {
|
||||||
.map(|a| a.name.unwrap())
|
.map(|a| a.name.unwrap())
|
||||||
.collect::<Vec<_>>();
|
.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]
|
#[test]
|
||||||
|
@ -354,7 +356,10 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
artists,
|
artists,
|
||||||
vec!["hammerfall".to_owned(), "Heavenly".to_owned()]
|
vec![
|
||||||
|
UniCase::new("hammerfall".to_owned()),
|
||||||
|
UniCase::new("Heavenly".to_owned())
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ pub struct ArtistHeader {
|
||||||
impl From<index::ArtistHeader> for ArtistHeader {
|
impl From<index::ArtistHeader> for ArtistHeader {
|
||||||
fn from(a: index::ArtistHeader) -> Self {
|
fn from(a: index::ArtistHeader) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: a.name,
|
name: a.name.map(|s| s.into_inner()),
|
||||||
num_albums: a.num_albums,
|
num_albums: a.num_albums,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue