Added support for adding movies directly from the collection details UI, refactored to support contexts for different routes, and fixed the horizontal scrolling bug with the get_width_with_margin function.

This commit is contained in:
2023-08-08 10:50:05 -06:00
parent 3007f76efe
commit 6866f90329
16 changed files with 646 additions and 208 deletions
+4 -5
View File
@@ -14,7 +14,7 @@ use crate::network::NetworkEvent;
pub(crate) mod key_binding;
pub mod radarr;
const DEFAULT_ROUTE: Route = Route::Radarr(ActiveRadarrBlock::Movies);
const DEFAULT_ROUTE: Route = Route::Radarr(ActiveRadarrBlock::Movies, None);
pub struct App {
navigation_stack: Vec<Route>,
@@ -72,7 +72,7 @@ impl App {
pub async fn on_tick(&mut self, is_first_render: bool) {
if self.tick_count % self.tick_until_poll == 0 || self.is_routing || self.should_refresh {
if let Route::Radarr(active_radarr_block) = self.get_current_route() {
if let Route::Radarr(active_radarr_block, _) = self.get_current_route() {
self
.radarr_on_tick(*active_radarr_block, is_first_render)
.await;
@@ -117,14 +117,13 @@ impl Default for App {
TabRoute {
title: "Radarr".to_owned(),
route: ActiveRadarrBlock::Movies.into(),
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <?> help | <q> quit "
.to_owned(),
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ".to_owned(),
contextual_help: None,
},
TabRoute {
title: "Sonarr".to_owned(),
route: Route::Sonarr,
help: "<tab> change servarr | <?> help | <q> quit ".to_owned(),
help: "<tab> change servarr | <q> quit ".to_owned(),
contextual_help: None,
},
]),
+69 -1
View File
@@ -2,6 +2,7 @@ use std::collections::HashMap;
use std::time::Duration;
use chrono::{DateTime, Utc};
use strum::IntoEnumIterator;
use crate::app::{App, Route};
use crate::models::radarr_models::{
@@ -88,6 +89,21 @@ impl RadarrData {
self.add_movie_minimum_availability_list = StatefulList::default();
self.add_movie_quality_profile_list = StatefulList::default();
}
pub fn populate_add_movie_preferences_lists(&mut self) {
self
.add_movie_monitor_list
.set_items(Vec::from_iter(Monitor::iter()));
self
.add_movie_minimum_availability_list
.set_items(Vec::from_iter(MinimumAvailability::iter()));
let mut quality_profile_names: Vec<String> =
self.quality_profile_map.values().cloned().collect();
quality_profile_names.sort();
self
.add_movie_quality_profile_list
.set_items(quality_profile_names);
}
}
impl Default for RadarrData {
@@ -290,7 +306,13 @@ impl ActiveRadarrBlock {
impl From<ActiveRadarrBlock> for Route {
fn from(active_radarr_block: ActiveRadarrBlock) -> Route {
Route::Radarr(active_radarr_block)
Route::Radarr(active_radarr_block, None)
}
}
impl From<(ActiveRadarrBlock, Option<ActiveRadarrBlock>)> for Route {
fn from(value: (ActiveRadarrBlock, Option<ActiveRadarrBlock>)) -> Route {
Route::Radarr(value.0, value.1)
}
}
@@ -565,9 +587,29 @@ pub mod radarr_test_utils {
#[cfg(test)]
mod tests {
mod radarr_data_tests {
use std::collections::HashMap;
use pretty_assertions::assert_eq;
use strum::IntoEnumIterator;
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
use crate::app::radarr::{ActiveRadarrBlock, RadarrData};
use crate::models::radarr_models::{MinimumAvailability, Monitor};
use crate::models::Route;
#[test]
fn test_from_tuple_to_route_with_context() {
assert_eq!(
Route::from((
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::AddMovieSearchResults)
)),
Route::Radarr(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::AddMovieSearchResults)
)
);
}
#[test]
fn test_reset_movie_collection_table() {
@@ -613,6 +655,32 @@ mod tests {
assert_add_movie_selections_reset!(radarr_data);
}
#[test]
fn test_populate_add_movie_preferences_lists() {
let mut radarr_data = RadarrData {
quality_profile_map: HashMap::from([
(2222, "HD - 1080p".to_owned()),
(1111, "Any".to_owned()),
]),
..RadarrData::default()
};
radarr_data.populate_add_movie_preferences_lists();
assert_eq!(
radarr_data.add_movie_monitor_list.items,
Vec::from_iter(Monitor::iter())
);
assert_eq!(
radarr_data.add_movie_minimum_availability_list.items,
Vec::from_iter(MinimumAvailability::iter())
);
assert_eq!(
radarr_data.add_movie_quality_profile_list.items,
vec!["Any".to_owned(), "HD - 1080p".to_owned()]
);
}
}
mod active_radarr_block_tests {
+36 -29
View File
@@ -29,7 +29,7 @@ pub trait KeyEventHandler<'a, T: Into<Route>> {
self.handle_key_event();
}
fn with(key: &'a Key, app: &'a mut App, active_block: &'a T) -> Self;
fn with(key: &'a Key, app: &'a mut App, active_block: &'a T, context: &'a Option<T>) -> Self;
fn get_key(&self) -> &Key;
fn handle_scroll_up(&mut self);
fn handle_scroll_down(&mut self);
@@ -43,8 +43,8 @@ pub trait KeyEventHandler<'a, T: Into<Route>> {
}
pub fn handle_events(key: Key, app: &mut App) {
if let Route::Radarr(active_radarr_block) = *app.get_current_route() {
RadarrHandler::with(&key, app, &active_radarr_block).handle()
if let Route::Radarr(active_radarr_block, context) = *app.get_current_route() {
RadarrHandler::with(&key, app, &active_radarr_block, &context).handle()
}
}
@@ -57,7 +57,7 @@ fn handle_clear_errors(app: &mut App) {
fn handle_prompt_toggle(app: &mut App, key: &Key) {
match key {
_ if *key == DEFAULT_KEYBINDINGS.left.key || *key == DEFAULT_KEYBINDINGS.right.key => {
if let Route::Radarr(_) = *app.get_current_route() {
if let Route::Radarr(_, _) = *app.get_current_route() {
app.data.radarr_data.prompt_confirm = !app.data.radarr_data.prompt_confirm;
}
}
@@ -177,7 +177,7 @@ mod test_utils {
#[macro_export]
macro_rules! test_iterable_scroll {
($func:ident, $handler:ident, $data_ref:ident, $block:expr) => {
($func:ident, $handler:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
@@ -187,16 +187,16 @@ mod test_utils {
.$data_ref
.set_items(vec!["Test 1".to_owned(), "Test 2".to_owned()]);
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 2");
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 1");
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $field:ident) => {
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
@@ -206,14 +206,14 @@ mod test_utils {
.$data_ref
.set_items(simple_stateful_iterable_vec!($items));
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 2"
);
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
@@ -221,13 +221,13 @@ mod test_utils {
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $field:ident, $conversion_fn:ident) => {
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
@@ -240,7 +240,7 @@ mod test_utils {
"Test 2"
);
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
@@ -258,7 +258,7 @@ mod test_utils {
#[macro_export]
macro_rules! test_enum_scroll {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr) => {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[rstest]
fn $func(#[values(DEFAULT_KEYBINDINGS.up.key, DEFAULT_KEYBINDINGS.down.key)] key: Key) {
let reference_vec = Vec::from_iter($name::iter());
@@ -271,7 +271,7 @@ mod test_utils {
if key == Key::Up {
for i in (0..reference_vec.len()).rev() {
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
@@ -280,7 +280,7 @@ mod test_utils {
}
} else {
for i in 0..reference_vec.len() {
$handler::with(&key, &mut app, &$block).handle();
$handler::with(&key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
@@ -294,7 +294,7 @@ mod test_utils {
#[macro_export]
macro_rules! test_iterable_home_and_end {
($func:ident, $handler:ident, $data_ref:ident, $block:expr) => {
($func:ident, $handler:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[test]
fn $func() {
let mut app = App::default();
@@ -304,16 +304,16 @@ mod test_utils {
"Test 3".to_owned(),
]);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 3");
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(app.data.radarr_data.$data_ref.current_selection(), "Test 1");
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $field:ident) => {
($func:ident, $handler:ident, $data_ref:ident, $items:ident, $block:expr, $context:expr, $field:ident) => {
#[test]
fn $func() {
let mut app = App::default();
@@ -323,14 +323,14 @@ mod test_utils {
.$data_ref
.set_items(extended_stateful_iterable_vec!($items));
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app.data.radarr_data.$data_ref.current_selection().$field,
@@ -338,13 +338,13 @@ mod test_utils {
);
}
};
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $field:ident, $conversion_fn:ident) => {
($func:ident, $handler:ident, $data_ref:ident, $items:expr, $block:expr, $context:expr, $field:ident, $conversion_fn:ident) => {
#[test]
fn $func() {
let mut app = App::default();
app.data.radarr_data.$data_ref.set_items($items);
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
@@ -357,7 +357,7 @@ mod test_utils {
"Test 3"
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_str_eq!(
app
@@ -375,7 +375,7 @@ mod test_utils {
#[macro_export]
macro_rules! test_enum_home_and_end {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr) => {
($func:ident, $handler:ident, $name:ident, $data_ref:ident, $block:expr, $context:expr) => {
#[test]
fn $func() {
let reference_vec = Vec::from_iter($name::iter());
@@ -386,14 +386,14 @@ mod test_utils {
.$data_ref
.set_items(reference_vec.clone());
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.end.key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
&reference_vec[reference_vec.len() - 1]
);
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block).handle();
$handler::with(&DEFAULT_KEYBINDINGS.home.key, &mut app, &$block, &$context).handle();
assert_eq!(
app.data.radarr_data.$data_ref.current_selection(),
@@ -410,12 +410,19 @@ mod test_utils {
app.push_navigation_stack($base.clone().into());
app.push_navigation_stack($active_block.clone().into());
RadarrHandler::with(&DEFAULT_KEYBINDINGS.esc.key, &mut app, &$active_block).handle();
RadarrHandler::with(
&DEFAULT_KEYBINDINGS.esc.key,
&mut app,
&$active_block,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &$base.into());
};
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
+125 -54
View File
@@ -1,9 +1,6 @@
use strum::IntoEnumIterator;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::app::radarr::ActiveRadarrBlock;
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
use crate::models::radarr_models::{MinimumAvailability, Monitor};
use crate::models::{Scrollable, StatefulTable};
use crate::network::radarr_network::RadarrEvent;
use crate::{handle_text_box_keys, App, Key};
@@ -12,6 +9,7 @@ pub(super) struct AddMovieHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_radarr_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>,
}
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
@@ -19,11 +17,13 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>,
) -> AddMovieHandler<'a> {
AddMovieHandler {
key,
app,
active_radarr_block: active_block,
context,
}
}
@@ -192,6 +192,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
.current_selection()
.tmdb_id
.clone();
if self
.app
.data
@@ -212,29 +213,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
.app
.data
.radarr_data
.add_movie_monitor_list
.set_items(Vec::from_iter(Monitor::iter()));
self
.app
.data
.radarr_data
.add_movie_minimum_availability_list
.set_items(Vec::from_iter(MinimumAvailability::iter()));
let mut quality_profile_names: Vec<String> = self
.app
.data
.radarr_data
.quality_profile_map
.values()
.cloned()
.collect();
quality_profile_names.sort();
self
.app
.data
.radarr_data
.add_movie_quality_profile_list
.set_items(quality_profile_names);
.populate_add_movie_preferences_lists();
}
}
ActiveRadarrBlock::AddMoviePrompt => match self.app.data.radarr_data.selected_block {
@@ -248,13 +227,21 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
}
ActiveRadarrBlock::AddMovieSelectMonitor => self
.app
.push_navigation_stack(ActiveRadarrBlock::AddMovieSelectMonitor.into()),
ActiveRadarrBlock::AddMovieSelectMinimumAvailability => self
.app
.push_navigation_stack(ActiveRadarrBlock::AddMovieSelectMinimumAvailability.into()),
ActiveRadarrBlock::AddMovieSelectQualityProfile => self
.app
.push_navigation_stack(ActiveRadarrBlock::AddMovieSelectQualityProfile.into()),
.push_navigation_stack((ActiveRadarrBlock::AddMovieSelectMonitor, *self.context).into()),
ActiveRadarrBlock::AddMovieSelectMinimumAvailability => self.app.push_navigation_stack(
(
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
*self.context,
)
.into(),
),
ActiveRadarrBlock::AddMovieSelectQualityProfile => self.app.push_navigation_stack(
(
ActiveRadarrBlock::AddMovieSelectQualityProfile,
*self.context,
)
.into(),
),
_ => (),
},
ActiveRadarrBlock::AddMovieSelectMonitor
@@ -298,6 +285,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
}
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
use pretty_assertions::assert_str_eq;
@@ -325,6 +313,7 @@ mod tests {
add_searched_movies,
simple_stateful_iterable_vec!(AddMovieSearchResult, HorizontallyScrollableText),
ActiveRadarrBlock::AddMovieSearchResults,
None,
title,
stationary_style
);
@@ -334,7 +323,8 @@ mod tests {
AddMovieHandler,
Monitor,
add_movie_monitor_list,
ActiveRadarrBlock::AddMovieSelectMonitor
ActiveRadarrBlock::AddMovieSelectMonitor,
None
);
test_enum_scroll!(
@@ -342,14 +332,16 @@ mod tests {
AddMovieHandler,
MinimumAvailability,
add_movie_minimum_availability_list,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
None
);
test_iterable_scroll!(
test_add_movie_select_quality_profile_scroll,
AddMovieHandler,
add_movie_quality_profile_list,
ActiveRadarrBlock::AddMovieSelectQualityProfile
ActiveRadarrBlock::AddMovieSelectQualityProfile,
None
);
#[rstest]
@@ -357,7 +349,7 @@ mod tests {
let mut app = App::default();
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieSelectMinimumAvailability;
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
if key == Key::Up {
assert_eq!(
@@ -388,6 +380,7 @@ mod tests {
add_searched_movies,
extended_stateful_iterable_vec!(AddMovieSearchResult, HorizontallyScrollableText),
ActiveRadarrBlock::AddMovieSearchResults,
None,
title,
stationary_style
);
@@ -397,7 +390,8 @@ mod tests {
AddMovieHandler,
Monitor,
add_movie_monitor_list,
ActiveRadarrBlock::AddMovieSelectMonitor
ActiveRadarrBlock::AddMovieSelectMonitor,
None
);
test_enum_home_and_end!(
@@ -405,14 +399,16 @@ mod tests {
AddMovieHandler,
MinimumAvailability,
add_movie_minimum_availability_list,
ActiveRadarrBlock::AddMovieSelectMinimumAvailability
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
None
);
test_iterable_home_and_end!(
test_add_movie_select_quality_profile_scroll,
AddMovieHandler,
add_movie_quality_profile_list,
ActiveRadarrBlock::AddMovieSelectQualityProfile
ActiveRadarrBlock::AddMovieSelectQualityProfile,
None
);
}
@@ -425,11 +421,11 @@ mod tests {
fn test_left_right_prompt_toggle(#[values(Key::Left, Key::Right)] key: Key) {
let mut app = App::default();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(&key, &mut app, &ActiveRadarrBlock::AddMoviePrompt, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
@@ -458,6 +454,7 @@ mod tests {
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
@@ -483,6 +480,7 @@ mod tests {
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
@@ -521,6 +519,7 @@ mod tests {
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
@@ -548,6 +547,7 @@ mod tests {
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
@@ -564,7 +564,13 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt;
AddMovieHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
@@ -578,7 +584,13 @@ mod tests {
app.data.radarr_data.prompt_confirm = true;
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt;
AddMovieHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_eq!(
@@ -597,12 +609,27 @@ mod tests {
selected_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
app.data.radarr_data.selected_block = selected_block;
AddMovieHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(app.get_current_route(), &selected_block.into());
assert_eq!(
app.get_current_route(),
&(selected_block, Some(ActiveRadarrBlock::CollectionDetails)).into()
);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
}
@@ -619,7 +646,13 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
AddMovieHandler::with(&SUBMIT_KEY, &mut app, &active_radarr_block).handle();
AddMovieHandler::with(
&SUBMIT_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
@@ -648,7 +681,13 @@ mod tests {
app.should_ignore_quit_key = true;
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
AddMovieHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::AddMovieSearchInput).handle();
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
assert!(!app.should_ignore_quit_key);
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
@@ -673,6 +712,7 @@ mod tests {
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieSearchResults,
&None,
)
.handle();
@@ -695,6 +735,7 @@ mod tests {
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMovieAlreadyInLibrary,
&None,
)
.handle();
@@ -711,7 +752,13 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
AddMovieHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::AddMoviePrompt,
&None,
)
.handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(
@@ -731,14 +778,36 @@ mod tests {
active_radarr_block: ActiveRadarrBlock,
) {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
app.push_navigation_stack(active_radarr_block.into());
app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
app.push_navigation_stack(
(
active_radarr_block,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
AddMovieHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::AddMoviePrompt).handle();
AddMovieHandler::with(
&ESC_KEY,
&mut app,
&active_radarr_block,
&Some(ActiveRadarrBlock::CollectionDetails),
)
.handle();
assert_eq!(
app.get_current_route(),
&ActiveRadarrBlock::AddMoviePrompt.into()
&(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into()
);
}
}
@@ -755,6 +824,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
@@ -769,6 +839,7 @@ mod tests {
&Key::Char('h'),
&mut app,
&ActiveRadarrBlock::AddMovieSearchInput,
&None,
)
.handle();
@@ -8,6 +8,7 @@ pub(super) struct CollectionDetailsHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_radarr_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>,
}
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for CollectionDetailsHandler<'a> {
@@ -15,11 +16,13 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for CollectionDetailsHandler<'a>
key: &'a Key,
app: &'a mut App,
active_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>,
) -> CollectionDetailsHandler<'a> {
CollectionDetailsHandler {
key,
app,
active_radarr_block: active_block,
_context,
}
}
@@ -62,9 +65,41 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for CollectionDetailsHandler<'a>
fn handle_submit(&mut self) {
if ActiveRadarrBlock::CollectionDetails == *self.active_radarr_block {
self
let tmdb_id = self
.app
.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into())
.data
.radarr_data
.collection_movies
.current_selection()
.tmdb_id
.clone();
if self
.app
.data
.radarr_data
.movies
.items
.iter()
.any(|movie| movie.tmdb_id == tmdb_id)
{
self
.app
.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into());
} else {
self.app.push_navigation_stack(
(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails),
)
.into(),
);
self
.app
.data
.radarr_data
.populate_add_movie_preferences_lists();
}
}
}
@@ -93,6 +128,7 @@ mod tests {
use crate::handlers::radarr_handlers::collection_details_handler::CollectionDetailsHandler;
use crate::handlers::KeyEventHandler;
use crate::models::radarr_models::CollectionMovie;
use crate::models::HorizontallyScrollableText;
mod test_handle_scroll_up_and_down {
use rstest::rstest;
@@ -105,9 +141,11 @@ mod tests {
test_collection_details_scroll,
CollectionDetailsHandler,
collection_movies,
CollectionMovie,
simple_stateful_iterable_vec!(CollectionMovie, HorizontallyScrollableText),
ActiveRadarrBlock::CollectionDetails,
title
None,
title,
stationary_style
);
}
@@ -120,15 +158,21 @@ mod tests {
test_collection_details_home_end,
CollectionDetailsHandler,
collection_movies,
CollectionMovie,
extended_stateful_iterable_vec!(CollectionMovie, HorizontallyScrollableText),
ActiveRadarrBlock::CollectionDetails,
title
None,
title,
stationary_style
);
}
mod test_handle_submit {
use std::collections::HashMap;
use pretty_assertions::assert_eq;
use crate::models::radarr_models::Movie;
use super::*;
const SUBMIT_KEY: Key = DEFAULT_KEYBINDINGS.submit.key;
@@ -136,10 +180,74 @@ mod tests {
#[test]
fn test_collection_details_submit() {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
app.data.radarr_data.quality_profile_map =
HashMap::from([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
CollectionDetailsHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::CollectionDetails)
.handle();
CollectionDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
&(
ActiveRadarrBlock::AddMoviePrompt,
Some(ActiveRadarrBlock::CollectionDetails)
)
.into()
);
assert!(!app.data.radarr_data.add_movie_monitor_list.items.is_empty());
assert!(!app
.data
.radarr_data
.add_movie_minimum_availability_list
.items
.is_empty());
assert!(!app
.data
.radarr_data
.add_movie_quality_profile_list
.items
.is_empty());
assert_str_eq!(
app
.data
.radarr_data
.add_movie_quality_profile_list
.current_selection(),
"A - Test 1"
);
}
#[test]
fn test_collection_details_submit_movie_already_in_library() {
let mut app = App::default();
app
.data
.radarr_data
.collection_movies
.set_items(vec![CollectionMovie::default()]);
app
.data
.radarr_data
.movies
.set_items(vec![Movie::default()]);
CollectionDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
@@ -166,8 +274,13 @@ mod tests {
.collection_movies
.set_items(vec![CollectionMovie::default()]);
CollectionDetailsHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::CollectionDetails)
.handle();
CollectionDetailsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::CollectionDetails,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
@@ -182,8 +295,13 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::CollectionDetails.into());
app.push_navigation_stack(ActiveRadarrBlock::ViewMovieOverview.into());
CollectionDetailsHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::ViewMovieOverview)
.handle();
CollectionDetailsHandler::with(
&ESC_KEY,
&mut app,
&ActiveRadarrBlock::ViewMovieOverview,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
+85 -22
View File
@@ -20,19 +20,22 @@ pub(super) struct RadarrHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_radarr_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>,
}
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
fn handle(&mut self) {
match self.active_radarr_block {
_ if MOVIE_DETAILS_BLOCKS.contains(self.active_radarr_block) => {
MovieDetailsHandler::with(self.key, self.app, self.active_radarr_block).handle()
MovieDetailsHandler::with(self.key, self.app, self.active_radarr_block, self.context)
.handle()
}
_ if COLLECTION_DETAILS_BLOCKS.contains(self.active_radarr_block) => {
CollectionDetailsHandler::with(self.key, self.app, self.active_radarr_block).handle()
CollectionDetailsHandler::with(self.key, self.app, self.active_radarr_block, self.context)
.handle()
}
_ if ADD_MOVIE_BLOCKS.contains(self.active_radarr_block) => {
AddMovieHandler::with(self.key, self.app, self.active_radarr_block).handle()
AddMovieHandler::with(self.key, self.app, self.active_radarr_block, self.context).handle()
}
_ => self.handle_key_event(),
}
@@ -42,11 +45,13 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_block: &'a ActiveRadarrBlock,
context: &'a Option<ActiveRadarrBlock>,
) -> RadarrHandler<'a> {
RadarrHandler {
key,
app,
active_radarr_block: active_block,
context,
}
}
@@ -536,6 +541,7 @@ mod tests {
collections,
Collection,
ActiveRadarrBlock::Collections,
None,
title
);
@@ -545,6 +551,7 @@ mod tests {
filtered_collections,
Collection,
ActiveRadarrBlock::Collections,
None,
title
);
@@ -554,6 +561,7 @@ mod tests {
movies,
Movie,
ActiveRadarrBlock::Movies,
None,
title
);
@@ -563,6 +571,7 @@ mod tests {
filtered_movies,
Movie,
ActiveRadarrBlock::Movies,
None,
title
);
@@ -572,6 +581,7 @@ mod tests {
downloads,
DownloadRecord,
ActiveRadarrBlock::Downloads,
None,
title
);
}
@@ -588,6 +598,7 @@ mod tests {
collections,
Collection,
ActiveRadarrBlock::Collections,
None,
title
);
@@ -597,6 +608,7 @@ mod tests {
filtered_collections,
Collection,
ActiveRadarrBlock::Collections,
None,
title
);
@@ -606,6 +618,7 @@ mod tests {
movies,
Movie,
ActiveRadarrBlock::Movies,
None,
title
);
@@ -615,6 +628,7 @@ mod tests {
filtered_movies,
Movie,
ActiveRadarrBlock::Movies,
None,
title
);
@@ -624,6 +638,7 @@ mod tests {
downloads,
DownloadRecord,
ActiveRadarrBlock::Downloads,
None,
title
);
}
@@ -639,7 +654,7 @@ mod tests {
fn test_movies_delete() {
let mut app = App::default();
RadarrHandler::with(&DELETE_KEY, &mut app, &ActiveRadarrBlock::Movies).handle();
RadarrHandler::with(&DELETE_KEY, &mut app, &ActiveRadarrBlock::Movies, &None).handle();
assert_eq!(
app.get_current_route(),
@@ -651,7 +666,7 @@ mod tests {
fn test_downloads_delete() {
let mut app = App::default();
RadarrHandler::with(&DELETE_KEY, &mut app, &ActiveRadarrBlock::Downloads).handle();
RadarrHandler::with(&DELETE_KEY, &mut app, &ActiveRadarrBlock::Downloads, &None).handle();
assert_eq!(
app.get_current_route(),
@@ -682,6 +697,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.left.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -708,6 +724,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.right.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -732,11 +749,11 @@ mod tests {
) {
let mut app = App::default();
RadarrHandler::with(&key, &mut app, &active_radarr_block).handle();
RadarrHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
RadarrHandler::with(&key, &mut app, &active_radarr_block).handle();
RadarrHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
@@ -761,7 +778,7 @@ mod tests {
) {
let mut app = App::default();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &active_radarr_block).handle();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &expected_radarr_block.into());
}
@@ -776,7 +793,13 @@ mod tests {
.set_items(extended_stateful_iterable_vec!(Movie));
app.data.radarr_data.search = "Test 2".to_owned();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::SearchMovie).handle();
RadarrHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::SearchMovie,
&None,
)
.handle();
assert_str_eq!(
app.data.radarr_data.movies.current_selection().title,
@@ -794,7 +817,13 @@ mod tests {
.set_items(extended_stateful_iterable_vec!(Movie));
app.data.radarr_data.search = "Test 2".to_owned();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::SearchMovie).handle();
RadarrHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::SearchMovie,
&None,
)
.handle();
assert_str_eq!(
app
@@ -817,7 +846,13 @@ mod tests {
.set_items(extended_stateful_iterable_vec!(Collection));
app.data.radarr_data.search = "Test 2".to_owned();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::SearchCollection).handle();
RadarrHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::SearchCollection,
&None,
)
.handle();
assert_str_eq!(
app.data.radarr_data.collections.current_selection().title,
@@ -835,7 +870,13 @@ mod tests {
.set_items(extended_stateful_iterable_vec!(Collection));
app.data.radarr_data.search = "Test 2".to_owned();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::SearchCollection).handle();
RadarrHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::SearchCollection,
&None,
)
.handle();
assert_str_eq!(
app
@@ -858,7 +899,13 @@ mod tests {
.set_items(extended_stateful_iterable_vec!(Movie));
app.data.radarr_data.filter = "Test".to_owned();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::FilterMovies).handle();
RadarrHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::FilterMovies,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.filtered_movies.items.len(), 3);
assert_str_eq!(
@@ -882,7 +929,13 @@ mod tests {
.set_items(extended_stateful_iterable_vec!(Collection));
app.data.radarr_data.filter = "Test".to_owned();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::FilterCollections).handle();
RadarrHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::FilterCollections,
&None,
)
.handle();
assert_eq!(app.data.radarr_data.filtered_collections.items.len(), 3);
assert_str_eq!(
@@ -932,7 +985,7 @@ mod tests {
app.push_navigation_stack(base_route.into());
app.push_navigation_stack(prompt_block.into());
RadarrHandler::with(&SUBMIT_KEY, &mut app, &prompt_block).handle();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
assert_eq!(
@@ -962,7 +1015,7 @@ mod tests {
app.push_navigation_stack(base_route.into());
app.push_navigation_stack(prompt_block.into());
RadarrHandler::with(&SUBMIT_KEY, &mut app, &prompt_block).handle();
RadarrHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
@@ -994,7 +1047,7 @@ mod tests {
app.push_navigation_stack(search_block.into());
app.data.radarr_data = create_test_radarr_data();
RadarrHandler::with(&ESC_KEY, &mut app, &search_block).handle();
RadarrHandler::with(&ESC_KEY, &mut app, &search_block, &None).handle();
assert_eq!(app.get_current_route(), &base_block.into());
assert!(!app.should_ignore_quit_key);
@@ -1014,7 +1067,7 @@ mod tests {
app.push_navigation_stack(filter_block.into());
app.data.radarr_data = create_test_radarr_data();
RadarrHandler::with(&ESC_KEY, &mut app, &filter_block).handle();
RadarrHandler::with(&ESC_KEY, &mut app, &filter_block, &None).handle();
assert_eq!(app.get_current_route(), &base_block.into());
assert!(!app.should_ignore_quit_key);
@@ -1042,7 +1095,7 @@ mod tests {
app.push_navigation_stack(prompt_block.into());
app.data.radarr_data.prompt_confirm = true;
RadarrHandler::with(&ESC_KEY, &mut app, &prompt_block).handle();
RadarrHandler::with(&ESC_KEY, &mut app, &prompt_block, &None).handle();
assert_eq!(app.get_current_route(), &base_block.into());
assert!(!app.data.radarr_data.prompt_confirm);
@@ -1056,7 +1109,7 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::Downloads.into());
app.data.radarr_data = create_test_radarr_data();
RadarrHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::Downloads).handle();
RadarrHandler::with(&ESC_KEY, &mut app, &ActiveRadarrBlock::Downloads, &None).handle();
assert_eq!(
app.get_current_route(),
@@ -1089,6 +1142,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.search.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -1110,6 +1164,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.filter.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -1126,6 +1181,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.add.key,
&mut app,
&ActiveRadarrBlock::Movies,
&None,
)
.handle();
@@ -1156,6 +1212,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.refresh.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -1174,6 +1231,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -1192,6 +1250,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.backspace.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -1205,7 +1264,7 @@ mod tests {
) {
let mut app = App::default();
RadarrHandler::with(&Key::Char('h'), &mut app, &active_radarr_block).handle();
RadarrHandler::with(&Key::Char('h'), &mut app, &active_radarr_block, &None).handle();
assert_str_eq!(app.data.radarr_data.search, "h");
}
@@ -1217,7 +1276,7 @@ mod tests {
) {
let mut app = App::default();
RadarrHandler::with(&Key::Char('h'), &mut app, &active_radarr_block).handle();
RadarrHandler::with(&Key::Char('h'), &mut app, &active_radarr_block, &None).handle();
assert_str_eq!(app.data.radarr_data.filter, "h");
}
@@ -1242,6 +1301,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.submit.key,
&mut app,
&ActiveRadarrBlock::SearchMovie,
&None,
)
.search_table(movies, |movie| &movie.title);
@@ -1271,6 +1331,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.submit.key,
&mut app,
&ActiveRadarrBlock::SearchMovie,
&None,
)
.search_table(movies, |movie| &movie.title);
@@ -1303,6 +1364,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.submit.key,
&mut app,
&ActiveRadarrBlock::FilterMovies,
&None,
)
.filter_table(movies, |movie| &movie.title);
@@ -1333,6 +1395,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.submit.key,
&mut app,
&ActiveRadarrBlock::FilterMovies,
&None,
)
.filter_table(movies, |movie| &movie.title);
@@ -16,6 +16,7 @@ pub(super) struct MovieDetailsHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_radarr_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>,
}
impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
@@ -23,11 +24,13 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
key: &'a Key,
app: &'a mut App,
active_block: &'a ActiveRadarrBlock,
_context: &'a Option<ActiveRadarrBlock>,
) -> MovieDetailsHandler<'a> {
MovieDetailsHandler {
key,
app,
active_radarr_block: active_block,
_context,
}
}
@@ -317,6 +320,7 @@ fn sort_releases_by_selected_field(
}
#[cfg(test)]
#[allow(unused_imports)]
mod tests {
use pretty_assertions::assert_str_eq;
use rstest::rstest;
@@ -354,6 +358,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.up.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
@@ -363,6 +368,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.down.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
@@ -375,6 +381,7 @@ mod tests {
movie_history,
simple_stateful_iterable_vec!(MovieHistoryItem, HorizontallyScrollableText, source_title),
ActiveRadarrBlock::MovieHistory,
None,
source_title,
stationary_style
);
@@ -385,6 +392,7 @@ mod tests {
movie_cast,
simple_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Cast,
None,
person_name,
to_owned
);
@@ -395,6 +403,7 @@ mod tests {
movie_crew,
simple_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Crew,
None,
person_name,
to_owned
);
@@ -405,6 +414,7 @@ mod tests {
movie_releases,
simple_stateful_iterable_vec!(Release, HorizontallyScrollableText),
ActiveRadarrBlock::ManualSearch,
None,
title,
stationary_style
);
@@ -414,7 +424,8 @@ mod tests {
MovieDetailsHandler,
ReleaseField,
movie_releases_sort,
ActiveRadarrBlock::ManualSearchSortPrompt
ActiveRadarrBlock::ManualSearchSortPrompt,
None
);
}
@@ -437,6 +448,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.end.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
@@ -446,6 +458,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.home.key,
&mut app,
&ActiveRadarrBlock::MovieDetails,
&None,
)
.handle();
@@ -458,6 +471,7 @@ mod tests {
movie_history,
extended_stateful_iterable_vec!(MovieHistoryItem, HorizontallyScrollableText, source_title),
ActiveRadarrBlock::MovieHistory,
None,
source_title,
stationary_style
);
@@ -468,6 +482,7 @@ mod tests {
movie_cast,
extended_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Cast,
None,
person_name,
to_owned
);
@@ -478,6 +493,7 @@ mod tests {
movie_crew,
extended_stateful_iterable_vec!(Credit, String, person_name),
ActiveRadarrBlock::Crew,
None,
person_name,
to_owned
);
@@ -488,6 +504,7 @@ mod tests {
movie_releases,
extended_stateful_iterable_vec!(Release, HorizontallyScrollableText),
ActiveRadarrBlock::ManualSearch,
None,
title,
stationary_style
);
@@ -497,7 +514,8 @@ mod tests {
MovieDetailsHandler,
ReleaseField,
movie_releases_sort,
ActiveRadarrBlock::ManualSearchSortPrompt
ActiveRadarrBlock::ManualSearchSortPrompt,
None
);
}
@@ -519,11 +537,11 @@ mod tests {
) {
let mut app = App::default();
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block).handle();
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block).handle();
MovieDetailsHandler::with(&key, &mut app, &active_radarr_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
}
@@ -550,7 +568,8 @@ mod tests {
.position(|tab_route| tab_route.route == right_block.into())
.unwrap_or_default();
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.left.key, &mut app, &right_block).handle();
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.left.key, &mut app, &right_block, &None)
.handle();
assert_eq!(
app.get_current_route(),
@@ -558,7 +577,8 @@ mod tests {
);
assert_eq!(app.get_current_route(), &left_block.into());
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.right.key, &mut app, &left_block).handle();
MovieDetailsHandler::with(&DEFAULT_KEYBINDINGS.right.key, &mut app, &left_block, &None)
.handle();
assert_eq!(
app.get_current_route(),
@@ -584,7 +604,13 @@ mod tests {
let mut app = App::default();
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &ActiveRadarrBlock::ManualSearch).handle();
MovieDetailsHandler::with(
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::ManualSearch,
&None,
)
.handle();
assert_eq!(
app.get_current_route(),
@@ -611,7 +637,7 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block).handle();
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(app.data.radarr_data.prompt_confirm);
assert_eq!(
@@ -637,7 +663,7 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::MovieDetails.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block).handle();
MovieDetailsHandler::with(&SUBMIT_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(
@@ -667,6 +693,7 @@ mod tests {
&SUBMIT_KEY,
&mut app,
&ActiveRadarrBlock::ManualSearchSortPrompt,
&None,
)
.handle();
@@ -706,7 +733,7 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(active_radarr_block.into());
MovieDetailsHandler::with(&ESC_KEY, &mut app, &active_radarr_block).handle();
MovieDetailsHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
assert_movie_info_tabs_reset!(app.data.radarr_data);
@@ -727,7 +754,7 @@ mod tests {
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
app.push_navigation_stack(prompt_block.into());
MovieDetailsHandler::with(&ESC_KEY, &mut app, &prompt_block).handle();
MovieDetailsHandler::with(&ESC_KEY, &mut app, &prompt_block, &None).handle();
assert!(!app.data.radarr_data.prompt_confirm);
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
@@ -758,6 +785,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.search.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
@@ -775,6 +803,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.sort.key,
&mut app,
&ActiveRadarrBlock::ManualSearch,
&None,
)
.handle();
@@ -805,6 +834,7 @@ mod tests {
&DEFAULT_KEYBINDINGS.refresh.key,
&mut app,
&active_radarr_block,
&None,
)
.handle();
+1 -1
View File
@@ -10,7 +10,7 @@ pub mod radarr_models;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Route {
Radarr(ActiveRadarrBlock),
Radarr(ActiveRadarrBlock, Option<ActiveRadarrBlock>),
Sonarr,
Readarr,
Lidarr,
+3 -1
View File
@@ -65,12 +65,14 @@ pub struct Movie {
#[derivative(Default)]
#[serde(rename_all = "camelCase")]
pub struct CollectionMovie {
pub title: String,
pub title: HorizontallyScrollableText,
pub overview: String,
#[derivative(Default(value = "Number::from(0)"))]
pub year: Number,
#[derivative(Default(value = "Number::from(0)"))]
pub runtime: Number,
#[derivative(Default(value = "Number::from(0)"))]
pub tmdb_id: Number,
pub genres: Vec<String>,
pub ratings: RatingsList,
}
+4 -1
View File
@@ -952,6 +952,7 @@ mod test {
"overview": "Collection blah blah blah",
"year": 2023,
"runtime": 120,
"tmdbId": 1234,
"genres": ["cool", "family", "fun"],
"ratings": {
"imdb": {
@@ -1587,6 +1588,7 @@ mod test {
"overview": "Collection blah blah blah",
"year": 2023,
"runtime": 120,
"tmdbId": 1234,
"genres": ["cool", "family", "fun"],
"ratings": {
"imdb": {
@@ -2128,10 +2130,11 @@ mod test {
fn collection_movie() -> CollectionMovie {
CollectionMovie {
title: "Test".to_owned(),
title: "Test".to_owned().into(),
overview: "Collection blah blah blah".to_owned(),
year: Number::from(2023),
runtime: Number::from(120),
tmdb_id: Number::from(1234),
genres: genres(),
ratings: ratings_list(),
}
+2 -2
View File
@@ -56,7 +56,7 @@ pub fn ui<B: Backend>(f: &mut Frame<B>, app: &mut App) {
draw_header_row(f, app, main_chunks[0]);
draw_context_row(f, app, main_chunks[1]);
if let Route::Radarr(_) = app.get_current_route() {
if let Route::Radarr(_, _) = app.get_current_route() {
radarr_ui::draw_radarr_ui(f, app, main_chunks[2])
}
}
@@ -173,7 +173,7 @@ pub fn draw_drop_down_popup<B: Backend>(
}
fn draw_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &App, area: Rect) {
if let Route::Radarr(_) = app.get_current_route() {
if let Route::Radarr(_, _) = app.get_current_route() {
radarr_ui::draw_radarr_context_row(f, app, area)
}
}
+56 -25
View File
@@ -7,8 +7,9 @@ use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::models::radarr_models::AddMovieSearchResult;
use crate::models::Route;
use crate::ui::radarr_ui::collection_details_ui::draw_collection_details;
use crate::ui::utils::{
borderless_block, get_width_with_margin, horizontal_chunks, layout_block,
borderless_block, get_width_from_percentage, horizontal_chunks, layout_block,
layout_paragraph_borderless, show_cursor, style_default, style_help, style_primary,
title_block_centered, vertical_chunks_with_margin,
};
@@ -24,7 +25,7 @@ pub(super) fn draw_add_movie_search_popup<B: Backend>(
app: &mut App,
area: Rect,
) {
if let Route::Radarr(active_radarr_block) = *app.get_current_route() {
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::AddMovieSearchInput | ActiveRadarrBlock::AddMovieSearchResults => {
draw_add_movie_search(f, app, area);
@@ -33,7 +34,17 @@ pub(super) fn draw_add_movie_search_popup<B: Backend>(
| ActiveRadarrBlock::AddMovieSelectMonitor
| ActiveRadarrBlock::AddMovieSelectMinimumAvailability
| ActiveRadarrBlock::AddMovieSelectQualityProfile => {
draw_medium_popup_over(f, app, area, draw_add_movie_search, draw_confirmation_popup);
if context_option.is_some() {
draw_medium_popup_over(
f,
app,
area,
draw_collection_details,
draw_confirmation_popup,
);
} else {
draw_medium_popup_over(f, app, area, draw_add_movie_search, draw_confirmation_popup);
}
}
ActiveRadarrBlock::AddMovieAlreadyInLibrary => draw_error_popup_over(
f,
@@ -73,7 +84,7 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
.style(style_default())
.block(title_block_centered("Add Movie"));
if let Route::Radarr(active_radarr_block) = *app.get_current_route() {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::AddMovieSearchInput => {
show_cursor(f, chunks[0], block_content);
@@ -173,9 +184,10 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
""
};
movie
.title
.scroll_or_reset(get_width_with_margin(area), *movie == current_selection);
movie.title.scroll_or_reset(
get_width_from_percentage(area, 27),
*movie == current_selection,
);
Row::new(vec![
Cell::from(in_library),
@@ -200,7 +212,7 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
}
fn draw_confirmation_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) {
if let Route::Radarr(active_radarr_block) = *app.get_current_route() {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::AddMovieSelectMonitor => {
draw_drop_down_popup(
@@ -272,23 +284,42 @@ fn draw_select_quality_profile_popup<B: Backend>(
fn draw_confirmation_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) {
let title = "Add Movie";
let prompt = format!(
"{}:\n\n{}",
app
.data
.radarr_data
.add_searched_movies
.current_selection()
.title
.to_string()
.trim(),
app
.data
.radarr_data
.add_searched_movies
.current_selection()
.overview
);
let (movie_title, movie_overview) = if let Route::Radarr(_, Some(_)) = app.get_current_route() {
(
app
.data
.radarr_data
.collection_movies
.current_selection()
.title
.to_string(),
app
.data
.radarr_data
.collection_movies
.current_selection()
.overview
.clone(),
)
} else {
(
app
.data
.radarr_data
.add_searched_movies
.current_selection()
.title
.stationary_style(),
app
.data
.radarr_data
.add_searched_movies
.current_selection()
.overview
.clone(),
)
};
let prompt = format!("{}:\n\n{}", movie_title, movie_overview);
let yes_no_value = &app.data.radarr_data.prompt_confirm;
let selected_block = &app.data.radarr_data.selected_block;
let highlight_yes_no = *selected_block == ActiveRadarrBlock::AddMovieConfirmPrompt;
+42 -7
View File
@@ -6,10 +6,12 @@ use tui::Frame;
use crate::app::radarr::ActiveRadarrBlock;
use crate::app::App;
use crate::models::radarr_models::CollectionMovie;
use crate::models::Route;
use crate::ui::utils::{
borderless_block, layout_block_top_border_with_title, spans_info_primary, style_default,
style_help, style_primary, title_block, title_style, vertical_chunks_with_margin,
borderless_block, get_width_from_percentage, layout_block_top_border_with_title,
spans_info_primary, style_default, style_help, style_primary, title_block, title_style,
vertical_chunks_with_margin,
};
use crate::ui::{draw_small_popup_over, draw_table, TableProps};
use crate::utils::convert_runtime;
@@ -19,7 +21,7 @@ pub(super) fn draw_collection_details_popup<B: Backend>(
app: &mut App,
content_area: Rect,
) {
if let Route::Radarr(active_radarr_block) = app.get_current_route() {
if let Route::Radarr(active_radarr_block, _) = app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::ViewMovieOverview => {
draw_small_popup_over(
@@ -36,7 +38,11 @@ pub(super) fn draw_collection_details_popup<B: Backend>(
}
}
fn draw_collection_details<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) {
pub(super) fn draw_collection_details<B: Backend>(
f: &mut Frame<'_, B>,
app: &mut App,
content_area: Rect,
) {
let chunks = vertical_chunks_with_margin(
vec![
Constraint::Percentage(20),
@@ -62,7 +68,17 @@ fn draw_collection_details<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, cont
.get(&collection_selection.quality_profile_id.as_u64().unwrap())
.unwrap()
.to_owned();
let mut help_text = Text::from("<↑↓> scroll table | <enter> show overview | <esc> close");
let current_selection = if app.data.radarr_data.collection_movies.items.is_empty() {
CollectionMovie::default()
} else {
app
.data
.radarr_data
.collection_movies
.current_selection_clone()
};
let mut help_text =
Text::from("<↑↓> scroll table | <enter> show overview/add movie | <esc> close");
help_text.patch_style(style_help());
let collection_description = Text::from(vec![
@@ -103,6 +119,7 @@ fn draw_collection_details<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, cont
TableProps {
content: &mut app.data.radarr_data.collection_movies,
table_headers: vec![
"",
"Title",
"Year",
"Runtime",
@@ -111,16 +128,33 @@ fn draw_collection_details<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, cont
"Genres",
],
constraints: vec![
Constraint::Percentage(2),
Constraint::Percentage(20),
Constraint::Percentage(8),
Constraint::Percentage(10),
Constraint::Percentage(10),
Constraint::Percentage(18),
Constraint::Percentage(30),
Constraint::Percentage(28),
],
help: None,
},
|movie| {
let in_library = if app
.data
.radarr_data
.movies
.items
.iter()
.any(|mov| mov.tmdb_id == movie.tmdb_id)
{
""
} else {
""
};
movie.title.scroll_or_reset(
get_width_from_percentage(chunks[1], 20),
current_selection == *movie,
);
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
let imdb_rating = movie
.ratings
@@ -150,7 +184,8 @@ fn draw_collection_details<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, cont
};
Row::new(vec![
Cell::from(movie.title.to_owned()),
Cell::from(in_library),
Cell::from(movie.title.to_string()),
Cell::from(movie.year.as_u64().unwrap().to_string()),
Cell::from(format!("{}h {}m", hours, minutes)),
Cell::from(imdb_rating),
+26 -14
View File
@@ -21,7 +21,7 @@ use crate::ui::radarr_ui::add_movie_ui::draw_add_movie_search_popup;
use crate::ui::radarr_ui::collection_details_ui::draw_collection_details_popup;
use crate::ui::radarr_ui::movie_details_ui::draw_movie_info_popup;
use crate::ui::utils::{
borderless_block, get_width_with_margin, horizontal_chunks, layout_block,
borderless_block, get_width_from_percentage, horizontal_chunks, layout_block,
layout_block_top_border, line_gauge_with_label, line_gauge_with_title, show_cursor, style_bold,
style_default, style_failure, style_primary, style_success, style_warning, title_block,
title_block_centered, vertical_chunks_with_margin,
@@ -39,7 +39,7 @@ mod movie_details_ui;
pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
let (content_rect, _) = draw_tabs(f, area, "Movies", &app.data.radarr_data.main_tabs);
if let Route::Radarr(active_radarr_block) = *app.get_current_route() {
if let Route::Radarr(active_radarr_block, _) = *app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::Movies => draw_library(f, app, content_rect),
ActiveRadarrBlock::SearchMovie => {
@@ -71,13 +71,25 @@ pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, ar
_ if MOVIE_DETAILS_BLOCKS.contains(&active_radarr_block) => {
draw_large_popup_over(f, app, content_rect, draw_library, draw_movie_info_popup)
}
_ if ADD_MOVIE_BLOCKS.contains(&active_radarr_block) => draw_large_popup_over(
f,
app,
content_rect,
draw_library,
draw_add_movie_search_popup,
),
_ if ADD_MOVIE_BLOCKS.contains(&active_radarr_block) => {
if let Route::Radarr(_, Some(_)) = app.get_current_route() {
draw_large_popup_over(
f,
app,
content_rect,
draw_collections,
draw_add_movie_search_popup,
)
} else {
draw_large_popup_over(
f,
app,
content_rect,
draw_library,
draw_add_movie_search_popup,
)
}
}
_ if COLLECTION_DETAILS_BLOCKS.contains(&active_radarr_block) => draw_large_popup_over(
f,
app,
@@ -269,7 +281,7 @@ fn draw_search_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1);
if !app.data.radarr_data.is_searching {
let error_msg = match app.get_current_route() {
Route::Radarr(active_radarr_block) => match active_radarr_block {
Route::Radarr(active_radarr_block, _) => match active_radarr_block {
ActiveRadarrBlock::SearchMovie => "Movie not found!",
ActiveRadarrBlock::SearchCollection => "Collection not found!",
_ => "",
@@ -284,7 +296,7 @@ fn draw_search_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
f.render_widget(input, chunks[0]);
} else {
let (block_title, block_content) = match app.get_current_route() {
Route::Radarr(active_radarr_block) => match active_radarr_block {
Route::Radarr(active_radarr_block, _) => match active_radarr_block {
_ if SEARCH_BLOCKS.contains(active_radarr_block) => {
("Search", app.data.radarr_data.search.as_str())
}
@@ -307,7 +319,7 @@ fn draw_filter_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1);
if !app.data.radarr_data.is_filtering {
let error_msg = match app.get_current_route() {
Route::Radarr(active_radarr_block) => match active_radarr_block {
Route::Radarr(active_radarr_block, _) => match active_radarr_block {
ActiveRadarrBlock::FilterMovies => "No movies found matching filter!",
ActiveRadarrBlock::FilterCollections => "No collections found matching filter!",
_ => "",
@@ -322,7 +334,7 @@ fn draw_filter_box<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
f.render_widget(input, chunks[0]);
} else {
let (block_title, block_content) = match app.get_current_route() {
Route::Radarr(active_radarr_block) => match active_radarr_block {
Route::Radarr(active_radarr_block, _) => match active_radarr_block {
_ if FILTER_BLOCKS.contains(active_radarr_block) => {
("Filter", app.data.radarr_data.filter.as_str())
}
@@ -418,7 +430,7 @@ fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
let path = output_path.clone().unwrap_or_default();
path.scroll_or_reset(
get_width_with_margin(area),
get_width_from_percentage(area, 18),
current_selection == *download_record,
);
+8 -12
View File
@@ -12,7 +12,7 @@ use crate::app::App;
use crate::models::radarr_models::{Credit, MovieHistoryItem, Release, ReleaseField};
use crate::models::Route;
use crate::ui::utils::{
borderless_block, get_width_with_margin, layout_block_bottom_border, layout_block_top_border,
borderless_block, get_width_from_percentage, layout_block_bottom_border, layout_block_top_border,
spans_info_default, style_bold, style_default, style_failure, style_primary, style_success,
style_warning, vertical_chunks,
};
@@ -25,7 +25,7 @@ use crate::utils::convert_to_gb;
pub(super) fn draw_movie_info_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
let (content_area, _) = draw_tabs(f, area, "Movie Info", &app.data.radarr_data.movie_info_tabs);
if let Route::Radarr(active_radarr_block) = app.get_current_route() {
if let Route::Radarr(active_radarr_block, _) = app.get_current_route() {
match active_radarr_block {
ActiveRadarrBlock::AutomaticallySearchMoviePrompt => draw_prompt_popup_over(
f,
@@ -68,7 +68,7 @@ pub(super) fn draw_movie_info_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut
}
fn draw_movie_info<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
if let Route::Radarr(active_radarr_block) =
if let Route::Radarr(active_radarr_block, _) =
app.data.radarr_data.movie_info_tabs.get_active_route()
{
match active_radarr_block {
@@ -258,14 +258,10 @@ fn draw_movie_history<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_a
event_type,
} = movie_history_item;
if current_selection == *movie_history_item
&& movie_history_item.source_title.text.len()
> (content_area.width as f64 * 0.34) as usize
{
source_title.scroll_text();
} else {
source_title.reset_offset();
}
movie_history_item.source_title.scroll_or_reset(
get_width_from_percentage(content_area, 34),
current_selection == *movie_history_item,
);
Row::new(vec![
Cell::from(source_title.to_string()),
@@ -432,7 +428,7 @@ fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_
} = release;
let age = format!("{} days", age.as_u64().unwrap_or(0));
title.scroll_or_reset(
get_width_with_margin(content_area),
get_width_from_percentage(content_area, 30),
current_selection == *release
&& current_route != ActiveRadarrBlock::ManualSearchConfirmPrompt.into(),
);
+13 -10
View File
@@ -241,8 +241,8 @@ pub fn show_cursor<B: Backend>(f: &mut Frame<'_, B>, area: Rect, string: &str) {
f.set_cursor(area.x + string.len() as u16 + 1, area.y + 1);
}
pub fn get_width_with_margin(area: Rect) -> usize {
(area.width as f32 * 0.30) as usize
pub fn get_width_from_percentage(area: Rect, percentage: u16) -> usize {
(area.width as f64 * (percentage as f64 / 100.0)) as usize
}
#[cfg(test)]
@@ -254,7 +254,7 @@ mod test {
use tui::widgets::{Block, BorderType, Borders};
use crate::ui::utils::{
borderless_block, centered_rect, get_width_with_margin, horizontal_chunks,
borderless_block, centered_rect, get_width_from_percentage, horizontal_chunks,
horizontal_chunks_with_margin, layout_block, layout_block_bottom_border,
layout_block_top_border, layout_block_top_border_with_title, layout_block_with_title,
layout_with_constraints, logo_block, spans_info_default, spans_info_primary,
@@ -625,14 +625,17 @@ mod test {
}
#[test]
fn test_get_width_with_margin() {
fn test_get_width_from_percentage() {
assert_eq!(
get_width_with_margin(Rect {
x: 0,
y: 0,
width: 100,
height: 10
}),
get_width_from_percentage(
Rect {
x: 0,
y: 0,
width: 100,
height: 10
},
30
),
30
);
}