feat(readarr): add the add author UI

Renders the author search box, the search results table, and the
multi-step add confirmation prompt with its five dropdown popups.

The prompt's per-field highlighting is conveyed purely by style, which
render_to_string_with_app discards, so the highlight mapping is extracted
into add_author_prompt_highlights and unit tested per selection step.

Enriches the fully populated author search fixture with a second result
that is absent from the library, so both branches of the in-library
marker render in one snapshot and every table column carries a value.
This commit is contained in:
Dark-Alex-17 committed 2026-09-03 18:03:12 -06:00
1 parent 7500e2da24
commit 7d1ff86c68
24 files changed
+1682 -5

No files matched your search

@@ -30,7 +30,7 @@ use {
super::modals::EditionDetailsModal,
crate::models::readarr_models::{
AuthorStatus, BookFile, DownloadStatus, Edition, MediaInfo, MonitorType, NewItemMonitorType,
ReadarrHistoryEventType, ReadarrTaskName,
Ratings, ReadarrHistoryEventType, ReadarrTaskName,
},
crate::models::servarr_models::{IndexerField, Quality, QualityWrapper},
crate::models::stateful_table::SortOption,
@@ -378,9 +378,26 @@ impl ReadarrData<'_> {
author_name: "Test Author".into(),
status: AuthorStatus::Continuing,
overview: Some("some interesting description of the author".to_owned()),
author_type: Some("Person".to_owned()),
disambiguation: Some("American novelist".to_owned()),
ratings: Some(Ratings {
votes: 1024,
value: 4.5,
popularity: Some(9.75),
}),
genres: vec!["science fiction".to_owned()],
..AddAuthorSearchResult::default()
};
let unadded_author_search_result = AddAuthorSearchResult {
foreign_author_id: "unadded-foreign-id".to_owned(),
author_name: "Unadded Author".into(),
status: AuthorStatus::Ended,
ended: true,
overview: Some("an author who is not yet in the library".to_owned()),
author_type: Some("Group".to_owned()),
genres: vec!["fantasy".to_owned(), "horror".to_owned()],
..AddAuthorSearchResult::default()
};
let task = ReadarrTask {
name: "Backup".to_owned(),
task_name: ReadarrTaskName::Backup,
@@ -589,7 +606,7 @@ impl ReadarrData<'_> {
readarr_data.queued_events.set_items(vec![queued_event()]);
readarr_data.add_author_search = Some("Test Author".into());
let mut add_searched_authors = StatefulTable::default();
add_searched_authors.set_items(vec![add_author_search_result]);
add_searched_authors.set_items(vec![add_author_search_result, unadded_author_search_result]);
readarr_data.add_searched_authors = Some(add_searched_authors);
readarr_data.logs.set_items(vec![log_line.into()]);
readarr_data.log_details.set_items(vec![log_line.into()]);