diff --git a/crates/musicus/src/screens/ensemble.rs b/crates/musicus/src/screens/ensemble.rs index 91e05f0..8737dda 100644 --- a/crates/musicus/src/screens/ensemble.rs +++ b/crates/musicus/src/screens/ensemble.rs @@ -7,7 +7,7 @@ use gettextrs::gettext; use glib::clone; use gtk::prelude::*; use libadwaita::prelude::*; -use musicus_backend::db::{Ensemble, Recording}; +use musicus_backend::db::{Ensemble, Medium, Recording}; use std::cell::RefCell; use std::rc::Rc; @@ -17,7 +17,9 @@ pub struct EnsembleScreen { ensemble: Ensemble, widget: widgets::Screen, recording_list: Rc, + medium_list: Rc, recordings: RefCell>, + mediums: RefCell>, } impl Screen for EnsembleScreen { @@ -28,13 +30,16 @@ impl Screen for EnsembleScreen { widget.set_title(&ensemble.name); let recording_list = List::new(); + let medium_list = List::new(); let this = Rc::new(Self { handle, ensemble, widget, recording_list, + medium_list, recordings: RefCell::new(Vec::new()), + mediums: RefCell::new(Vec::new()), }); this.widget.set_back_cb(clone!(@weak this => move || { @@ -58,6 +63,7 @@ impl Screen for EnsembleScreen { this.widget.set_search_cb(clone!(@weak this => move || { this.recording_list.invalidate_filter(); + this.medium_list.invalidate_filter(); })); this.recording_list.set_make_widget_cb(clone!(@weak this => move |index| { @@ -86,6 +92,27 @@ impl Screen for EnsembleScreen { search.is_empty() || text.to_lowercase().contains(&search) })); + this.medium_list.set_make_widget_cb(clone!(@weak this => move |index| { + let medium = &this.mediums.borrow()[index]; + + let row = libadwaita::ActionRow::new(); + row.set_activatable(true); + row.set_title(Some(&medium.name)); + + row.connect_activated(clone!(@weak this => move |_| { + // TODO: Show medium screen. + })); + + row.upcast() + })); + + this.medium_list.set_filter_cb(clone!(@weak this => move |index| { + let medium = &this.mediums.borrow()[index]; + let search = this.widget.get_search(); + let name = medium.name.to_lowercase(); + search.is_empty() || name.contains(&search) + })); + // Load the content asynchronously. spawn!(@clone this, async move { @@ -96,6 +123,13 @@ impl Screen for EnsembleScreen { .await .unwrap(); + let mediums = this.handle + .backend + .db() + .get_mediums_for_ensemble(&this.ensemble.id) + .await + .unwrap(); + if !recordings.is_empty() { let length = recordings.len(); this.recordings.replace(recordings); @@ -105,6 +139,15 @@ impl Screen for EnsembleScreen { this.widget.add_content(§ion.widget); } + if !mediums.is_empty() { + let length = mediums.len(); + this.mediums.replace(mediums); + this.medium_list.update(length); + + let section = Section::new("Mediums", &this.medium_list.widget); + this.widget.add_content(§ion.widget); + } + this.widget.ready(); }); diff --git a/crates/musicus/src/screens/person.rs b/crates/musicus/src/screens/person.rs index 73f78e6..9a96a7a 100644 --- a/crates/musicus/src/screens/person.rs +++ b/crates/musicus/src/screens/person.rs @@ -7,7 +7,7 @@ use gettextrs::gettext; use glib::clone; use gtk::prelude::*; use libadwaita::prelude::*; -use musicus_backend::db::{Person, Recording, Work}; +use musicus_backend::db::{Medium, Person, Recording, Work}; use std::cell::RefCell; use std::rc::Rc; @@ -18,8 +18,10 @@ pub struct PersonScreen { widget: widgets::Screen, work_list: Rc, recording_list: Rc, + medium_list: Rc, works: RefCell>, recordings: RefCell>, + mediums: RefCell>, } impl Screen for PersonScreen { @@ -31,6 +33,7 @@ impl Screen for PersonScreen { let work_list = List::new(); let recording_list = List::new(); + let medium_list = List::new(); let this = Rc::new(Self { handle, @@ -38,8 +41,10 @@ impl Screen for PersonScreen { widget, work_list, recording_list, + medium_list, works: RefCell::new(Vec::new()), recordings: RefCell::new(Vec::new()), + mediums: RefCell::new(Vec::new()), }); this.widget.set_back_cb(clone!(@weak this => move || { @@ -64,6 +69,7 @@ impl Screen for PersonScreen { this.widget.set_search_cb(clone!(@weak this => move || { this.work_list.invalidate_filter(); this.recording_list.invalidate_filter(); + this.medium_list.invalidate_filter(); })); this.work_list.set_make_widget_cb(clone!(@weak this => move |index| { @@ -117,6 +123,27 @@ impl Screen for PersonScreen { search.is_empty() || text.to_lowercase().contains(&search) })); + this.medium_list.set_make_widget_cb(clone!(@weak this => move |index| { + let medium = &this.mediums.borrow()[index]; + + let row = libadwaita::ActionRow::new(); + row.set_activatable(true); + row.set_title(Some(&medium.name)); + + row.connect_activated(clone!(@weak this => move |_| { + // TODO: Show medium screen. + })); + + row.upcast() + })); + + this.medium_list.set_filter_cb(clone!(@weak this => move |index| { + let medium = &this.mediums.borrow()[index]; + let search = this.widget.get_search(); + let name = medium.name.to_lowercase(); + search.is_empty() || name.contains(&search) + })); + // Load the content asynchronously. spawn!(@clone this, async move { @@ -134,6 +161,13 @@ impl Screen for PersonScreen { .await .unwrap(); + let mediums = this.handle + .backend + .db() + .get_mediums_for_person(&this.person.id) + .await + .unwrap(); + if !works.is_empty() { let length = works.len(); this.works.replace(works); @@ -152,6 +186,15 @@ impl Screen for PersonScreen { this.widget.add_content(§ion.widget); } + if !mediums.is_empty() { + let length = mediums.len(); + this.mediums.replace(mediums); + this.medium_list.update(length); + + let section = Section::new("Mediums", &this.medium_list.widget); + this.widget.add_content(§ion.widget); + } + this.widget.ready(); });