Skip to content

Commit

Permalink
Merge pull request #421 from hasezoey/alphanumericSort
Browse files Browse the repository at this point in the history
Alphanumeric sort for Music-Library & Database
  • Loading branch information
tramhao authored Feb 3, 2025
2 parents bccd90c + 2b5f6f1 commit 0a4764f
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- Fix(tui): change Theme preview to not reset to index 0 each preview.
- Fix(tui): not having the current theme selected when entering Theme preview tab.
- Fix(tui): actually report any errors when adding to the playlist. (Like "invalid file type")
- Fix(tui): sort Music-Library content Alphanumerically.

### [V0.9.1]
- Released on: August 21, 2024.
Expand Down
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ walkdir = "2.5"
wildmatch = "2.4"
ytd-rs = { version = "0.1", features = ["yt-dlp"] }
futures = "0.3"
alphanumeric-sort = "1.5"
# transistive dependency for some packages (like libsqlite), manually specified to upgrade the version, see https://github.com/rusqlite/rusqlite/issues/1543
cc = "1.2"

Expand Down
1 change: 1 addition & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ tokio.workspace = true
tokio-util = { workspace = true, features = ["rt"] }
tonic.workspace = true
prost.workspace = true
alphanumeric-sort.workspace = true

[build-dependencies]
cc.workspace = true
Expand Down
18 changes: 14 additions & 4 deletions lib/src/library_db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,22 @@ impl DataBase {
let conn = self.conn.lock();
let mut stmt = conn.prepare(&search_str)?;

let mut vec_records: Vec<TrackDB> = stmt
let mut vec_records: Vec<(String, TrackDB)> = stmt
.query_map([criteria_val], TrackDB::try_from_row_named)?
.flatten()
.map(|v| (get_pin_yin(&v.name), v))
.collect();

// Left for debug
// error!("criteria_val: {}", criteria_val);
// error!("criteria: {}", criteria);
// error!("vec: {:?}", vec_records);

vec_records.sort_by_cached_key(|k| get_pin_yin(&k.name));
// TODO: if SearchCriteria is "Album", maybe we should sort by album track index
// TODO: should we really do the search here in the libary?
vec_records.sort_by(|a, b| alphanumeric_sort::compare_str(&a.0, &b.0));

let vec_records = vec_records.into_iter().map(|v| v.1).collect();
Ok(vec_records)
}

Expand All @@ -266,15 +271,20 @@ impl DataBase {
let conn = self.conn.lock();
let mut stmt = conn.prepare(&search_str)?;

let mut vec: Vec<String> = stmt
// tuple.0 is the sort key, and tuple.1 is the actual value
let mut vec: Vec<(String, String)> = stmt
.query_map([], |row| {
let criteria: String = row.get(0)?;
Ok(criteria)
})?
.flatten()
.map(|v| (get_pin_yin(&v), v))
.collect();

vec.sort_by_cached_key(|k| get_pin_yin(k));
// TODO: should we really do the search here in the libary?
vec.sort_by(|a, b| alphanumeric_sort::compare_str(&a.0, &b.0));

let vec = vec.into_iter().map(|v| v.1).collect();
Ok(vec)
}

Expand Down
1 change: 1 addition & 0 deletions tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ tokio-stream.workspace = true
futures.workspace = true
reqwest.workspace = true
parking_lot.workspace = true
alphanumeric-sort.workspace = true


[features]
Expand Down
23 changes: 13 additions & 10 deletions tui/src/ui/components/music_library.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::ui::{Id, LIMsg, Model, Msg, TEMsg, YSMsg};
use crate::utils::get_pin_yin;
use anyhow::{bail, Context, Result};
use std::fs::{remove_dir_all, remove_file, rename};
use std::fs::{remove_dir_all, remove_file, rename, DirEntry};
use std::path::{Path, PathBuf};
use termusiclib::config::v2::server::config_extra::ServerConfigVersionedDefaulted;
use termusiclib::config::v2::server::ScanDepth;
Expand Down Expand Up @@ -266,17 +266,16 @@ impl Model {

if depth > 0 && p.is_dir() {
if let Ok(paths) = std::fs::read_dir(p) {
let mut paths: Vec<_> = paths
let mut paths: Vec<(String, PathBuf)> = paths
.filter_map(std::result::Result::ok)
.filter(|p| !p.file_name().to_string_lossy().starts_with('.'))
.map(|v| (get_pin_yin(&v.file_name().to_string_lossy()), v.path()))
.collect();

paths.sort_by_cached_key(|k| get_pin_yin(&k.file_name().to_string_lossy()));
paths.sort_by(|a, b| alphanumeric_sort::compare_str(&a.0, &b.0));

for p in paths {
node.add_child(Self::library_dir_tree(
p.path().as_path(),
ScanDepth::Limited(depth - 1),
));
node.add_child(Self::library_dir_tree(&p.1, ScanDepth::Limited(depth - 1)));
}
}
}
Expand All @@ -286,10 +285,14 @@ impl Model {
let mut children: Vec<String> = vec![];
if p.is_dir() {
if let Ok(paths) = std::fs::read_dir(p) {
let mut paths: Vec<_> = paths.filter_map(std::result::Result::ok).collect();
let mut paths: Vec<(String, DirEntry)> = paths
.filter_map(std::result::Result::ok)
.map(|v| (get_pin_yin(&v.file_name().to_string_lossy()), v))
.collect();

paths.sort_by_cached_key(|k| get_pin_yin(&k.file_name().to_string_lossy()));
for p in paths {
paths.sort_by(|a, b| alphanumeric_sort::compare_str(&a.0, &b.0));

for (_, p) in paths {
if !p.path().is_dir() {
children.push(String::from(p.path().to_string_lossy()));
}
Expand Down

0 comments on commit 0a4764f

Please sign in to comment.