diff --git a/src/ui/lidarr_ui/library/album_details_ui.rs b/src/ui/lidarr_ui/library/album_details_ui.rs index 31628d86..e5dd920c 100644 --- a/src/ui/lidarr_ui/library/album_details_ui.rs +++ b/src/ui/lidarr_ui/library/album_details_ui.rs @@ -1,6 +1,8 @@ use crate::app::App; use crate::models::Route; -use crate::models::lidarr_models::{LidarrHistoryItem, LidarrRelease, Track}; +use crate::models::lidarr_models::{ + DownloadRecord, DownloadStatus, LidarrHistoryItem, LidarrRelease, Track, +}; use crate::models::servarr_data::lidarr::lidarr_data::{ALBUM_DETAILS_BLOCKS, ActiveLidarrBlock}; use crate::ui::lidarr_ui::library::track_details_ui::TrackDetailsUi; use crate::ui::lidarr_ui::lidarr_ui_utils::create_history_event_details; @@ -150,6 +152,7 @@ fn draw_tracks_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { .expect("Album details modal is unpopulated") .tracks, ); + let downloads_vec = &app.data.lidarr_data.downloads.items; let track_row_mapping = |track: &Track| { let Track { @@ -187,6 +190,7 @@ fn draw_tracks_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { let duration_str = format!("{mins}:{secs:02}"); decorate_track_row_with_style( + downloads_vec, track, Row::new(vec![ Cell::from(track_number.clone()), @@ -221,12 +225,35 @@ fn draw_tracks_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { } } -fn decorate_track_row_with_style<'a>(track: &Track, row: Row<'a>) -> Row<'a> { - if track.has_file { - row.downloaded() - } else { - row.missing() +fn decorate_track_row_with_style<'a>( + downloads_vec: &[DownloadRecord], + track: &Track, + row: Row<'a>, +) -> Row<'a> { + if !track.has_file { + let default_album_id = Number::from(-1i64); + if let Some(download) = downloads_vec.iter().find(|&download| { + download + .album_id + .as_ref() + .unwrap_or(&default_album_id) + .as_i64() + .unwrap() + == track.album_id + }) { + if download.status == DownloadStatus::Downloading { + return row.downloading(); + } + + if download.status == DownloadStatus::Completed { + return row.awaiting_import(); + } + } + + return row.missing(); } + + row.downloaded() } fn draw_album_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { diff --git a/src/ui/lidarr_ui/library/album_details_ui_tests.rs b/src/ui/lidarr_ui/library/album_details_ui_tests.rs index 260fb8af..a277027b 100644 --- a/src/ui/lidarr_ui/library/album_details_ui_tests.rs +++ b/src/ui/lidarr_ui/library/album_details_ui_tests.rs @@ -2,14 +2,16 @@ mod tests { use pretty_assertions::assert_eq; use ratatui::widgets::{Cell, Row}; + use serde_json::Number; use strum::IntoEnumIterator; use crate::app::App; - use crate::models::lidarr_models::Track; + use crate::models::lidarr_models::{DownloadRecord, DownloadStatus, Track}; use crate::models::servarr_data::lidarr::lidarr_data::{ ALBUM_DETAILS_BLOCKS, ActiveLidarrBlock, TRACK_DETAILS_BLOCKS, }; use crate::models::stateful_table::StatefulTable; + use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::download_record; use crate::ui::DrawUi; use crate::ui::lidarr_ui::library::album_details_ui::{ AlbumDetailsUi, decorate_track_row_with_style, @@ -39,7 +41,7 @@ mod tests { }; let row = Row::new(vec![Cell::from("test".to_owned())]); - let style = decorate_track_row_with_style(&track, row.clone()); + let style = decorate_track_row_with_style(&[], &track, row.clone()); assert_eq!(style, row.downloaded()); } @@ -52,11 +54,89 @@ mod tests { }; let row = Row::new(vec![Cell::from("test".to_owned())]); - let style = decorate_track_row_with_style(&track, row.clone()); + let style = decorate_track_row_with_style(&[], &track, row.clone()); assert_eq!(style, row.missing()); } + #[test] + fn test_decorate_track_row_with_style_downloading_when_track_has_no_file_and_album_is_downloading() + { + let downloads_vec = vec![album_download(7, DownloadStatus::Downloading)]; + let track = Track { + has_file: false, + album_id: 7, + ..Track::default() + }; + let row = Row::new(vec![Cell::from("test".to_owned())]); + + let style = decorate_track_row_with_style(&downloads_vec, &track, row.clone()); + + assert_eq!(style, row.downloading()); + } + + #[test] + fn test_decorate_track_row_with_style_awaiting_import_when_track_has_no_file_and_album_download_is_completed() + { + let downloads_vec = vec![album_download(7, DownloadStatus::Completed)]; + let track = Track { + has_file: false, + album_id: 7, + ..Track::default() + }; + let row = Row::new(vec![Cell::from("test".to_owned())]); + + let style = decorate_track_row_with_style(&downloads_vec, &track, row.clone()); + + assert_eq!(style, row.awaiting_import()); + } + + #[test] + fn test_decorate_track_row_with_style_missing_when_album_download_is_neither_downloading_nor_completed() + { + let downloads_vec = vec![album_download(7, DownloadStatus::Queued)]; + let track = Track { + has_file: false, + album_id: 7, + ..Track::default() + }; + let row = Row::new(vec![Cell::from("test".to_owned())]); + + let style = decorate_track_row_with_style(&downloads_vec, &track, row.clone()); + + assert_eq!(style, row.missing()); + } + + #[test] + fn test_decorate_track_row_with_style_missing_when_only_a_different_album_is_downloading() { + let downloads_vec = vec![album_download(8, DownloadStatus::Downloading)]; + let track = Track { + has_file: false, + album_id: 7, + ..Track::default() + }; + let row = Row::new(vec![Cell::from("test".to_owned())]); + + let style = decorate_track_row_with_style(&downloads_vec, &track, row.clone()); + + assert_eq!(style, row.missing()); + } + + #[test] + fn test_decorate_track_row_with_style_downloaded_when_track_has_file_and_album_is_downloading() { + let downloads_vec = vec![album_download(7, DownloadStatus::Downloading)]; + let track = Track { + has_file: true, + album_id: 7, + ..Track::default() + }; + let row = Row::new(vec![Cell::from("test".to_owned())]); + + let style = decorate_track_row_with_style(&downloads_vec, &track, row.clone()); + + assert_eq!(style, row.downloaded()); + } + mod snapshot_tests { use crate::ui::ui_test_utils::test_utils::TerminalSize; use rstest::rstest; @@ -177,4 +257,13 @@ mod tests { insta::assert_snapshot!(output); } } + + fn album_download(album_id: i64, status: DownloadStatus) -> DownloadRecord { + DownloadRecord { + status, + album_id: Some(Number::from(album_id)), + artist_id: Some(Number::from(3i64)), + ..download_record() + } + } }