Skip to content

Commit

Permalink
refactor: migrate album tree component to list component
Browse files Browse the repository at this point in the history
  • Loading branch information
lautarodragan committed Jan 10, 2025
1 parent e2c40cb commit 7372817
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 67 deletions.
2 changes: 1 addition & 1 deletion assets/actions.kv
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Navigation.End=End
Navigation.PageUp=PageUp
Navigation.PageDown=PageDown

Text.Delete=Delete
# Text.Delete=Delete
Text.DeleteBack=Backspace

List.Insert=Insert
Expand Down
9 changes: 4 additions & 5 deletions src/components/library/album_tree/album_tree_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ impl PartialOrd for AlbumTreeItem {

impl Display for AlbumTreeItem {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let x = match self {
AlbumTreeItem::Artist(s) => s,
AlbumTreeItem::Album(_, s) => s,
};
write!(f, "{x}")
match self {
AlbumTreeItem::Artist(s) => write!(f, "{s}"),
AlbumTreeItem::Album(_, s) => write!(f, " {s}"),
}
}
}
65 changes: 59 additions & 6 deletions src/components/library/keyboard_handler.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,78 @@
use crate::structs::{Action, NavigationAction, OnAction};
use crate::{
components::library::album_tree::AlbumTreeItem,
structs::{Action, ListAction, NavigationAction, OnAction},
};

use super::library::Library;

impl OnAction for Library<'_> {
fn on_action(&self, action: Action) {
// log::trace!(target: "::library.on_action", "{action:?}");

let i = self.focused_component.get();

match action {
Action::Navigation(NavigationAction::FocusNext) => {
let focused_component = self.focused_component.get();
self.focused_component.set({
if i < self.components.len().saturating_sub(1) {
i + 1
if focused_component < self.components.len().saturating_sub(1) {
focused_component + 1
} else {
0
}
});
}
Action::ListAction(ListAction::OpenClose) => {
let (artist_index, artist_album_count) = self.album_tree.with_items(|items| {
let artist_index = {
let mut artist_index = self.album_tree.selected_index_true();
log::debug!("OpenClose {artist_index} {:?}", items[artist_index]);
loop {
if let AlbumTreeItem::Artist(_) = items[artist_index] {
break artist_index;
} else {
artist_index -= 1;
}
}
};

log::debug!("OpenClose artist_index={artist_index} {:?}", items[artist_index]);

let artist_album_count = {
let mut artist_album_count = 1;
loop {
let item_index = artist_index + artist_album_count;
log::debug!("matching {artist_index} {artist_album_count} {:?}", items[item_index]);

if item_index >= items.len() - 1 {
break artist_album_count;
}

match items[item_index] {
AlbumTreeItem::Album(ar, al) => artist_album_count += 1,
_ => break artist_album_count - 1,
}
}
};

log::debug!("OpenClose artist_album_count={artist_album_count}");
log::debug!("OpenClose artist_album_count={artist_album_count} {:?}", items[artist_index + artist_album_count]);

(artist_index, artist_album_count)
});

log::debug!("toggling {artist_index}..{artist_album_count}");
let is_open = !self.album_tree.is_open(artist_index);
self.album_tree.set_is_open(artist_index, is_open);

for i in artist_index + 1..artist_index + 1 + artist_album_count {
self.album_tree.set_is_visible(i, is_open);
}

if !is_open {
self.album_tree.set_selected_index_true(artist_index);
}
}
_ => {
if let Some(a) = self.components.get(i) {
if let Some(a) = self.components.get(self.focused_component.get()) {
a.on_action(action);
}
}
Expand Down
67 changes: 39 additions & 28 deletions src/components/library/library.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
cell::Cell,
collections::HashSet,
rc::Rc,
sync::{Mutex, MutexGuard},
};
Expand All @@ -15,7 +16,7 @@ pub struct Library<'a> {
pub(super) songs_by_artist: Rc<Mutex<crate::files::Library>>,

pub(super) song_list: Rc<List<'a, Song>>,
pub(super) album_tree: Rc<AlbumTree<'a>>,
pub(super) album_tree: Rc<List<'a, AlbumTreeItem>>,
pub(super) components: Rc<Vec<Component<'a>>>,
pub(super) focused_component: Rc<Cell<usize>>,

Expand All @@ -27,7 +28,7 @@ impl<'a> Library<'a> {
let on_select_songs_fn: Rc<Mutex<Box<dyn FnMut(Vec<Song>) + 'a>>> = Rc::new(Mutex::new(Box::new(|_| {}) as _));

let songs_by_artist = Rc::new(Mutex::new(crate::files::Library::from_file()));
let album_tree = Rc::new(AlbumTree::new(theme));
let album_tree = Rc::new(List::new(theme, vec![]));
let song_list = Rc::new(List::new(theme, vec![]));

album_tree.on_select({
Expand Down Expand Up @@ -65,7 +66,7 @@ impl<'a> Library<'a> {
}
});

album_tree.on_confirm({
album_tree.on_enter({
let songs = songs_by_artist.clone();
let on_select_songs_fn = on_select_songs_fn.clone();

Expand Down Expand Up @@ -102,7 +103,7 @@ impl<'a> Library<'a> {
album_tree.on_delete({
let songs_by_artist = songs_by_artist.clone();

move |item| {
move |item, index| {
log::trace!(target: "::library.album_tree.on_delete", "item deleted {:?}", item);

let mut songs_by_artist = songs_by_artist.lock().unwrap();
Expand Down Expand Up @@ -194,38 +195,48 @@ impl<'a> Library<'a> {
}

fn refresh_artist_tree(&self, songs_by_artist: &MutexGuard<crate::files::Library>) {
let mut items = vec![];

for (artist, songs) in &songs_by_artist.songs_by_artist {
items.push(AlbumTreeItem::Artist(artist.clone()));
let mut albums = HashSet::new();

for song in songs {
let album = song.album.clone().unwrap_or("(no album)".to_string());
self.album_tree.add_album(artist.clone(), album);
albums.insert(album.clone());
}
}
}

fn refresh_song_list(&self, songs_by_artist: &MutexGuard<crate::files::Library>) {
let Some(selected_item) = self.album_tree.selected_item() else {
return;
};
for album in albums {
items.push(AlbumTreeItem::Album(artist.clone(), album));
}
}

let (selected_artist, selected_album) = match selected_item {
AlbumTreeItem::Artist(selected_artist) => (selected_artist, None),
AlbumTreeItem::Album(selected_artist, selected_album) => (selected_artist, Some(selected_album)),
};
self.album_tree.set_items(items);
}

let Some(songs) = songs_by_artist.songs_by_artist.get(&selected_artist) else {
log::error!(target: "::library.add_songs", "This should never happen! There's an error with songs_by_artist/songs_by_artist.");
return;
};
fn refresh_song_list(&self, library: &MutexGuard<crate::files::Library>) {
let songs = self.album_tree.with_selected_item(|selected_item| {
let (selected_artist, selected_album) = match selected_item {
AlbumTreeItem::Artist(selected_artist) => (selected_artist.as_str(), None),
AlbumTreeItem::Album(selected_artist, selected_album) => (selected_artist.as_str(), Some(selected_album.as_str())),
};

let Some(songs) = library.songs_by_artist.get(selected_artist) else {
log::error!(target: "::library.add_songs", "This should never happen! There's an error with songs_by_artist/songs_by_artist.");
panic!();
};

if let Some(selected_album) = selected_album {
songs
.iter()
.filter(|s| s.album.as_ref().is_some_and(|sa| *sa == selected_album))
.cloned()
.collect()
} else {
songs.clone()
}
});

let songs = if let Some(selected_album) = selected_album {
songs
.iter()
.filter(|s| s.album.as_ref().is_some_and(|sa| *sa == selected_album))
.cloned()
.collect()
} else {
songs.clone()
};
self.song_list.set_items(songs);
}
}
Expand Down
Loading

0 comments on commit 7372817

Please sign in to comment.