feat: Implemented TUI handler support for the Album Details popup in Lidarr

This commit is contained in:
2026-01-16 17:16:44 -07:00
parent bc6ecc39f4
commit caf4ad1e64
17 changed files with 2136 additions and 79 deletions
+1 -5
View File
@@ -92,15 +92,11 @@ pub static MANUAL_ARTIST_SEARCH_CONTEXT_CLUES: [ContextClue; 7] = [
(DEFAULT_KEYBINDINGS.esc, DEFAULT_KEYBINDINGS.esc.desc),
];
pub static ALBUM_DETAILS_CONTEXT_CLUES: [ContextClue; 7] = [
pub static ALBUM_DETAILS_CONTEXT_CLUES: [ContextClue; 6] = [
(
DEFAULT_KEYBINDINGS.refresh,
DEFAULT_KEYBINDINGS.refresh.desc,
),
(
DEFAULT_KEYBINDINGS.toggle_monitoring,
DEFAULT_KEYBINDINGS.toggle_monitoring.desc,
),
(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc),
(
DEFAULT_KEYBINDINGS.auto_search,
@@ -249,13 +249,6 @@ mod tests {
DEFAULT_KEYBINDINGS.refresh.desc
)
);
assert_some_eq_x!(
album_details_context_clues_iter.next(),
&(
DEFAULT_KEYBINDINGS.toggle_monitoring,
DEFAULT_KEYBINDINGS.toggle_monitoring.desc
)
);
assert_some_eq_x!(
album_details_context_clues_iter.next(),
&(DEFAULT_KEYBINDINGS.search, DEFAULT_KEYBINDINGS.search.desc)
+112
View File
@@ -9,6 +9,7 @@ mod tests {
use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::artist;
use pretty_assertions::{assert_eq, assert_str_eq};
use tokio::sync::mpsc;
use crate::models::servarr_data::lidarr::modals::AlbumDetailsModal;
#[tokio::test]
async fn test_dispatch_by_lidarr_block_artists() {
@@ -156,6 +157,117 @@ mod tests {
assert_eq!(app.tick_count, 0);
}
#[tokio::test]
async fn test_dispatch_by_album_history_block() {
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
let mut app = App::test_default();
app.data.lidarr_data.prompt_confirm = true;
app.network_tx = Some(tx);
app.data.lidarr_data.artists.set_items(vec![Artist {
id: 1,
..Artist::default()
}]);
app.data.lidarr_data.albums.set_items(vec![Album {
id: 1,
..Album::default()
}]);
app
.dispatch_by_lidarr_block(&ActiveLidarrBlock::AlbumHistory)
.await;
assert!(app.is_loading);
assert_eq!(
rx.recv().await.unwrap(),
LidarrEvent::GetAlbumHistory(1, 1).into()
);
assert!(!app.data.lidarr_data.prompt_confirm);
assert_eq!(app.tick_count, 0);
}
#[tokio::test]
async fn test_dispatch_by_album_history_block_no_op_when_albums_table_is_empty() {
let (tx, _) = mpsc::channel::<NetworkEvent>(500);
let mut app = App::test_default();
app.data.lidarr_data.prompt_confirm = true;
app.network_tx = Some(tx);
app.data.lidarr_data.artists.set_items(vec![Artist {
id: 1,
..Artist::default()
}]);
app
.dispatch_by_lidarr_block(&ActiveLidarrBlock::AlbumHistory)
.await;
assert!(!app.is_loading);
assert!(!app.data.lidarr_data.prompt_confirm);
assert_eq!(app.tick_count, 0);
}
#[tokio::test]
async fn test_dispatch_by_manual_album_search_block() {
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
let mut app = App::test_default();
app.data.lidarr_data.prompt_confirm = true;
app.network_tx = Some(tx);
app.data.lidarr_data.artists.set_items(vec![Artist {
id: 1,
..Artist::default()
}]);
app.data.lidarr_data.albums.set_items(vec![Album {
id: 1,
..Album::default()
}]);
app.data.lidarr_data.album_details_modal = Some(AlbumDetailsModal::default());
app
.dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch)
.await;
assert!(app.is_loading);
assert_eq!(
rx.recv().await.unwrap(),
LidarrEvent::GetAlbumReleases(1, 1).into()
);
assert!(!app.data.lidarr_data.prompt_confirm);
assert_eq!(app.tick_count, 0);
}
#[tokio::test]
async fn test_dispatch_by_manual_album_search_block_is_loading() {
let mut app = App {
is_loading: true,
..App::test_default()
};
app
.dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch)
.await;
assert!(app.is_loading);
assert!(!app.data.lidarr_data.prompt_confirm);
assert_eq!(app.tick_count, 0);
}
#[tokio::test]
async fn test_dispatch_by_manual_album_search_block_album_releases_non_empty() {
let mut app = App::test_default();
let mut album_details_modal = AlbumDetailsModal::default();
album_details_modal
.album_releases
.set_items(vec![LidarrRelease::default()]);
app.data.lidarr_data.album_details_modal = Some(album_details_modal);
app
.dispatch_by_lidarr_block(&ActiveLidarrBlock::ManualAlbumSearch)
.await;
assert!(!app.is_loading);
assert!(!app.data.lidarr_data.prompt_confirm);
assert_eq!(app.tick_count, 0);
}
#[tokio::test]
async fn test_dispatch_by_downloads_block() {
let (tx, mut rx) = mpsc::channel::<NetworkEvent>(500);
+23 -1
View File
@@ -2,7 +2,6 @@ use crate::{
models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock,
network::lidarr_network::LidarrEvent,
};
use super::App;
pub mod lidarr_context_clues;
@@ -67,6 +66,29 @@ impl App<'_> {
.dispatch_network_event(LidarrEvent::GetDownloads(500).into())
.await;
}
ActiveLidarrBlock::AlbumHistory => {
if !self.data.lidarr_data.albums.is_empty() {
self
.dispatch_network_event(
LidarrEvent::GetAlbumHistory(self.extract_artist_id().await, self.extract_album_id().await)
.into(),
)
.await;
}
}
ActiveLidarrBlock::ManualAlbumSearch => {
match self.data.lidarr_data.album_details_modal.as_ref() {
Some(album_details_modal) if album_details_modal.album_releases.is_empty() => {
self
.dispatch_network_event(
LidarrEvent::GetAlbumReleases(self.extract_artist_id().await, self.extract_album_id().await)
.into(),
)
.await;
}
_ => (),
}
}
ActiveLidarrBlock::AddArtistSearchResults => {
self
.dispatch_network_event(