Add sorting

This commit is contained in:
Mikko Ahlroth 2023-11-13 21:43:08 +02:00
parent ee70f6742c
commit ccecb20aea
10 changed files with 105 additions and 5 deletions

View file

@ -1,7 +1,12 @@
import gleam/list
import gleam/string
import gleam/int
import elekf/utils/order
import elekf/library.{type Library}
import elekf/library/album.{type Album}
const year_sorters = [year_compare, name_compare]
/// Get the individual tracks in an album.
pub fn get_tracks(library: Library, album: Album) {
list.map(
@ -9,3 +14,21 @@ pub fn get_tracks(library: Library, album: Album) {
fn(track_id) { #(track_id, library.assert_track(library, track_id)) },
)
}
/// Sort given albums by their lowercased names.
pub fn sort_by_name(a: Album, b: Album) {
name_compare(a, b)
}
/// Sort given albums by their publishing year first, then lowercased names.
pub fn sort_by_year(a: Album, b: Album) {
order.compare_by_multiple(year_sorters, a, b)
}
fn name_compare(a: Album, b: Album) {
string.compare(a.name_lower, b.name_lower)
}
fn year_compare(a: Album, b: Album) {
int.compare(a.year, b.year)
}

View file

@ -0,0 +1,7 @@
import gleam/string
import elekf/library/artist.{type Artist}
/// Sort given artists by their lowercased names.
pub fn sort_by_name(a: Artist, b: Artist) {
string.compare(a.name_lower, b.name_lower)
}

View file

@ -0,0 +1,24 @@
import gleam/string
import gleam/int
import elekf/utils/order
import elekf/library/track.{type Track}
const track_number_sorters = [order_compare, name_compare]
/// Sort given tracks by their lowercased names.
pub fn sort_by_name(a: Track, b: Track) {
name_compare(a, b)
}
/// Sort given tracks by their track number first, lowercased title second.
pub fn sort_by_track_number(a: Track, b: Track) {
order.compare_by_multiple(track_number_sorters, a, b)
}
fn order_compare(a: Track, b: Track) {
int.compare(a.number, b.number)
}
fn name_compare(a: Track, b: Track) {
string.compare(a.title_lower, b.title_lower)
}

View file

@ -0,0 +1,21 @@
import gleam/order
import gleam/list
/// A function that sorts two values.
pub type Sorter(a) =
fn(a, a) -> order.Order
/// Compare two values by using multiple sorters. The comparison will stop after
/// the first sorter that returns something other than `order.Eq`.
pub fn compare_by_multiple(sorters: List(Sorter(a)), a: a, b: a) {
list.fold_until(
sorters,
order.Eq,
fn(prev, sorter) {
case prev {
order.Eq -> list.Continue(sorter(a, b))
other -> list.Stop(other)
}
},
)
}

View file

@ -12,6 +12,7 @@ import lustre/element.{text}
import lustre/element/html.{div, h3}
import lustre/attribute
import lustre/event
import elekf/utils/order.{type Sorter} as order_utils
import elekf/library.{type Library}
import elekf/library/track.{type Track}
import elekf/library/artist.{type Artist}
@ -78,6 +79,7 @@ pub type Model(a) {
data: List(LibraryItem(a)),
data_getter: DataGetter(a),
shuffler: Shuffler(a),
sorter: Sorter(a),
search: search.Model,
settings: option.Option(common.Settings),
)
@ -97,11 +99,12 @@ pub fn register(
data_getter: DataGetter(a),
item_view: ItemView(a),
shuffler: Shuffler(a),
sorter: Sorter(a),
search_filter: SearchFilter(a),
) {
lustre.component(
name,
fn() { init(library.empty(), data_getter, shuffler) },
fn() { init(library.empty(), data_getter, shuffler, sorter) },
update,
generate_view(item_view, search_filter),
generic_attributes(),
@ -134,13 +137,14 @@ pub fn render(
)
}
pub fn init(library, data_getter, shuffler) {
pub fn init(library, data_getter, shuffler, sorter) {
#(
Model(
library,
data_getter(library),
data_getter,
shuffler,
sorter,
search.init(),
option.None,
),
@ -151,7 +155,13 @@ pub fn init(library, data_getter, shuffler) {
pub fn update(model, msg) {
case msg {
LibraryUpdated(library) -> #(
Model(..model, library: library, data: model.data_getter(library)),
Model(
..model,
library: library,
data: library
|> model.data_getter()
|> list.sort(fn(a, b) { model.sorter(a.1, b.1) }),
),
effect.none(),
)
SettingsUpdated(settings) -> #(

View file

@ -11,6 +11,7 @@ import elekf/library.{type Library}
import elekf/library/album.{type Album}
import elekf/library/track.{type Track}
import elekf/library/album_utils
import elekf/library/track_utils
import elekf/web/components/library_view.{AlbumExpandToggled}
import elekf/web/components/library_item.{type LibraryItem}
import elekf/web/components/library_views/track_item
@ -94,6 +95,9 @@ pub fn view(
}
pub fn view_tracks(library: Library, tracks: List(LibraryItem(Track))) {
let tracks =
list.sort(tracks, fn(a, b) { track_utils.sort_by_track_number(a.1, b.1) })
div(
[
attribute.class(

View file

@ -58,7 +58,12 @@ pub fn render(
fn init() {
let #(lib_m, lib_e) =
library_view.init(library.empty(), data_getter, shuffler)
library_view.init(
library.empty(),
data_getter,
shuffler,
album_utils.sort_by_name,
)
#(
Model(library_view: lib_m, expanded_album: library.invalid_id),

View file

@ -11,6 +11,7 @@ import lustre/attribute
import lustre/event
import elekf/library.{type Library}
import elekf/library/artist.{type Artist}
import elekf/library/artist_utils
import elekf/web/components/library_view.{type Model, ShowArtist}
import elekf/web/components/library_item.{type LibraryItem}
import elekf/web/components/library_views/thumbnail
@ -25,6 +26,7 @@ pub fn register() {
data_getter,
item_view,
shuffler,
artist_utils.sort_by_name,
search_filter,
)
}

View file

@ -81,6 +81,7 @@ fn init() {
library.empty(),
fn(_) -> List(LibraryItem(Album)) { [] },
shuffler,
album_utils.sort_by_year,
)
#(
@ -101,7 +102,8 @@ fn update(model: Model, msg) {
expanded_album: library.invalid_id,
library_view: library_view.Model(
..model.library_view,
data: data_getter(model.library_view.library, artist),
data: data_getter(model.library_view.library, artist)
|> list.sort(fn(a, b) { model.library_view.sorter(a.1, b.1) }),
),
),
effect.none(),

View file

@ -7,6 +7,7 @@ import gleam/option
import lustre/attribute
import elekf/library.{type Library}
import elekf/library/track.{type Track}
import elekf/library/track_utils
import elekf/web/components/library_view.{type Model}
import elekf/web/components/library_item.{type LibraryItem}
import elekf/web/components/library_views/track_item
@ -21,6 +22,7 @@ pub fn register() {
data_getter,
item_view,
shuffler,
track_utils.sort_by_name,
search_filter,
)
}