diff --git a/delfin/src/media_details/media_details_contents.rs b/delfin/src/media_details/media_details_contents.rs index cf936b0..8799503 100644 --- a/delfin/src/media_details/media_details_contents.rs +++ b/delfin/src/media_details/media_details_contents.rs @@ -16,7 +16,9 @@ use crate::{ }; use super::{ - display_years::DisplayYears, media_details_header::MediaDetailsHeader, seasons::Seasons, + display_years::DisplayYears, + media_details_header::MediaDetailsHeader, + seasons::{Seasons, SeasonsOutput}, }; pub struct MediaDetailsContents { @@ -25,11 +27,13 @@ pub struct MediaDetailsContents { series_id: Option, header: OnceCell>, seasons: Option>, + selected_season_index: Option, } #[derive(Debug)] pub enum MediaDetailsContentsInput { RefreshSeasons, + SetSelectedSeasonIndex(usize), } #[relm4::component(pub async)] @@ -92,7 +96,7 @@ impl AsyncComponent for MediaDetailsContents { async fn init( init: Self::Init, root: Self::Root, - _sender: AsyncComponentSender, + sender: AsyncComponentSender, ) -> AsyncComponentParts { let (api_client, media) = init; @@ -115,6 +119,7 @@ impl AsyncComponent for MediaDetailsContents { series_id, header: OnceCell::new(), seasons: None, + selected_season_index: None, }; let widgets = view_output!(); @@ -133,7 +138,7 @@ impl AsyncComponent for MediaDetailsContents { model.add_info(info_box); - model.load_seasons(container); + model.load_seasons(&sender, container); AsyncComponentParts { model, widgets } } @@ -147,7 +152,10 @@ impl AsyncComponent for MediaDetailsContents { ) { match message { MediaDetailsContentsInput::RefreshSeasons => { - self.load_seasons(&widgets.container); + self.load_seasons(&sender, &widgets.container); + } + MediaDetailsContentsInput::SetSelectedSeasonIndex(selected_season_index) => { + self.selected_season_index = Some(selected_season_index); } } self.update_view(widgets, sender); @@ -155,7 +163,7 @@ impl AsyncComponent for MediaDetailsContents { } impl MediaDetailsContents { - fn load_seasons(&mut self, container: >k::Box) { + fn load_seasons(&mut self, sender: &AsyncComponentSender, container: >k::Box) { if let Some(seasons) = self.seasons.take() { container.remove(seasons.widget()); } @@ -165,8 +173,9 @@ impl MediaDetailsContents { .launch(SeasonsInit { api_client: self.api_client.clone(), series_id, + initial_selected_season_index: self.selected_season_index, }) - .detach(); + .forward(sender.input_sender(), |m| m.into()); container.append(seasons.widget()); self.seasons = Some(seasons); } @@ -232,3 +241,13 @@ impl MediaDetailsContents { } } } + +impl From for MediaDetailsContentsInput { + fn from(val: SeasonsOutput) -> Self { + match val { + SeasonsOutput::SeasonSelected(selected_season_index) => { + MediaDetailsContentsInput::SetSelectedSeasonIndex(selected_season_index) + } + } + } +} diff --git a/delfin/src/media_details/season_buttons.rs b/delfin/src/media_details/season_buttons.rs index 21042d0..4bc6850 100644 --- a/delfin/src/media_details/season_buttons.rs +++ b/delfin/src/media_details/season_buttons.rs @@ -10,7 +10,7 @@ pub(crate) struct SeasonButtons; #[relm4::component(pub(crate))] impl SimpleComponent for SeasonButtons { - type Init = Vec; + type Init = (Vec, usize); type Input = (); type Output = SeasonsInput; @@ -23,10 +23,12 @@ impl SimpleComponent for SeasonButtons { } fn init( - seasons: Self::Init, + init: Self::Init, seasons_box: &Self::Root, sender: ComponentSender, ) -> ComponentParts { + let (seasons, initial_selected_season_index) = init; + let model = SeasonButtons; let widgets = view_output!(); @@ -40,15 +42,16 @@ impl SimpleComponent for SeasonButtons { } }; - // First button will be active and is used to group remaining buttons + // First button will is used to group remaining buttons let first_btn = create_season_btn(&seasons[0]); - first_btn.set_active(true); + first_btn.set_active(initial_selected_season_index == 0); first_btn.connect_toggled(btn_toggle_handler(0)); seasons_box.append(&first_btn); for (index, season) in seasons.iter().enumerate().skip(1) { let season_btn = create_season_btn(season); season_btn.set_group(Some(&first_btn)); + season_btn.set_active(initial_selected_season_index == index); season_btn.connect_toggled(btn_toggle_handler(index)); seasons_box.append(&season_btn); } diff --git a/delfin/src/media_details/seasons.rs b/delfin/src/media_details/seasons.rs index 120a459..d6de285 100644 --- a/delfin/src/media_details/seasons.rs +++ b/delfin/src/media_details/seasons.rs @@ -26,6 +26,7 @@ pub struct Seasons { pub struct SeasonsInit { pub api_client: Arc, pub series_id: Uuid, + pub initial_selected_season_index: Option, } #[derive(Debug)] @@ -33,11 +34,16 @@ pub enum SeasonsInput { SeasonActivated(usize), } +#[derive(Debug)] +pub enum SeasonsOutput { + SeasonSelected(usize), +} + #[relm4::component(pub async)] impl AsyncComponent for Seasons { type Init = SeasonsInit; type Input = SeasonsInput; - type Output = (); + type Output = SeasonsOutput; type CommandOutput = (); view! { @@ -74,6 +80,7 @@ impl AsyncComponent for Seasons { let SeasonsInit { api_client, series_id, + initial_selected_season_index, } = init; let widgets = view_output!(); @@ -93,14 +100,18 @@ impl AsyncComponent for Seasons { return AsyncComponentParts { model, widgets }; } + let initial_selected_season_index = match initial_selected_season_index { + Some(season) if season < model.seasons.len() => season, + _ => 0, + }; + let season_buttons = SeasonButtons::builder() - .launch(model.seasons.clone()) + .launch((model.seasons.clone(), initial_selected_season_index)) .forward(sender.input_sender(), |e| e); root.append(season_buttons.widget()); model.season_buttons = Some(season_buttons); - // Load first season by default - sender.input(SeasonsInput::SeasonActivated(0)); + sender.input(SeasonsInput::SeasonActivated(initial_selected_season_index)); AsyncComponentParts { model, widgets } } @@ -108,7 +119,7 @@ impl AsyncComponent for Seasons { async fn update( &mut self, msg: Self::Input, - _sender: AsyncComponentSender, + sender: AsyncComponentSender, root: &Self::Root, ) { match msg { @@ -128,6 +139,8 @@ impl AsyncComponent for Seasons { .detach(); root.append(episodes.widget()); self.episodes = Some(episodes); + + sender.output(SeasonsOutput::SeasonSelected(index)).unwrap(); } } }